Transitioned from Main to ContextAware.
This commit is contained in:
@@ -1,54 +0,0 @@
|
|||||||
package me.trouper.alias;
|
|
||||||
|
|
||||||
import me.trouper.alias.data.Common;
|
|
||||||
import me.trouper.alias.server.AutoRegistrar;
|
|
||||||
import me.trouper.alias.server.commands.QuickCommand;
|
|
||||||
import me.trouper.alias.server.events.GuiListener;
|
|
||||||
import me.trouper.alias.server.events.QuickListener;
|
|
||||||
import me.trouper.alias.update.AutoUpdater;
|
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
|
||||||
|
|
||||||
public final class Alias extends JavaPlugin {
|
|
||||||
|
|
||||||
private static Class<? extends JavaPlugin> host;
|
|
||||||
private static AutoRegistrar autoRegistrar;
|
|
||||||
private static Common common;
|
|
||||||
private static boolean enabled;
|
|
||||||
|
|
||||||
|
|
||||||
public static synchronized void register(JavaPlugin plugin, Common common) {
|
|
||||||
if (plugin == null || enabled) return;
|
|
||||||
Alias.host = plugin.getClass();
|
|
||||||
Alias.common = common;
|
|
||||||
|
|
||||||
AutoUpdater.checkUpdate(plugin,common);
|
|
||||||
|
|
||||||
autoRegistrar = new AutoRegistrar(plugin);
|
|
||||||
autoRegistrar.getQuickListeners().add(new GuiListener());
|
|
||||||
autoRegistrar.loadAll(common.getPackageName());
|
|
||||||
|
|
||||||
enabled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static synchronized void stop(JavaPlugin plugin, Common common) {
|
|
||||||
autoRegistrar.getQuickListeners().forEach(QuickListener::unregister);
|
|
||||||
autoRegistrar.getQuickCommands().forEach(QuickCommand::disable);
|
|
||||||
AutoUpdater.checkUpdate(plugin,common);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Class<? extends JavaPlugin> getHost() {
|
|
||||||
return host;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AutoRegistrar getAutoRegistrar() {
|
|
||||||
return autoRegistrar;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Common getCommon() {
|
|
||||||
return common;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void updateCommon(Common common) {
|
|
||||||
Alias.common = common;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
99
src/main/java/me/trouper/alias/AliasContext.java
Normal file
99
src/main/java/me/trouper/alias/AliasContext.java
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
package me.trouper.alias;
|
||||||
|
|
||||||
|
import me.trouper.alias.data.Common;
|
||||||
|
import me.trouper.alias.data.DataManager;
|
||||||
|
import me.trouper.alias.data.JsonSerializable;
|
||||||
|
import me.trouper.alias.server.AutoRegistrar;
|
||||||
|
import me.trouper.alias.server.events.listeners.GuiListener;
|
||||||
|
import me.trouper.alias.server.events.listeners.SpawnListener;
|
||||||
|
import me.trouper.alias.server.events.listeners.WandListener;
|
||||||
|
import me.trouper.alias.server.systems.TaskManager;
|
||||||
|
import me.trouper.alias.server.systems.Text;
|
||||||
|
import me.trouper.alias.server.systems.Verbose;
|
||||||
|
import me.trouper.alias.server.systems.display.DisplayManager;
|
||||||
|
import me.trouper.alias.server.update.AutoUpdater;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class AliasContext {
|
||||||
|
private final JavaPlugin plugin;
|
||||||
|
private final Common common;
|
||||||
|
private final AutoRegistrar autoRegistrar;
|
||||||
|
private final AutoUpdater autoUpdater;
|
||||||
|
private final DataManager dataManager;
|
||||||
|
private final Text text;
|
||||||
|
private final Verbose verbose;
|
||||||
|
private final DisplayManager displayManager;
|
||||||
|
private boolean enabled = false;
|
||||||
|
|
||||||
|
public AliasContext(JavaPlugin plugin, Common common) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.common = common;
|
||||||
|
this.autoRegistrar = new AutoRegistrar(this);
|
||||||
|
this.autoUpdater = new AutoUpdater(this);
|
||||||
|
this.dataManager = new DataManager(this);
|
||||||
|
this.text = new Text(this);
|
||||||
|
this.verbose = new Verbose(this);
|
||||||
|
this.displayManager = new DisplayManager(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the Alias context and register all components.
|
||||||
|
* This must be called before using any Alias features.
|
||||||
|
* Alias should be registered first.
|
||||||
|
* See {@link AliasContextProvider#registerContext(JavaPlugin, AliasContext)}
|
||||||
|
*/
|
||||||
|
public synchronized void initialize() {
|
||||||
|
if (enabled) return;
|
||||||
|
|
||||||
|
plugin.getLogger().info("Initializing Alias context for " + plugin.getName());
|
||||||
|
|
||||||
|
autoUpdater.checkUpdate();
|
||||||
|
|
||||||
|
autoRegistrar.loadAll(common.getPackageName());
|
||||||
|
Bukkit.getPluginManager().registerEvents(new GuiListener(),getPlugin());
|
||||||
|
Bukkit.getPluginManager().registerEvents(new SpawnListener(this),getPlugin());
|
||||||
|
Bukkit.getPluginManager().registerEvents(new WandListener(this),getPlugin());
|
||||||
|
List<JsonSerializable<?>> copy = new ArrayList<>(autoRegistrar.getSerializables());
|
||||||
|
for (JsonSerializable<?> serializable : copy) {
|
||||||
|
dataManager.load(serializable.getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
enabled = true;
|
||||||
|
plugin.getLogger().info("Alias context initialized successfully");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shutdown the Alias context, save any {@link me.trouper.alias.data.JsonSerializable} and release resources.
|
||||||
|
* This should be called when the plugin is shutting down.
|
||||||
|
*/
|
||||||
|
public synchronized void shutdown() {
|
||||||
|
if (!enabled) return;
|
||||||
|
|
||||||
|
plugin.getLogger().info("Shutting down Alias context for " + plugin.getName());
|
||||||
|
|
||||||
|
autoRegistrar.getSerializables().forEach(jsonSerializable -> {
|
||||||
|
dataManager.save(jsonSerializable.getClass());
|
||||||
|
});
|
||||||
|
autoRegistrar.unregisterAll();
|
||||||
|
|
||||||
|
autoUpdater.checkUpdate();
|
||||||
|
|
||||||
|
enabled = false;
|
||||||
|
plugin.getLogger().info("Alias context shutdown complete");
|
||||||
|
}
|
||||||
|
|
||||||
|
public JavaPlugin getPlugin() { return plugin; }
|
||||||
|
public Common getCommon() { return common; }
|
||||||
|
public AutoRegistrar getAutoRegistrar() { return autoRegistrar; }
|
||||||
|
public Text getText() { return text; }
|
||||||
|
public boolean isEnabled() { return enabled; }
|
||||||
|
public TaskManager createTaskManager() { return new TaskManager(this); }
|
||||||
|
public Verbose getVerbose() { return verbose; }
|
||||||
|
public DisplayManager getDisplayManager() { return displayManager; }
|
||||||
|
public DataManager getDataManager() { return dataManager; }
|
||||||
|
public AutoUpdater getAutoUpdater() { return autoUpdater; }
|
||||||
|
}
|
||||||
44
src/main/java/me/trouper/alias/AliasContextProvider.java
Normal file
44
src/main/java/me/trouper/alias/AliasContextProvider.java
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
package me.trouper.alias;
|
||||||
|
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
public class AliasContextProvider {
|
||||||
|
private static final Map<Class<? extends JavaPlugin>, AliasContext> contexts = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a context for a plugin
|
||||||
|
* This must be called BEFORE {@link AliasContext#initialize()}.
|
||||||
|
*/
|
||||||
|
public static void registerContext(JavaPlugin plugin, AliasContext context) {
|
||||||
|
contexts.put(plugin.getClass(), context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get context for a plugin class
|
||||||
|
*/
|
||||||
|
public static AliasContext getContext(Class<? extends JavaPlugin> pluginClass) {
|
||||||
|
AliasContext context = contexts.get(pluginClass);
|
||||||
|
if (context == null) {
|
||||||
|
throw new RuntimeException("No Alias context registered for " + pluginClass.getSimpleName() +
|
||||||
|
". Make sure to call AliasContext.initialize() in your plugin's onEnable() method!");
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove context for a plugin
|
||||||
|
*/
|
||||||
|
public static void removeContext(Class<? extends JavaPlugin> pluginClass) {
|
||||||
|
contexts.remove(pluginClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if context exists for a plugin
|
||||||
|
*/
|
||||||
|
public static boolean hasContext(Class<? extends JavaPlugin> pluginClass) {
|
||||||
|
return contexts.containsKey(pluginClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
72
src/main/java/me/trouper/alias/data/DataManager.java
Normal file
72
src/main/java/me/trouper/alias/data/DataManager.java
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
package me.trouper.alias.data;
|
||||||
|
|
||||||
|
import me.trouper.alias.AliasContext;
|
||||||
|
import me.trouper.alias.server.AutoRegistrar;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manages loading, retrieving, and saving of JsonSerializable instances
|
||||||
|
* registered via AutoRegistrar.
|
||||||
|
*/
|
||||||
|
public class DataManager {
|
||||||
|
private final AutoRegistrar registrar;
|
||||||
|
|
||||||
|
public DataManager(AliasContext context) {
|
||||||
|
this.registrar = context.getAutoRegistrar();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the data for the given JsonSerializable type from file, updates the registry,
|
||||||
|
* and returns the loaded instance (or fallback if loading failed).
|
||||||
|
*
|
||||||
|
* @param clazz the class type to load
|
||||||
|
* @param <T> type extending JsonSerializable
|
||||||
|
* @return loaded or fallback instance
|
||||||
|
*/
|
||||||
|
public <T extends JsonSerializable<?>> T load(Class<T> clazz) {
|
||||||
|
Optional<T> opt = getOptional(clazz);
|
||||||
|
if (opt.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
T instance = opt.get();
|
||||||
|
T loaded = JsonSerializable.load(instance.getFile(), clazz, instance);
|
||||||
|
|
||||||
|
if (loaded != instance) {
|
||||||
|
List<JsonSerializable<?>> list = registrar.getSerializables();
|
||||||
|
list.remove(instance);
|
||||||
|
list.add(loaded);
|
||||||
|
}
|
||||||
|
return loaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the registered JsonSerializable instance without loading.
|
||||||
|
*
|
||||||
|
* @param clazz the class type to retrieve
|
||||||
|
* @param <T> type extending JsonSerializable
|
||||||
|
* @return instance or null if not found
|
||||||
|
*/
|
||||||
|
public <T extends JsonSerializable<?>> T get(Class<T> clazz) {
|
||||||
|
return getOptional(clazz).orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T extends JsonSerializable<?>> Optional<T> getOptional(Class<T> clazz) {
|
||||||
|
return registrar.getSerializables().stream()
|
||||||
|
.filter(clazz::isInstance)
|
||||||
|
.map(clazz::cast)
|
||||||
|
.findFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves the registered JsonSerializable instance to its file.
|
||||||
|
* Does nothing if the type is not registered.
|
||||||
|
*
|
||||||
|
* @param clazz the class type to save
|
||||||
|
* @param <T> type extending JsonSerializable
|
||||||
|
*/
|
||||||
|
public <T extends JsonSerializable<?>> void save(Class<T> clazz) {
|
||||||
|
getOptional(clazz).ifPresent(JsonSerializable::save);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
package me.trouper.alias.data;
|
package me.trouper.alias.data;
|
||||||
|
|
||||||
import com.google.gson.*;
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
import me.trouper.alias.utils.misc.FileValidationUtils;
|
import me.trouper.alias.utils.misc.FileValidationUtils;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
package me.trouper.alias.server;
|
package me.trouper.alias.server;
|
||||||
|
|
||||||
|
import me.trouper.alias.AliasContext;
|
||||||
|
import me.trouper.alias.data.DataManager;
|
||||||
|
import me.trouper.alias.data.JsonSerializable;
|
||||||
import me.trouper.alias.server.commands.QuickCommand;
|
import me.trouper.alias.server.commands.QuickCommand;
|
||||||
import me.trouper.alias.server.events.QuickListener;
|
import me.trouper.alias.server.events.QuickListener;
|
||||||
import me.trouper.alias.server.systems.AbstractWand;
|
import me.trouper.alias.server.systems.AbstractWand;
|
||||||
@@ -13,66 +16,77 @@ import java.util.Set;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
public class AutoRegistrar {
|
public class AutoRegistrar {
|
||||||
|
|
||||||
private final JavaPlugin plugin;
|
private final JavaPlugin plugin;
|
||||||
private final List<QuickCommand> quickCommands = new ArrayList<>();
|
private final List<QuickCommand> quickCommands = new ArrayList<>();
|
||||||
private final List<QuickListener> quickListeners = new ArrayList<>();
|
private final List<QuickListener> quickListeners = new ArrayList<>();
|
||||||
private final List<AbstractWand> wands = new ArrayList<>();
|
private final List<AbstractWand> wands = new ArrayList<>();
|
||||||
|
private final List<JsonSerializable<?>> serializables = new ArrayList<>();
|
||||||
|
|
||||||
public AutoRegistrar(JavaPlugin plugin) {
|
public AutoRegistrar(AliasContext context) {
|
||||||
this.plugin = plugin;
|
this.plugin = context.getPlugin();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadAll(String basePackage) {
|
public void loadAll(String basePackage) {
|
||||||
Set<Class<?>> classes = ReflectionUtils.getClassesInPackage(plugin, basePackage);
|
Set<Class<?>> classes = ReflectionUtils.getClassesInPackage(plugin, basePackage);
|
||||||
|
|
||||||
for (Class<?> clazz : classes) {
|
for (Class<?> clazz : classes) {
|
||||||
if (clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers()) || clazz.isEnum() || clazz.isAnnotation()) {
|
if (clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers()) ||
|
||||||
continue;
|
clazz.isEnum() || clazz.isAnnotation()) continue;
|
||||||
}
|
|
||||||
|
|
||||||
boolean isCommand = QuickCommand.class.isAssignableFrom(clazz);
|
boolean isCommand = QuickCommand.class.isAssignableFrom(clazz);
|
||||||
boolean isWand = AbstractWand.class.isAssignableFrom(clazz);
|
boolean isWand = AbstractWand.class.isAssignableFrom(clazz);
|
||||||
boolean isListener = QuickListener.class.isAssignableFrom(clazz);
|
boolean isListener = QuickListener.class.isAssignableFrom(clazz);
|
||||||
|
boolean isSerializable = JsonSerializable.class.isAssignableFrom(clazz);
|
||||||
|
|
||||||
if (!isCommand && !isWand && !isListener) continue;
|
if (!isCommand && !isWand && !isListener && !isSerializable) continue;
|
||||||
|
|
||||||
|
Registrar registrarFlags = clazz.getAnnotation(Registrar.class);
|
||||||
|
if (registrarFlags != null && registrarFlags.exclude()) {
|
||||||
|
plugin.getLogger().info("Excluding " + clazz.getSimpleName() + " from the Registrar.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Object instance = clazz.getDeclaredConstructor().newInstance();
|
Object instance = clazz.getDeclaredConstructor().newInstance();
|
||||||
|
|
||||||
if (instance instanceof QuickCommand command) {
|
if (instance instanceof QuickCommand command) {
|
||||||
command.register();
|
|
||||||
quickCommands.add(command);
|
quickCommands.add(command);
|
||||||
plugin.getLogger().info("Registered QuickCommand: " + clazz.getSimpleName());
|
plugin.getLogger().info("Found QuickCommand: " + clazz.getSimpleName());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instance instanceof QuickListener listener && !(instance instanceof AbstractWand)) {
|
||||||
|
quickListeners.add(listener);
|
||||||
|
plugin.getLogger().info("Found QuickListener: " + clazz.getSimpleName());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (instance instanceof AbstractWand wand) {
|
if (instance instanceof AbstractWand wand) {
|
||||||
wand.register();
|
|
||||||
wands.add(wand);
|
wands.add(wand);
|
||||||
plugin.getLogger().info("Registered AbstractWand: " + clazz.getSimpleName());
|
plugin.getLogger().info("Found AbstractWand: " + clazz.getSimpleName());
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (instance instanceof QuickListener listener) {
|
if (instance instanceof JsonSerializable<?> js) {
|
||||||
listener.register();
|
serializables.add(js);
|
||||||
quickListeners.add(listener);
|
plugin.getLogger().info("Found JsonSerializable: " + clazz.getSimpleName());
|
||||||
plugin.getLogger().info("Registered QuickListener: " + clazz.getSimpleName());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
plugin.getLogger().log(Level.WARNING, "Failed to instantiate: " + clazz.getName(), t);
|
plugin.getLogger().log(Level.WARNING, "Failed to instantiate: " + clazz.getName(), t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
quickListeners.forEach(QuickListener::register);
|
||||||
|
quickCommands.forEach(QuickCommand::register);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<QuickCommand> getQuickCommands() {
|
public void unregisterAll() {
|
||||||
return quickCommands;
|
quickListeners.forEach(QuickListener::unregister);
|
||||||
|
quickListeners.clear();
|
||||||
|
quickCommands.forEach(QuickCommand::disable);
|
||||||
|
quickCommands.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<QuickListener> getQuickListeners() {
|
public List<QuickCommand> getQuickCommands() { return quickCommands; }
|
||||||
return quickListeners;
|
public List<QuickListener> getQuickListeners() { return quickListeners; }
|
||||||
}
|
public List<AbstractWand> getWands() { return wands; }
|
||||||
|
public List<JsonSerializable<?>> getSerializables() { return serializables; }
|
||||||
public List<AbstractWand> getWands() {
|
|
||||||
return wands;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
104
src/main/java/me/trouper/alias/server/ContextAware.java
Normal file
104
src/main/java/me/trouper/alias/server/ContextAware.java
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
package me.trouper.alias.server;
|
||||||
|
|
||||||
|
import me.trouper.alias.AliasContext;
|
||||||
|
import me.trouper.alias.AliasContextProvider;
|
||||||
|
import me.trouper.alias.data.Common;
|
||||||
|
import me.trouper.alias.data.DataManager;
|
||||||
|
import me.trouper.alias.server.systems.Text;
|
||||||
|
import me.trouper.alias.server.systems.Verbose;
|
||||||
|
import me.trouper.alias.server.systems.display.DisplayManager;
|
||||||
|
import me.trouper.alias.utils.misc.Randomizer;
|
||||||
|
import net.kyori.adventure.audience.Audience;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public interface ContextAware {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the plugin class this component belongs to.
|
||||||
|
* Easiest thing to avoid repeating this method is to make a "PluginContext" interface and fill out this method.
|
||||||
|
*/
|
||||||
|
Class<? extends JavaPlugin> getPluginClass();
|
||||||
|
|
||||||
|
default AliasContext getContext() {
|
||||||
|
return AliasContextProvider.getContext(getPluginClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
default JavaPlugin getPlugin() {
|
||||||
|
return getContext().getPlugin();
|
||||||
|
}
|
||||||
|
|
||||||
|
default Common getCommon() {
|
||||||
|
return getContext().getCommon();
|
||||||
|
}
|
||||||
|
|
||||||
|
default Text getTextSystem() {
|
||||||
|
return getContext().getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
default DisplayManager getDisplayManager() {
|
||||||
|
return getContext().getDisplayManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
default Verbose getVerbose() {
|
||||||
|
return getContext().getVerbose();
|
||||||
|
}
|
||||||
|
|
||||||
|
default AutoRegistrar getAutoRegistrar() {
|
||||||
|
return getContext().getAutoRegistrar();
|
||||||
|
}
|
||||||
|
|
||||||
|
default DataManager getDataManager() {
|
||||||
|
return getContext().getDataManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
default void info(Audience audience, Component message, Component... args) {
|
||||||
|
getTextSystem().message(Text.Pallet.INFO, audience, message, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
default void error(Audience audience, Component message, Component... args) {
|
||||||
|
getTextSystem().message(Text.Pallet.ERROR, audience, message, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
default void warning(Audience audience, Component message, Component... args) {
|
||||||
|
getTextSystem().message(Text.Pallet.WARNING, audience, message, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
default void success(Audience audience, Component message, Component... args) {
|
||||||
|
getTextSystem().message(Text.Pallet.SUCCESS, audience, message, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
default void message(Audience audience, Component message, Component... args) {
|
||||||
|
getTextSystem().message(Text.Pallet.NEUTRAL, audience, message, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
default void infoAny(Audience audience, String message, Object... args) {
|
||||||
|
getTextSystem().messageAny(Text.Pallet.INFO, audience, message, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
default void errorAny(Audience audience, String message, Object... args) {
|
||||||
|
getTextSystem().messageAny(Text.Pallet.ERROR, audience, message, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
default void warningAny(Audience audience, String message, Object... args) {
|
||||||
|
getTextSystem().messageAny(Text.Pallet.WARNING, audience, message, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
default void successAny(Audience audience, String message, Object... args) {
|
||||||
|
getTextSystem().messageAny(Text.Pallet.SUCCESS, audience, message, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
default void messageAny(Audience audience, String message, Object... args) {
|
||||||
|
getTextSystem().messageAny(Text.Pallet.NEUTRAL, audience, message, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
default Random random() {
|
||||||
|
return new Random();
|
||||||
|
}
|
||||||
|
|
||||||
|
default Randomizer randomizer() {
|
||||||
|
return new Randomizer();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
package me.trouper.alias.server;
|
|
||||||
|
|
||||||
import io.papermc.paper.registry.RegistryAccess;
|
|
||||||
import me.trouper.alias.Alias;
|
|
||||||
import me.trouper.alias.data.Common;
|
|
||||||
import me.trouper.alias.server.systems.Text;
|
|
||||||
import me.trouper.alias.utils.misc.Randomizer;
|
|
||||||
import net.kyori.adventure.audience.Audience;
|
|
||||||
import net.kyori.adventure.text.Component;
|
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
|
||||||
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
public interface Main {
|
|
||||||
Main main = new Main() {};
|
|
||||||
|
|
||||||
default RegistryAccess getRegistryAccess() {
|
|
||||||
return RegistryAccess.registryAccess();
|
|
||||||
}
|
|
||||||
|
|
||||||
default JavaPlugin getPlugin() {
|
|
||||||
Class<? extends JavaPlugin> host = Alias.getHost();
|
|
||||||
if (host == null) throw new RuntimeException("Alias is not enabled. Make sure to call Alias#register() in your JavaPlugin#onLoad() method!");
|
|
||||||
return getPlugin(host);
|
|
||||||
}
|
|
||||||
|
|
||||||
default <T extends JavaPlugin> T getPlugin(Class<T> pluginClass) {
|
|
||||||
return JavaPlugin.getPlugin(pluginClass);
|
|
||||||
}
|
|
||||||
|
|
||||||
default Common getCommon() {
|
|
||||||
return Alias.getCommon();
|
|
||||||
}
|
|
||||||
|
|
||||||
default void infoAny(Audience player, String message, Object... args) {
|
|
||||||
Text.messageAny(Text.Pallet.INFO, player, message, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
default void errorAny(Audience player, String message, Object... args) {
|
|
||||||
Text.messageAny(Text.Pallet.ERROR,player, message, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
default void warningAny(Audience player, String message, Object... args) {
|
|
||||||
Text.messageAny(Text.Pallet.WARNING, player, message, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
default void successAny(Audience player, String message, Object... args) {
|
|
||||||
Text.messageAny(Text.Pallet.SUCCESS, player, message, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
default void messageAny(Audience player, String message, Object... args) {
|
|
||||||
Text.messageAny(Text.Pallet.NEUTRAL, player, message, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
default void info(Audience player, Component message, Component... args) {
|
|
||||||
Text.message(Text.Pallet.INFO, player, message, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
default void error(Audience player, Component message, Component... args) {
|
|
||||||
Text.message(Text.Pallet.ERROR,player, message, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
default void warning(Audience player, Component message, Component... args) {
|
|
||||||
Text.message(Text.Pallet.WARNING, player, message, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
default void success(Audience player, Component message, Component... args) {
|
|
||||||
Text.message(Text.Pallet.SUCCESS, player, message, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
default void message(Audience player, Component message, Component... args) {
|
|
||||||
Text.message(Text.Pallet.NEUTRAL, player, message, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
default Random random() {
|
|
||||||
return new Random();
|
|
||||||
}
|
|
||||||
|
|
||||||
default Randomizer randomizer() {
|
|
||||||
return new Randomizer();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
12
src/main/java/me/trouper/alias/server/Registrar.java
Normal file
12
src/main/java/me/trouper/alias/server/Registrar.java
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package me.trouper.alias.server;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface Registrar {
|
||||||
|
boolean exclude() default false;
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package me.trouper.alias.server.commands;
|
package me.trouper.alias.server.commands;
|
||||||
|
|
||||||
import me.trouper.alias.server.Main;
|
import me.trouper.alias.server.ContextAware;
|
||||||
import me.trouper.alias.server.commands.completions.CompletionBuilder;
|
import me.trouper.alias.server.commands.completions.CompletionBuilder;
|
||||||
import me.trouper.alias.server.commands.completions.CompletionNode;
|
import me.trouper.alias.server.commands.completions.CompletionNode;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
@@ -12,8 +12,7 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface QuickCommand extends TabExecutor, Main {
|
public interface QuickCommand extends TabExecutor, ContextAware {
|
||||||
|
|
||||||
|
|
||||||
void handleCommand(CommandSender sender, Command command, String label, Args args);
|
void handleCommand(CommandSender sender, Command command, String label, Args args);
|
||||||
void handleCompletion(CommandSender sender, Command command, String label, Args args, CompletionBuilder b);
|
void handleCompletion(CommandSender sender, Command command, String label, Args args, CompletionBuilder b);
|
||||||
@@ -23,6 +22,7 @@ public interface QuickCommand extends TabExecutor, Main {
|
|||||||
PluginCommand command = getPlugin().getCommand(registry.value());
|
PluginCommand command = getPlugin().getCommand(registry.value());
|
||||||
|
|
||||||
if (command != null) {
|
if (command != null) {
|
||||||
|
getPlugin().getLogger().info("Registering Command from " + this.getClass().getSimpleName());
|
||||||
command.setExecutor(this);
|
command.setExecutor(this);
|
||||||
command.setTabCompleter(this);
|
command.setTabCompleter(this);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package me.trouper.alias.server.commands;
|
|||||||
import me.trouper.alias.server.events.QuickListener;
|
import me.trouper.alias.server.events.QuickListener;
|
||||||
|
|
||||||
public interface QuickCommandListener extends QuickCommand, QuickListener {
|
public interface QuickCommandListener extends QuickCommand, QuickListener {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default void register() {
|
default void register() {
|
||||||
QuickCommand.super.register();
|
QuickCommand.super.register();
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
package me.trouper.alias.server.events;
|
package me.trouper.alias.server.events;
|
||||||
|
|
||||||
import me.trouper.alias.server.Main;
|
import me.trouper.alias.server.ContextAware;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.event.HandlerList;
|
import org.bukkit.event.HandlerList;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
|
|
||||||
public interface QuickListener extends Listener, Main {
|
public interface QuickListener extends Listener, ContextAware {
|
||||||
|
|
||||||
default void register() {
|
default void register() {
|
||||||
Bukkit.getPluginManager().registerEvents(this,main.getPlugin());
|
getPlugin().getLogger().info("Registering Listeners from " + this.getClass().getSimpleName());
|
||||||
|
Bukkit.getPluginManager().registerEvents(this,getPlugin());
|
||||||
}
|
}
|
||||||
|
|
||||||
default void unregister() {
|
default void unregister() {
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package me.trouper.alias.server.events.custom;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.Cancellable;
|
||||||
|
import org.bukkit.event.Event;
|
||||||
|
import org.bukkit.event.HandlerList;
|
||||||
|
|
||||||
|
public class PlayerSpawnEntityEvent extends Event implements Cancellable {
|
||||||
|
private static final HandlerList HANDLERS = new HandlerList();
|
||||||
|
private final Player player;
|
||||||
|
private final Entity spawnedEntity;
|
||||||
|
private boolean cancelled = false;
|
||||||
|
|
||||||
|
public PlayerSpawnEntityEvent(Player player, Entity spawnedEntity) {
|
||||||
|
this.player = player;
|
||||||
|
this.spawnedEntity = spawnedEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Player getPlayer() {
|
||||||
|
return player;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Entity getSpawnedEntity() {
|
||||||
|
return spawnedEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCancelled() {
|
||||||
|
return cancelled;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCancelled(boolean cancel) {
|
||||||
|
this.cancelled = cancel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HandlerList getHandlers() {
|
||||||
|
return HANDLERS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HandlerList getHandlerList() {
|
||||||
|
return HANDLERS;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,14 +1,17 @@
|
|||||||
package me.trouper.alias.server.events;
|
package me.trouper.alias.server.events.listeners;
|
||||||
|
|
||||||
|
import me.trouper.alias.server.events.QuickListener;
|
||||||
import me.trouper.alias.server.systems.gui.QuickGui;
|
import me.trouper.alias.server.systems.gui.QuickGui;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.EventPriority;
|
import org.bukkit.event.EventPriority;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||||
import org.bukkit.event.inventory.InventoryDragEvent;
|
import org.bukkit.event.inventory.InventoryDragEvent;
|
||||||
import org.bukkit.event.player.PlayerQuitEvent;
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
public class GuiListener implements QuickListener {
|
public class GuiListener implements Listener {
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.NORMAL)
|
@EventHandler(priority = EventPriority.NORMAL)
|
||||||
public void onInventoryClick(InventoryClickEvent event) {
|
public void onInventoryClick(InventoryClickEvent event) {
|
||||||
@@ -31,5 +34,4 @@ public class GuiListener implements QuickListener {
|
|||||||
gui.getViewers().remove(event.getPlayer());
|
gui.getViewers().remove(event.getPlayer());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
package me.trouper.alias.server.events.listeners;
|
||||||
|
|
||||||
|
import me.trouper.alias.AliasContext;
|
||||||
|
import me.trouper.alias.server.events.custom.PlayerSpawnEntityEvent;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.EnderPearl;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.block.BlockPlaceEvent;
|
||||||
|
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||||
|
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
|
||||||
|
import org.bukkit.event.entity.ProjectileLaunchEvent;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
|
|
||||||
|
public class SpawnListener implements Listener {
|
||||||
|
|
||||||
|
private final AliasContext context;
|
||||||
|
private final ConcurrentLinkedQueue<Placed> recentBlocks = new ConcurrentLinkedQueue<>();
|
||||||
|
private final Map<UUID, UUID> pearlOwners = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
public SpawnListener(AliasContext context) {
|
||||||
|
this.context = context;
|
||||||
|
Bukkit.getScheduler().runTaskTimer(context.getPlugin(), this::cleanup, 20, 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cleanup() {
|
||||||
|
long cutoff = System.currentTimeMillis() - 2000;
|
||||||
|
Iterator<Placed> it = recentBlocks.iterator();
|
||||||
|
while (it.hasNext() && it.next().time < cutoff) {
|
||||||
|
it.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onBlockPlace(BlockPlaceEvent e) {
|
||||||
|
recentBlocks.add(new Placed(e.getPlayer().getUniqueId(), e.getBlockPlaced().getLocation(), System.currentTimeMillis()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onProjectileLaunch(ProjectileLaunchEvent e) {
|
||||||
|
if (!(e.getEntity() instanceof EnderPearl)) return;
|
||||||
|
if (!(e.getEntity().getShooter() instanceof Player p)) return;
|
||||||
|
pearlOwners.put(e.getEntity().getUniqueId(), p.getUniqueId());
|
||||||
|
Bukkit.getScheduler().runTaskLaterAsynchronously(
|
||||||
|
context.getPlugin(),
|
||||||
|
() -> pearlOwners.remove(e.getEntity().getUniqueId()),
|
||||||
|
100L
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onCreatureSpawn(CreatureSpawnEvent e) {
|
||||||
|
SpawnReason reason = e.getSpawnReason();
|
||||||
|
Player spawner = null;
|
||||||
|
|
||||||
|
if (reason == SpawnReason.BUILD_IRONGOLEM
|
||||||
|
|| reason == SpawnReason.BUILD_SNOWMAN
|
||||||
|
|| reason == SpawnReason.BUILD_WITHER) {
|
||||||
|
|
||||||
|
Location spawnLoc = e.getEntity().getLocation();
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
for (Placed p : recentBlocks) {
|
||||||
|
if (p.time > now - 2000 && p.loc.getWorld().equals(spawnLoc.getWorld())
|
||||||
|
&& p.loc.distanceSquared(spawnLoc) < 4) {
|
||||||
|
spawner = Bukkit.getPlayer(p.playerId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (reason == SpawnReason.ENDER_PEARL) {
|
||||||
|
for (Map.Entry<UUID, UUID> en : pearlOwners.entrySet()) {
|
||||||
|
Entity pearl = Bukkit.getEntity(en.getKey());
|
||||||
|
if (pearl != null && pearl.getLocation().distanceSquared(e.getEntity().getLocation()) < 4) {
|
||||||
|
spawner = Bukkit.getPlayer(en.getValue());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spawner == null) return;
|
||||||
|
|
||||||
|
PlayerSpawnEntityEvent pse = new PlayerSpawnEntityEvent(spawner, e.getEntity());
|
||||||
|
Bukkit.getPluginManager().callEvent(pse);
|
||||||
|
if (pse.isCancelled()) {
|
||||||
|
e.setCancelled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Placed {
|
||||||
|
final UUID playerId;
|
||||||
|
final Location loc;
|
||||||
|
final long time;
|
||||||
|
Placed(UUID p, Location l, long t) { playerId = p; loc = l; time = t; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,168 @@
|
|||||||
|
package me.trouper.alias.server.events.listeners;
|
||||||
|
|
||||||
|
import me.trouper.alias.AliasContext;
|
||||||
|
import me.trouper.alias.server.systems.AbstractWand;
|
||||||
|
import me.trouper.alias.utils.misc.Cooldown;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.EventPriority;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.block.Action;
|
||||||
|
import org.bukkit.event.block.BlockBreakEvent;
|
||||||
|
import org.bukkit.event.block.BlockPlaceEvent;
|
||||||
|
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||||
|
import org.bukkit.event.player.*;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class WandListener implements Listener {
|
||||||
|
|
||||||
|
private final AliasContext context;
|
||||||
|
private final Cooldown<UUID> debounce = new Cooldown<>();
|
||||||
|
|
||||||
|
public WandListener(AliasContext context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<AbstractWand> getWands() {
|
||||||
|
return context.getAutoRegistrar().getWands();
|
||||||
|
}
|
||||||
|
|
||||||
|
private AbstractWand getWandForItem(ItemStack item) {
|
||||||
|
if (item == null) return null;
|
||||||
|
|
||||||
|
for (AbstractWand wand : getWands()) {
|
||||||
|
if (item.isSimilar(wand.getWandItem())) {
|
||||||
|
return wand;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private AbstractWand getWandForPlayer(Player p) {
|
||||||
|
ItemStack inMain = p.getInventory().getItemInMainHand();
|
||||||
|
ItemStack inOff = p.getInventory().getItemInOffHand();
|
||||||
|
|
||||||
|
AbstractWand wand = getWandForItem(inMain);
|
||||||
|
if (wand != null) return wand;
|
||||||
|
|
||||||
|
return getWandForItem(inOff);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public final void onSwapHands(PlayerSwapHandItemsEvent e) {
|
||||||
|
Player p = e.getPlayer();
|
||||||
|
AbstractWand wand = getWandForPlayer(p);
|
||||||
|
if (wand == null || !p.hasPermission(wand.getUsePermission())) return;
|
||||||
|
e.setCancelled(true);
|
||||||
|
|
||||||
|
wand.swapHand(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGHEST)
|
||||||
|
public final void onInteract(PlayerInteractEvent e) {
|
||||||
|
Player p = e.getPlayer();
|
||||||
|
AbstractWand wand = getWandForPlayer(p);
|
||||||
|
if (wand == null || !p.hasPermission(wand.getUsePermission())) return;
|
||||||
|
|
||||||
|
Action action = e.getAction();
|
||||||
|
|
||||||
|
switch (action) {
|
||||||
|
case RIGHT_CLICK_AIR, RIGHT_CLICK_BLOCK -> {
|
||||||
|
e.setCancelled(true);
|
||||||
|
|
||||||
|
if (debounce.isOnCooldown(p.getUniqueId())) return;
|
||||||
|
debounce.setCooldown(p.getUniqueId(), 100);
|
||||||
|
|
||||||
|
wand.rightClick(p);
|
||||||
|
}
|
||||||
|
case LEFT_CLICK_AIR, LEFT_CLICK_BLOCK -> {
|
||||||
|
e.setCancelled(true);
|
||||||
|
wand.leftClick(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGHEST)
|
||||||
|
public final void onEntityDamage(EntityDamageByEntityEvent e) {
|
||||||
|
if (!(e.getDamager() instanceof Player p)) return;
|
||||||
|
AbstractWand wand = getWandForPlayer(p);
|
||||||
|
if (wand == null || !p.hasPermission(wand.getUsePermission())) return;
|
||||||
|
|
||||||
|
e.setCancelled(true);
|
||||||
|
wand.leftClick(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGHEST)
|
||||||
|
public final void onEntityInteract(PlayerInteractEntityEvent e) {
|
||||||
|
Player p = e.getPlayer();
|
||||||
|
AbstractWand wand = getWandForPlayer(p);
|
||||||
|
if (wand == null || !p.hasPermission(wand.getUsePermission())) return;
|
||||||
|
e.setCancelled(true);
|
||||||
|
|
||||||
|
if (debounce.isOnCooldown(p.getUniqueId())) return;
|
||||||
|
debounce.setCooldown(p.getUniqueId(), 100);
|
||||||
|
|
||||||
|
wand.rightClick(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGHEST)
|
||||||
|
public final void onEntityInteractAt(PlayerInteractAtEntityEvent e) {
|
||||||
|
Player p = e.getPlayer();
|
||||||
|
AbstractWand wand = getWandForPlayer(p);
|
||||||
|
if (wand == null || !p.hasPermission(wand.getUsePermission())) return;
|
||||||
|
|
||||||
|
if (debounce.isOnCooldown(p.getUniqueId())) return;
|
||||||
|
debounce.setCooldown(p.getUniqueId(), 100);
|
||||||
|
|
||||||
|
e.setCancelled(true);
|
||||||
|
wand.rightClick(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGHEST)
|
||||||
|
public final void onBlockBreak(BlockBreakEvent e) {
|
||||||
|
Player p = e.getPlayer();
|
||||||
|
AbstractWand wand = getWandForPlayer(p);
|
||||||
|
if (wand == null || !p.hasPermission(wand.getUsePermission())) return;
|
||||||
|
|
||||||
|
e.setCancelled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGHEST)
|
||||||
|
public final void onBlockPlace(BlockPlaceEvent e) {
|
||||||
|
Player p = e.getPlayer();
|
||||||
|
AbstractWand wand = getWandForItem(e.getItemInHand());
|
||||||
|
if (wand == null || !p.hasPermission(wand.getUsePermission())) return;
|
||||||
|
|
||||||
|
e.setCancelled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGHEST)
|
||||||
|
public final void onItemDrop(PlayerDropItemEvent e) {
|
||||||
|
Player p = e.getPlayer();
|
||||||
|
AbstractWand wand = getWandForItem(e.getItemDrop().getItemStack());
|
||||||
|
if (wand == null || !p.hasPermission(wand.getUsePermission())) return;
|
||||||
|
|
||||||
|
e.setCancelled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public final void onScroll(PlayerItemHeldEvent e) {
|
||||||
|
Player p = e.getPlayer();
|
||||||
|
AbstractWand wand = getWandForPlayer(p);
|
||||||
|
if (wand == null || !p.hasPermission(wand.getUsePermission())) return;
|
||||||
|
|
||||||
|
int prev = e.getPreviousSlot();
|
||||||
|
int curr = e.getNewSlot();
|
||||||
|
|
||||||
|
if (!p.isSneaking() || getWandForItem(p.getInventory().getItem(prev)) == null) return;
|
||||||
|
e.setCancelled(true);
|
||||||
|
|
||||||
|
if (curr == 8 && prev == 0) wand.onScrollUp(p);
|
||||||
|
else if (curr == 0 && prev == 8) wand.onScrollDown(p);
|
||||||
|
else if (curr < prev) wand.onScrollUp(p);
|
||||||
|
else if (curr > prev) wand.onScrollDown(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,27 +1,12 @@
|
|||||||
package me.trouper.alias.server.systems;
|
package me.trouper.alias.server.systems;
|
||||||
|
|
||||||
import me.trouper.alias.server.Main;
|
|
||||||
import me.trouper.alias.server.events.QuickListener;
|
|
||||||
import me.trouper.alias.utils.misc.Cooldown;
|
|
||||||
import org.bukkit.block.Block;
|
|
||||||
import org.bukkit.entity.Entity;
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
|
||||||
import org.bukkit.event.EventPriority;
|
|
||||||
import org.bukkit.event.block.Action;
|
|
||||||
import org.bukkit.event.block.BlockBreakEvent;
|
|
||||||
import org.bukkit.event.block.BlockPlaceEvent;
|
|
||||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
|
||||||
import org.bukkit.event.player.*;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
import java.util.UUID;
|
public abstract class AbstractWand {
|
||||||
|
|
||||||
public abstract class AbstractWand implements QuickListener, Main {
|
|
||||||
|
|
||||||
private final String usePermission;
|
private final String usePermission;
|
||||||
private final ItemStack wandItem;
|
private final ItemStack wandItem;
|
||||||
private final Cooldown<UUID> debounce = new Cooldown<>();
|
|
||||||
|
|
||||||
public AbstractWand(String usePermission, ItemStack wandItem) {
|
public AbstractWand(String usePermission, ItemStack wandItem) {
|
||||||
this.wandItem = wandItem.clone();
|
this.wandItem = wandItem.clone();
|
||||||
@@ -31,126 +16,11 @@ public abstract class AbstractWand implements QuickListener, Main {
|
|||||||
public String getUsePermission() {
|
public String getUsePermission() {
|
||||||
return usePermission;
|
return usePermission;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ItemStack getWandItem() {
|
public ItemStack getWandItem() {
|
||||||
return wandItem.clone();
|
return wandItem.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isWand(ItemStack item) {
|
|
||||||
return item != null && item.isSimilar(wandItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isHoldingWand(Player p) {
|
|
||||||
ItemStack inMain = p.getInventory().getItemInMainHand();
|
|
||||||
ItemStack inOff = p.getInventory().getItemInOffHand();
|
|
||||||
return isWand(inMain) || isWand(inOff);
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public final void onSwapHands(PlayerSwapHandItemsEvent e) {
|
|
||||||
Player p = e.getPlayer();
|
|
||||||
if (!isHoldingWand(p) || !p.hasPermission(getUsePermission())) return;
|
|
||||||
e.setCancelled(true);
|
|
||||||
|
|
||||||
swapHand(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.HIGHEST)
|
|
||||||
public final void onInteract(PlayerInteractEvent e) {
|
|
||||||
Player p = e.getPlayer();
|
|
||||||
if (!isHoldingWand(p) || !p.hasPermission(getUsePermission())) return;
|
|
||||||
|
|
||||||
Action action = e.getAction();
|
|
||||||
|
|
||||||
switch (action) {
|
|
||||||
case RIGHT_CLICK_AIR, RIGHT_CLICK_BLOCK -> {
|
|
||||||
e.setCancelled(true);
|
|
||||||
|
|
||||||
if (debounce.isOnCooldown(p.getUniqueId())) return;
|
|
||||||
debounce.setCooldown(p.getUniqueId(),100);
|
|
||||||
|
|
||||||
rightClick(p);
|
|
||||||
}
|
|
||||||
case LEFT_CLICK_AIR, LEFT_CLICK_BLOCK -> {
|
|
||||||
e.setCancelled(true);
|
|
||||||
leftClick(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.HIGHEST)
|
|
||||||
public final void onEntityDamage(EntityDamageByEntityEvent e) {
|
|
||||||
if (!(e.getDamager() instanceof Player p)) return;
|
|
||||||
if (!isHoldingWand(p) || !p.hasPermission(getUsePermission())) return;
|
|
||||||
|
|
||||||
e.setCancelled(true);
|
|
||||||
leftClick(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.HIGHEST)
|
|
||||||
public final void onEntityInteract(PlayerInteractEntityEvent e) {
|
|
||||||
Player p = e.getPlayer();
|
|
||||||
if (!isHoldingWand(p) || !p.hasPermission(getUsePermission())) return;
|
|
||||||
e.setCancelled(true);
|
|
||||||
|
|
||||||
if (debounce.isOnCooldown(p.getUniqueId())) return;
|
|
||||||
debounce.setCooldown(p.getUniqueId(),100);
|
|
||||||
|
|
||||||
rightClick(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.HIGHEST)
|
|
||||||
public final void onEntityInteractAt(PlayerInteractAtEntityEvent e) {
|
|
||||||
Player p = e.getPlayer();
|
|
||||||
if (!isHoldingWand(p) || !p.hasPermission(getUsePermission())) return;
|
|
||||||
|
|
||||||
if (debounce.isOnCooldown(p.getUniqueId())) return;
|
|
||||||
debounce.setCooldown(p.getUniqueId(),100);
|
|
||||||
|
|
||||||
e.setCancelled(true);
|
|
||||||
rightClick(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.HIGHEST)
|
|
||||||
public final void onBlockBreak(BlockBreakEvent e) {
|
|
||||||
Player p = e.getPlayer();
|
|
||||||
if (!isHoldingWand(p) || !p.hasPermission(getUsePermission())) return;
|
|
||||||
|
|
||||||
e.setCancelled(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.HIGHEST)
|
|
||||||
public final void onBlockPlace(BlockPlaceEvent e) {
|
|
||||||
Player p = e.getPlayer();
|
|
||||||
if (!isWand(e.getItemInHand()) || !p.hasPermission(getUsePermission())) return;
|
|
||||||
|
|
||||||
e.setCancelled(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.HIGHEST)
|
|
||||||
public final void onItemDrop(PlayerDropItemEvent e) {
|
|
||||||
Player p = e.getPlayer();
|
|
||||||
if (!isWand(e.getItemDrop().getItemStack()) || !p.hasPermission(getUsePermission())) return;
|
|
||||||
|
|
||||||
e.setCancelled(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public final void onScroll(PlayerItemHeldEvent e) {
|
|
||||||
Player p = e.getPlayer();
|
|
||||||
if (!isHoldingWand(p) || !p.hasPermission(getUsePermission())) return;
|
|
||||||
|
|
||||||
int prev = e.getPreviousSlot();
|
|
||||||
int curr = e.getNewSlot();
|
|
||||||
|
|
||||||
if (!p.isSneaking() || !isWand(p.getInventory().getItem(prev))) return;
|
|
||||||
e.setCancelled(true);
|
|
||||||
|
|
||||||
if (curr == 8 && prev == 0) onScrollUp(p);
|
|
||||||
else if (curr == 0 && prev == 8) onScrollDown(p);
|
|
||||||
else if (curr < prev) onScrollUp(p);
|
|
||||||
else if (curr > prev) onScrollDown(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void swapHand(Player p) {
|
public final void swapHand(Player p) {
|
||||||
if (p.isSneaking()) onSwapHandSneak(p);
|
if (p.isSneaking()) onSwapHandSneak(p);
|
||||||
else onSwapHand(p);
|
else onSwapHand(p);
|
||||||
@@ -166,20 +36,20 @@ public abstract class AbstractWand implements QuickListener, Main {
|
|||||||
else onRightClick(p);
|
else onRightClick(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void onSwapHand(Player player) {}
|
public void onSwapHand(Player player) {}
|
||||||
protected void onSwapHandSneak(Player player) {}
|
public void onSwapHandSneak(Player player) {}
|
||||||
protected void onRightClick(Player player) {}
|
public void onRightClick(Player player) {}
|
||||||
protected void onRightClickSneak(Player player) {}
|
public void onRightClickSneak(Player player) {}
|
||||||
protected void onLeftClick(Player player) {}
|
public void onLeftClick(Player player) {}
|
||||||
protected void onLeftClickSneak(Player player) {}
|
public void onLeftClickSneak(Player player) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The player must be sneaking to scroll the wand.
|
* The player must be sneaking to scroll the wand.
|
||||||
*/
|
*/
|
||||||
protected void onScrollUp(Player player) {}
|
public void onScrollUp(Player player) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The player must be sneaking to scroll the wand.
|
* The player must be sneaking to scroll the wand.
|
||||||
*/
|
*/
|
||||||
protected void onScrollDown(Player player) {}
|
public void onScrollDown(Player player) {}
|
||||||
}
|
}
|
||||||
@@ -1,20 +1,25 @@
|
|||||||
package me.trouper.alias.server.systems;
|
package me.trouper.alias.server.systems;
|
||||||
|
|
||||||
import me.trouper.alias.server.Main;
|
import me.trouper.alias.AliasContext;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.util.*;
|
import java.util.HashMap;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.Map;
|
||||||
|
|
||||||
public class TaskManager implements Closeable, Main {
|
public class TaskManager implements Closeable {
|
||||||
|
private final AliasContext context;
|
||||||
private final Map<Integer, Boolean> tasks = new HashMap<>();
|
private final Map<Integer, Boolean> tasks = new HashMap<>();
|
||||||
private volatile boolean closed = false;
|
private volatile boolean closed = false;
|
||||||
|
|
||||||
|
public TaskManager(AliasContext context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
public int scheduleTask(Runnable task, long delay) {
|
public int scheduleTask(Runnable task, long delay) {
|
||||||
if (closed) return -1;
|
if (closed) return -1;
|
||||||
|
|
||||||
int taskId = Bukkit.getScheduler().runTaskLater(main.getPlugin(), () -> {
|
int taskId = Bukkit.getScheduler().runTaskLater(context.getPlugin(), () -> {
|
||||||
if (!closed) {
|
if (!closed) {
|
||||||
task.run();
|
task.run();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package me.trouper.alias.server.systems;
|
package me.trouper.alias.server.systems;
|
||||||
|
|
||||||
import me.trouper.alias.Alias;
|
import me.trouper.alias.AliasContext;
|
||||||
import me.trouper.alias.server.Main;
|
|
||||||
import net.kyori.adventure.audience.Audience;
|
import net.kyori.adventure.audience.Audience;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.ComponentLike;
|
import net.kyori.adventure.text.ComponentLike;
|
||||||
@@ -18,8 +17,12 @@ import org.bukkit.entity.Player;
|
|||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class Text implements Main {
|
public class Text {
|
||||||
|
private final AliasContext context;
|
||||||
|
|
||||||
|
public Text(AliasContext context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Messages an audience applying pallet formatting to the text and placeholders. Placeholders are zero-indexed and curly braced. {0}, {1}, {2}...
|
* Messages an audience applying pallet formatting to the text and placeholders. Placeholders are zero-indexed and curly braced. {0}, {1}, {2}...
|
||||||
* Supports both flat messages and fancy wrapped messages based on Alias configuration.
|
* Supports both flat messages and fancy wrapped messages based on Alias configuration.
|
||||||
@@ -29,7 +32,7 @@ public class Text implements Main {
|
|||||||
* @param text The message to format
|
* @param text The message to format
|
||||||
* @param args Qualified placeholders to color.
|
* @param args Qualified placeholders to color.
|
||||||
*/
|
*/
|
||||||
public static void messageAny(Pallet pallet, boolean playSound, Audience audience, String text, Object... args) {
|
public void messageAny(Pallet pallet, boolean playSound, Audience audience, String text, Object... args) {
|
||||||
message(
|
message(
|
||||||
pallet,
|
pallet,
|
||||||
playSound,
|
playSound,
|
||||||
@@ -49,7 +52,7 @@ public class Text implements Main {
|
|||||||
* @param text The message to format
|
* @param text The message to format
|
||||||
* @param args Qualified placeholders to color.
|
* @param args Qualified placeholders to color.
|
||||||
*/
|
*/
|
||||||
public static void messageAny(Pallet pallet, Audience audience, String text, Object... args) {
|
public void messageAny(Pallet pallet, Audience audience, String text, Object... args) {
|
||||||
messageAny(pallet,true,audience,text,args);
|
messageAny(pallet,true,audience,text,args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,7 +66,7 @@ public class Text implements Main {
|
|||||||
* @param text The component message to format
|
* @param text The component message to format
|
||||||
* @param args Qualified placeholders to color.
|
* @param args Qualified placeholders to color.
|
||||||
*/
|
*/
|
||||||
public static void message(Pallet pallet, boolean playSound, Audience audience, ComponentLike text, ComponentLike... args) {
|
public void message(Pallet pallet, boolean playSound, Audience audience, ComponentLike text, ComponentLike... args) {
|
||||||
Component message = getMessage(pallet, text, args);
|
Component message = getMessage(pallet, text, args);
|
||||||
audience.sendMessage(message);
|
audience.sendMessage(message);
|
||||||
if (playSound && audience instanceof Player p) p.playSound(p.getLocation(), pallet.sound.sound, SoundCategory.VOICE, 10f, pallet.sound.pitch);
|
if (playSound && audience instanceof Player p) p.playSound(p.getLocation(), pallet.sound.sound, SoundCategory.VOICE, 10f, pallet.sound.pitch);
|
||||||
@@ -78,7 +81,7 @@ public class Text implements Main {
|
|||||||
* @param text The component message to format
|
* @param text The component message to format
|
||||||
* @param args Qualified placeholders to color.
|
* @param args Qualified placeholders to color.
|
||||||
*/
|
*/
|
||||||
public static void message(Pallet pallet, Audience audience, ComponentLike text, ComponentLike... args) {
|
public void message(Pallet pallet, Audience audience, ComponentLike text, ComponentLike... args) {
|
||||||
message(pallet,true,audience,text,args);
|
message(pallet,true,audience,text,args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,7 +92,7 @@ public class Text implements Main {
|
|||||||
* @param args Qualified placeholders to color.
|
* @param args Qualified placeholders to color.
|
||||||
* @return The final component, formatted according to flat/fancy setting.
|
* @return The final component, formatted according to flat/fancy setting.
|
||||||
*/
|
*/
|
||||||
public static Component getMessageAny(Pallet pallet, String text, Object... args) {
|
public Component getMessageAny(Pallet pallet, String text, Object... args) {
|
||||||
return getMessage(
|
return getMessage(
|
||||||
pallet,
|
pallet,
|
||||||
color(text),
|
color(text),
|
||||||
@@ -108,10 +111,10 @@ public class Text implements Main {
|
|||||||
* @param args Qualified placeholders to color.
|
* @param args Qualified placeholders to color.
|
||||||
* @return The final component, formatted according to flat/fancy setting.
|
* @return The final component, formatted according to flat/fancy setting.
|
||||||
*/
|
*/
|
||||||
public static Component getMessage(Pallet pallet, ComponentLike text, ComponentLike... args) {
|
public Component getMessage(Pallet pallet, ComponentLike text, ComponentLike... args) {
|
||||||
Component formattedMessage = format(pallet, text, args);
|
Component formattedMessage = format(pallet, text, args);
|
||||||
|
|
||||||
if (main.getCommon().useFlat()) {
|
if (context.getCommon().useFlat()) {
|
||||||
return formatFlatMessage(formattedMessage);
|
return formatFlatMessage(formattedMessage);
|
||||||
} else {
|
} else {
|
||||||
return formatFancyMessage(formattedMessage);
|
return formatFancyMessage(formattedMessage);
|
||||||
@@ -123,8 +126,8 @@ public class Text implements Main {
|
|||||||
* @param message The formatted message component
|
* @param message The formatted message component
|
||||||
* @return The message with flat prefix applied
|
* @return The message with flat prefix applied
|
||||||
*/
|
*/
|
||||||
private static Component formatFlatMessage(Component message) {
|
private Component formatFlatMessage(Component message) {
|
||||||
Component prefix = color(main.getCommon().getFlatPrefix());
|
Component prefix = color(context.getCommon().getFlatPrefix());
|
||||||
return prefix.append(message);
|
return prefix.append(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,8 +137,8 @@ public class Text implements Main {
|
|||||||
* @param message The formatted message component
|
* @param message The formatted message component
|
||||||
* @return The message with fancy formatting and line wrapping
|
* @return The message with fancy formatting and line wrapping
|
||||||
*/
|
*/
|
||||||
private static Component formatFancyMessage(Component message) {
|
private Component formatFancyMessage(Component message) {
|
||||||
List<Component> wrappedLines = wrapComponent(message, 50, (int) Math.round((main.getCommon().getPluginName().length() + 3) * 1.3));
|
List<Component> wrappedLines = wrapComponent(message, 50, (int) Math.round((context.getCommon().getPluginName().length() + 3) * 1.3));
|
||||||
// 50 is slightly below the average character width of someone's minecraft chat. The 3 is to account for the bolded "| " and the 1.3 is to account for bolding the plugin name.
|
// 50 is slightly below the average character width of someone's minecraft chat. The 3 is to account for the bolded "| " and the 1.3 is to account for bolding the plugin name.
|
||||||
if (wrappedLines.isEmpty()) {
|
if (wrappedLines.isEmpty()) {
|
||||||
wrappedLines.add(Component.empty());
|
wrappedLines.add(Component.empty());
|
||||||
@@ -144,15 +147,15 @@ public class Text implements Main {
|
|||||||
Component result = Component.empty().appendNewline();
|
Component result = Component.empty().appendNewline();
|
||||||
|
|
||||||
Component firstLine = Component.empty()
|
Component firstLine = Component.empty()
|
||||||
.append(Component.text("| ", TextColor.color(main.getCommon().getSecondaryColor())).decorate(TextDecoration.BOLD))
|
.append(Component.text("| ", TextColor.color(context.getCommon().getSecondaryColor())).decorate(TextDecoration.BOLD))
|
||||||
.append(Component.text(main.getCommon().getPluginName() + " ", TextColor.color(main.getCommon().getMainColor()), TextDecoration.BOLD))
|
.append(Component.text(context.getCommon().getPluginName() + " ", TextColor.color(context.getCommon().getMainColor()), TextDecoration.BOLD))
|
||||||
.append(wrappedLines.get(0));
|
.append(wrappedLines.get(0));
|
||||||
|
|
||||||
result = result.append(firstLine);
|
result = result.append(firstLine);
|
||||||
|
|
||||||
for (int i = 1; i < wrappedLines.size(); i++) {
|
for (int i = 1; i < wrappedLines.size(); i++) {
|
||||||
Component line = Component.empty()
|
Component line = Component.empty()
|
||||||
.append(Component.text("| ", TextColor.color(main.getCommon().getSecondaryColor())).decorate(TextDecoration.BOLD))
|
.append(Component.text("| ", TextColor.color(context.getCommon().getSecondaryColor())).decorate(TextDecoration.BOLD))
|
||||||
.append(wrappedLines.get(i));
|
.append(wrappedLines.get(i));
|
||||||
|
|
||||||
result = result.appendNewline().append(line);
|
result = result.appendNewline().append(line);
|
||||||
@@ -170,7 +173,7 @@ public class Text implements Main {
|
|||||||
* @param firstLineOffset Offset for the first line (plugin name length)
|
* @param firstLineOffset Offset for the first line (plugin name length)
|
||||||
* @return List of wrapped component lines
|
* @return List of wrapped component lines
|
||||||
*/
|
*/
|
||||||
private static List<Component> wrapComponent(Component component, int maxLineLength, int firstLineOffset) {
|
private List<Component> wrapComponent(Component component, int maxLineLength, int firstLineOffset) {
|
||||||
List<Component> lines = new ArrayList<>();
|
List<Component> lines = new ArrayList<>();
|
||||||
|
|
||||||
List<ComponentWord> words = extractWords(component);
|
List<ComponentWord> words = extractWords(component);
|
||||||
@@ -218,7 +221,7 @@ public class Text implements Main {
|
|||||||
* @param word The word to check
|
* @param word The word to check
|
||||||
* @return true if the word starts with punctuation
|
* @return true if the word starts with punctuation
|
||||||
*/
|
*/
|
||||||
private static boolean startsWithPunctuation(ComponentWord word) {
|
private boolean startsWithPunctuation(ComponentWord word) {
|
||||||
String text = PlainTextComponentSerializer.plainText().serialize(word.component());
|
String text = PlainTextComponentSerializer.plainText().serialize(word.component());
|
||||||
return !text.isEmpty() && ".,!?;:)]}".indexOf(text.charAt(0)) != -1;
|
return !text.isEmpty() && ".,!?;:)]}".indexOf(text.charAt(0)) != -1;
|
||||||
}
|
}
|
||||||
@@ -228,7 +231,7 @@ public class Text implements Main {
|
|||||||
* @param component The component to extract words from
|
* @param component The component to extract words from
|
||||||
* @return List of ComponentWord objects
|
* @return List of ComponentWord objects
|
||||||
*/
|
*/
|
||||||
private static List<ComponentWord> extractWords(Component component) {
|
private List<ComponentWord> extractWords(Component component) {
|
||||||
List<ComponentWord> words = new ArrayList<>();
|
List<ComponentWord> words = new ArrayList<>();
|
||||||
extractWordsRecursive(component, Style.empty(), words);
|
extractWordsRecursive(component, Style.empty(), words);
|
||||||
return words;
|
return words;
|
||||||
@@ -240,7 +243,7 @@ public class Text implements Main {
|
|||||||
* @param inheritedStyle The style inherited from parent components
|
* @param inheritedStyle The style inherited from parent components
|
||||||
* @param words The list to add words to
|
* @param words The list to add words to
|
||||||
*/
|
*/
|
||||||
private static void extractWordsRecursive(Component component, Style inheritedStyle, List<ComponentWord> words) {
|
private void extractWordsRecursive(Component component, Style inheritedStyle, List<ComponentWord> words) {
|
||||||
Style currentStyle = inheritedStyle.merge(component.style());
|
Style currentStyle = inheritedStyle.merge(component.style());
|
||||||
|
|
||||||
if (component instanceof TextComponent textComponent) {
|
if (component instanceof TextComponent textComponent) {
|
||||||
@@ -267,7 +270,7 @@ public class Text implements Main {
|
|||||||
* @param text The text to measure
|
* @param text The text to measure
|
||||||
* @return The visible character count
|
* @return The visible character count
|
||||||
*/
|
*/
|
||||||
private static int getVisibleLength(String text) {
|
private int getVisibleLength(String text) {
|
||||||
return PlainTextComponentSerializer.plainText().serialize(Component.text(text)).length();
|
return PlainTextComponentSerializer.plainText().serialize(Component.text(text)).length();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,7 +279,7 @@ public class Text implements Main {
|
|||||||
* @param msg the legacy text
|
* @param msg the legacy text
|
||||||
* @return The deserialized component
|
* @return The deserialized component
|
||||||
*/
|
*/
|
||||||
public static Component color(String msg) {
|
public Component color(String msg) {
|
||||||
if (msg.contains("§")) return LegacyComponentSerializer.legacySection().deserialize(msg);
|
if (msg.contains("§")) return LegacyComponentSerializer.legacySection().deserialize(msg);
|
||||||
return LegacyComponentSerializer.legacyAmpersand().deserialize(msg);
|
return LegacyComponentSerializer.legacyAmpersand().deserialize(msg);
|
||||||
}
|
}
|
||||||
@@ -286,7 +289,7 @@ public class Text implements Main {
|
|||||||
* @param ampersands String with ampersand codes
|
* @param ampersands String with ampersand codes
|
||||||
* @return String with section codes
|
* @return String with section codes
|
||||||
*/
|
*/
|
||||||
public static String legacyAmpersandColor(String ampersands) {
|
public String legacyAmpersandColor(String ampersands) {
|
||||||
return ampersands.replaceAll("&","§");
|
return ampersands.replaceAll("&","§");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,7 +300,7 @@ public class Text implements Main {
|
|||||||
* @param args Arguments to replace placeholders
|
* @param args Arguments to replace placeholders
|
||||||
* @return Formatted component
|
* @return Formatted component
|
||||||
*/
|
*/
|
||||||
public static Component format(Pallet pallet, String text, Object... args) {
|
public Component format(Pallet pallet, String text, Object... args) {
|
||||||
return format(pallet, Component.text(text), Arrays.stream(args).map(arg->Component.text(arg.toString())).toArray(Component[]::new));
|
return format(pallet, Component.text(text), Arrays.stream(args).map(arg->Component.text(arg.toString())).toArray(Component[]::new));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,7 +312,7 @@ public class Text implements Main {
|
|||||||
* @param args Argument components to replace placeholders
|
* @param args Argument components to replace placeholders
|
||||||
* @return Formatted component with colors applied
|
* @return Formatted component with colors applied
|
||||||
*/
|
*/
|
||||||
public static Component format(Pallet pallet, ComponentLike text, ComponentLike... args) {
|
public Component format(Pallet pallet, ComponentLike text, ComponentLike... args) {
|
||||||
Component resultComponent = text.asComponent().color(pallet.mainText);
|
Component resultComponent = text.asComponent().color(pallet.mainText);
|
||||||
|
|
||||||
if (args == null || args.length == 0) {
|
if (args == null || args.length == 0) {
|
||||||
@@ -339,7 +342,7 @@ public class Text implements Main {
|
|||||||
* @param component The component to check.
|
* @param component The component to check.
|
||||||
* @return Currently always returns true, indicating recoloring should occur.
|
* @return Currently always returns true, indicating recoloring should occur.
|
||||||
*/
|
*/
|
||||||
private static boolean shouldRecolor(Component component) {
|
private boolean shouldRecolor(Component component) {
|
||||||
Set<TextColor> colors = new HashSet<>();
|
Set<TextColor> colors = new HashSet<>();
|
||||||
collectColors(component,colors);
|
collectColors(component,colors);
|
||||||
return colors.size() <= 1;
|
return colors.size() <= 1;
|
||||||
@@ -350,7 +353,7 @@ public class Text implements Main {
|
|||||||
* @param component The component to collect.
|
* @param component The component to collect.
|
||||||
* @param colors A mutable HashSet of colors.
|
* @param colors A mutable HashSet of colors.
|
||||||
*/
|
*/
|
||||||
private static void collectColors(Component component, Set<TextColor> colors) {
|
private void collectColors(Component component, Set<TextColor> colors) {
|
||||||
if (component.color() != null) {
|
if (component.color() != null) {
|
||||||
colors.add(component.color());
|
colors.add(component.color());
|
||||||
}
|
}
|
||||||
@@ -364,7 +367,7 @@ public class Text implements Main {
|
|||||||
* @param input The input string
|
* @param input The input string
|
||||||
* @return String with color codes removed
|
* @return String with color codes removed
|
||||||
*/
|
*/
|
||||||
public static String removeColors(String input) {
|
public String removeColors(String input) {
|
||||||
if (input == null) return null;
|
if (input == null) return null;
|
||||||
|
|
||||||
input = input.replaceAll("(?i)[&§][0-9a-fk-or]", ""); // Legacy colors
|
input = input.replaceAll("(?i)[&§][0-9a-fk-or]", ""); // Legacy colors
|
||||||
@@ -379,7 +382,7 @@ public class Text implements Main {
|
|||||||
* @param input The input component
|
* @param input The input component
|
||||||
* @return Component with plain text only
|
* @return Component with plain text only
|
||||||
*/
|
*/
|
||||||
public static Component removeColors(ComponentLike input) {
|
public Component removeColors(ComponentLike input) {
|
||||||
if (input == null) return Component.text("");
|
if (input == null) return Component.text("");
|
||||||
|
|
||||||
String plainText = PlainTextComponentSerializer.plainText().serialize(input.asComponent());
|
String plainText = PlainTextComponentSerializer.plainText().serialize(input.asComponent());
|
||||||
@@ -392,7 +395,7 @@ public class Text implements Main {
|
|||||||
* @param argIndex The argument index (0-indexed)
|
* @param argIndex The argument index (0-indexed)
|
||||||
* @return The appropriate TextColor for the argument
|
* @return The appropriate TextColor for the argument
|
||||||
*/
|
*/
|
||||||
private static TextColor getArgColor(Pallet pallet, int argIndex) {
|
private TextColor getArgColor(Pallet pallet, int argIndex) {
|
||||||
return switch (argIndex) {
|
return switch (argIndex) {
|
||||||
case 1 -> pallet.arg2;
|
case 1 -> pallet.arg2;
|
||||||
case 2 -> pallet.arg3;
|
case 2 -> pallet.arg3;
|
||||||
@@ -403,52 +406,49 @@ public class Text implements Main {
|
|||||||
/**
|
/**
|
||||||
* Represents a word extracted from a component with its formatting preserved.
|
* Represents a word extracted from a component with its formatting preserved.
|
||||||
*/
|
*/
|
||||||
private static record ComponentWord(Component component, int visibleLength) {}
|
private record ComponentWord(Component component, int visibleLength) {}
|
||||||
|
|
||||||
/**
|
|
||||||
* Color pallets for different message types with appropriate colors and sounds.
|
|
||||||
*/
|
|
||||||
public enum Pallet {
|
public enum Pallet {
|
||||||
ERROR(
|
ERROR(
|
||||||
TextColor.color(0xD3A6A4), // Soft red for main text
|
TextColor.color(0xD3A6A4),
|
||||||
TextColor.color(0xFFF1AE), // Light yellow for default args
|
TextColor.color(0xFFF1AE),
|
||||||
TextColor.color(0xFF796D), // Coral for second arg
|
TextColor.color(0xFF796D),
|
||||||
TextColor.color(0xC62828), // Dark red for third arg
|
TextColor.color(0xC62828),
|
||||||
new SoundData(Sound.BLOCK_NOTE_BLOCK_BASS, 1)
|
new SoundData(Sound.BLOCK_NOTE_BLOCK_BASS, 1)
|
||||||
),
|
),
|
||||||
WARNING(
|
WARNING(
|
||||||
TextColor.color(0xFFF3CD), // Light yellow for main text
|
TextColor.color(0xFFF3CD),
|
||||||
TextColor.color(0xFFF9F5), // Very light cream for default args
|
TextColor.color(0xFFF9F5),
|
||||||
TextColor.color(0xFFD54F), // Gold for second arg
|
TextColor.color(0xFFD54F),
|
||||||
TextColor.color(0xFFA000), // Orange for third arg
|
TextColor.color(0xFFA000),
|
||||||
new SoundData(Sound.BLOCK_NOTE_BLOCK_BIT, 0.5F)
|
new SoundData(Sound.BLOCK_NOTE_BLOCK_BIT, 0.5F)
|
||||||
),
|
),
|
||||||
INFO(
|
INFO(
|
||||||
TextColor.color(0xBBDEFB), // Light blue for main text
|
TextColor.color(0xBBDEFB),
|
||||||
TextColor.color(0xD2D0EA), // Light lavender for default args
|
TextColor.color(0xD2D0EA),
|
||||||
TextColor.color(0x64B5F6), // Medium blue for second arg
|
TextColor.color(0x64B5F6),
|
||||||
TextColor.color(0x1976D2), // Dark blue for third arg
|
TextColor.color(0x1976D2),
|
||||||
new SoundData(Sound.BLOCK_NOTE_BLOCK_CHIME, 0.7F)
|
new SoundData(Sound.BLOCK_NOTE_BLOCK_CHIME, 0.7F)
|
||||||
),
|
),
|
||||||
SUCCESS(
|
SUCCESS(
|
||||||
TextColor.color(0xCDFFC7), // Light green for main text
|
TextColor.color(0xCDFFC7),
|
||||||
TextColor.color(0xFFFFFF), // White for default args
|
TextColor.color(0xFFFFFF),
|
||||||
TextColor.color(0xB0FFE3), // Light mint for second arg
|
TextColor.color(0xB0FFE3),
|
||||||
TextColor.color(0x63CD83), // Medium green for third arg
|
TextColor.color(0x63CD83),
|
||||||
new SoundData(Sound.BLOCK_NOTE_BLOCK_PLING, 1.5F)
|
new SoundData(Sound.BLOCK_NOTE_BLOCK_PLING, 1.5F)
|
||||||
),
|
),
|
||||||
NEUTRAL(
|
NEUTRAL(
|
||||||
TextColor.color(0xD3D3D3), // Light gray for main text
|
TextColor.color(0xD3D3D3),
|
||||||
TextColor.color(0xFFFFFF), // White for default args
|
TextColor.color(0xFFFFFF),
|
||||||
TextColor.color(0xFFB3F8), // Light pink for second arg
|
TextColor.color(0xFFB3F8),
|
||||||
TextColor.color(0xE280FF), // Purple for third arg
|
TextColor.color(0xE280FF),
|
||||||
new SoundData(Sound.BLOCK_NOTE_BLOCK_BELL, 1)
|
new SoundData(Sound.BLOCK_NOTE_BLOCK_BELL, 1)
|
||||||
),
|
),
|
||||||
LOCATION(
|
LOCATION(
|
||||||
TextColor.color(0xAAAAAA), // Gray for main text
|
TextColor.color(0xAAAAAA),
|
||||||
TextColor.color(0xFFB0C1), // Light pink for default args
|
TextColor.color(0xFFB0C1),
|
||||||
TextColor.color(0xB6F5B6), // Light green for second arg
|
TextColor.color(0xB6F5B6),
|
||||||
TextColor.color(0xB0C1FF), // Light blue for third arg
|
TextColor.color(0xB0C1FF),
|
||||||
new SoundData(Sound.UI_TOAST_IN, 2)
|
new SoundData(Sound.UI_TOAST_IN, 2)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -1,22 +1,28 @@
|
|||||||
package me.trouper.alias.server.systems;
|
package me.trouper.alias.server.systems;
|
||||||
|
|
||||||
import me.trouper.alias.server.Main;
|
import me.trouper.alias.AliasContext;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.util.Vector;
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
public class Verbose implements Main {
|
public class Verbose {
|
||||||
|
|
||||||
|
private final AliasContext context;
|
||||||
|
|
||||||
|
public Verbose(AliasContext context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A dynamic verbose system which uses the format from the {@link Text} system.
|
* A Uses the format from the {@link Text} system.
|
||||||
* @param backtrace The number of calls up the stacktrace to go.
|
* @param backtrace The number of calls up the stacktrace to go.
|
||||||
* @param verbose A message with 0 indexed curly brace placeholders. {0}, {1}, {2}...
|
* @param verbose A message with 0 indexed curly brace placeholders. {0}, {1}, {2}...
|
||||||
* @param args Qualified placeholder values.
|
* @param args Qualified placeholder values.
|
||||||
*/
|
*/
|
||||||
public static void send(int backtrace, String verbose, Object... args) {
|
public void send(int backtrace, String verbose, Object... args) {
|
||||||
if (!main.getCommon().getDebugMode()) return;
|
if (!context.getCommon().getDebugMode()) return;
|
||||||
String callerInfo = "Unknown Caller";
|
String callerInfo = "Unknown Caller";
|
||||||
|
|
||||||
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
|
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
|
||||||
@@ -28,20 +34,20 @@ public class Verbose implements Main {
|
|||||||
if (className.contains("-")) callerInfo = "Protected";
|
if (className.contains("-")) callerInfo = "Protected";
|
||||||
else callerInfo = className + "." + caller.getMethodName();
|
else callerInfo = className + "." + caller.getMethodName();
|
||||||
|
|
||||||
if (main.getCommon().getDebuggerExclusions().contains(callerInfo)) return;
|
if (context.getCommon().getDebuggerExclusions().contains(callerInfo)) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object[] processedArgs = processArgs(args);
|
Object[] processedArgs = processArgs(args);
|
||||||
Component message = Text.format(Text.Pallet.INFO, verbose, processedArgs);
|
Component message = context.getText().format(Text.Pallet.INFO, verbose, processedArgs);
|
||||||
message = Text.format(Text.Pallet.INFO,
|
message = context.getText().format(Text.Pallet.INFO,
|
||||||
Component.text("{0} [DEBUG ^ {1}] [{2}] » {3}"),
|
Component.text("{0} [DEBUG ^ {1}] [{2}] » {3}"),
|
||||||
Component.text(main.getCommon().getPluginName()),
|
Component.text(context.getCommon().getPluginName()),
|
||||||
Component.text(backtrace),
|
Component.text(backtrace),
|
||||||
Component.text(callerInfo),
|
Component.text(callerInfo),
|
||||||
message
|
message
|
||||||
);
|
);
|
||||||
|
|
||||||
main.getPlugin().getComponentLogger().info(message);
|
context.getPlugin().getComponentLogger().info(message);
|
||||||
|
|
||||||
for (Player operator : Bukkit.getOnlinePlayers()) {
|
for (Player operator : Bukkit.getOnlinePlayers()) {
|
||||||
if (!operator.isOp()) continue;
|
if (!operator.isOp()) continue;
|
||||||
@@ -50,15 +56,15 @@ public class Verbose implements Main {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A dynamic verbose system which uses the format from the {@link Text} system.
|
* Uses the format from the {@link Text} system.
|
||||||
* @param verbose A message with 0 indexed curly brace placeholders. {0}, {1}, {2}...
|
* @param verbose A message with 0 indexed curly brace placeholders. {0}, {1}, {2}...
|
||||||
* @param args Qualified placeholder values.
|
* @param args Qualified placeholder values.
|
||||||
*/
|
*/
|
||||||
public static void send(String verbose, Object... args) {
|
public void send(String verbose, Object... args) {
|
||||||
send(1,verbose,args);
|
send(1,verbose,args);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Object[] processArgs(Object... args) {
|
private Object[] processArgs(Object... args) {
|
||||||
Object[] processed = new Object[args.length];
|
Object[] processed = new Object[args.length];
|
||||||
|
|
||||||
for (int i = 0; i < args.length; i++) {
|
for (int i = 0; i < args.length; i++) {
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package me.trouper.alias.server.systems.display;
|
||||||
|
|
||||||
|
import me.trouper.alias.AliasContext;
|
||||||
|
import me.trouper.alias.server.systems.display.tracing.BlockDisplayRaytracer;
|
||||||
|
import me.trouper.alias.server.systems.display.tracing.CustomRaytracer;
|
||||||
|
import me.trouper.alias.server.systems.display.visual.Outliner;
|
||||||
|
import me.trouper.alias.server.systems.display.visual.Patterns;
|
||||||
|
|
||||||
|
public class DisplayManager {
|
||||||
|
private final Patterns patterns;
|
||||||
|
private final Outliner outliner;
|
||||||
|
private final BlockDisplayRaytracer blockDisplayRaytracer;
|
||||||
|
private final CustomRaytracer customRaytracer;
|
||||||
|
|
||||||
|
public DisplayManager(AliasContext context) {
|
||||||
|
this.patterns = new Patterns(context);
|
||||||
|
this.blockDisplayRaytracer = new BlockDisplayRaytracer(context);
|
||||||
|
this.outliner = new Outliner(blockDisplayRaytracer);
|
||||||
|
this.customRaytracer = new CustomRaytracer(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Patterns getPatterns() { return patterns; }
|
||||||
|
public Outliner getOutliner() { return outliner; }
|
||||||
|
public BlockDisplayRaytracer getBlockDisplayRaytracer() { return blockDisplayRaytracer; }
|
||||||
|
public CustomRaytracer getCustomRaytracer() { return customRaytracer; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,213 @@
|
|||||||
|
package me.trouper.alias.server.systems.display.tracing;
|
||||||
|
|
||||||
|
import me.trouper.alias.AliasContext;
|
||||||
|
import org.bukkit.*;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.entity.BlockDisplay;
|
||||||
|
import org.bukkit.entity.Display;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
import org.bukkit.util.BoundingBox;
|
||||||
|
import org.bukkit.util.Transformation;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
import org.bukkit.util.VoxelShape;
|
||||||
|
import org.joml.AxisAngle4f;
|
||||||
|
import org.joml.Vector3f;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
public class BlockDisplayRaytracer {
|
||||||
|
|
||||||
|
private final AliasContext context;
|
||||||
|
|
||||||
|
public BlockDisplayRaytracer(AliasContext context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cleanup() {
|
||||||
|
JavaPlugin plugin = context.getPlugin();
|
||||||
|
List<World> worlds = plugin.getServer().getWorlds();
|
||||||
|
List<Entity> entities = new ArrayList<>();
|
||||||
|
for (World world : worlds) {
|
||||||
|
entities.addAll(world.getEntities().stream().filter(entity -> entity.getScoreboardTags().contains(context.getCommon().getTempTag())).toList());
|
||||||
|
entities.forEach(entity -> {
|
||||||
|
if (entity != null) entity.remove();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void trace(Material display, Location start, Location end, long stayTime, List<Player> viewers) {
|
||||||
|
trace(display, start, end.toVector().subtract(start.toVector()), 0.05, end.distance(start), stayTime, viewers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void trace(Material display, Location start, Location end, double thickness, long stayTime, List<Player> viewers) {
|
||||||
|
trace(display, start, end.toVector().subtract(start.toVector()), thickness, end.distance(start), stayTime, viewers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void trace(Material display, Location start, Vector direction, double thickness, double distance, long stayTime, List<Player> viewers) {
|
||||||
|
World world = start.getWorld();
|
||||||
|
|
||||||
|
BlockDisplay beam = world.spawn(start, BlockDisplay.class, entity -> {
|
||||||
|
AxisAngle4f angle = new AxisAngle4f(0, 0, 0, 1);
|
||||||
|
Vector3f transition = new Vector3f(-(float)(thickness / 2F));
|
||||||
|
Vector3f scale = new Vector3f((float)thickness, (float)thickness, (float)distance);
|
||||||
|
Transformation trans = new Transformation(transition, angle, scale, angle);
|
||||||
|
Location vector = entity.getLocation();
|
||||||
|
|
||||||
|
vector.setDirection(direction);
|
||||||
|
entity.teleport(vector);
|
||||||
|
entity.setBlock(display.createBlockData());
|
||||||
|
entity.setBrightness(new Display.Brightness(15, 15));
|
||||||
|
entity.setInterpolationDelay(0);
|
||||||
|
entity.setTransformation(trans);
|
||||||
|
entity.addScoreboardTag(context.getCommon().getTempTag());
|
||||||
|
|
||||||
|
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||||
|
if (!viewers.contains(player)) {
|
||||||
|
player.hideEntity(context.getPlugin(), entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Bukkit.getScheduler().runTaskLater(context.getPlugin(), entity::remove, stayTime);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void trace(Material display, Location start, Vector direction, double thickness, double distance, long stayTime, Consumer<BlockDisplay> onEntitySpawn, List<Player> viewers) {
|
||||||
|
World world = start.getWorld();
|
||||||
|
|
||||||
|
BlockDisplay beam = world.spawn(start, BlockDisplay.class, entity -> {
|
||||||
|
AxisAngle4f angle = new AxisAngle4f(0, 0, 0, 1);
|
||||||
|
Vector3f transition = new Vector3f(-(float)(thickness / 2F));
|
||||||
|
Vector3f scale = new Vector3f((float)thickness, (float)thickness, (float)distance);
|
||||||
|
Transformation trans = new Transformation(transition, angle, scale, angle);
|
||||||
|
Location vector = entity.getLocation();
|
||||||
|
|
||||||
|
vector.setDirection(direction);
|
||||||
|
entity.teleport(vector);
|
||||||
|
entity.setBlock(display.createBlockData());
|
||||||
|
entity.setBrightness(new Display.Brightness(15, 15));
|
||||||
|
entity.setInterpolationDelay(0);
|
||||||
|
entity.setTransformation(trans);
|
||||||
|
entity.addScoreboardTag(context.getCommon().getTempTag());
|
||||||
|
|
||||||
|
|
||||||
|
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||||
|
if (!viewers.contains(player)) {
|
||||||
|
player.hideEntity(context.getPlugin(), entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Bukkit.getScheduler().runTaskLater(context.getPlugin(), entity::remove, stayTime);
|
||||||
|
Bukkit.getScheduler().runTaskLater(context.getPlugin(), () -> onEntitySpawn.accept(entity), 5);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void traceGlowing(World world, double x1, double y1, double z1, double x2, double y2, double z2, Color color, long stayTime) {
|
||||||
|
Location loc1 = new Location(world, x1, y1, z1);
|
||||||
|
Location loc2 = new Location(world, x2, y2, z2);
|
||||||
|
BlockDisplay ent = trace(Material.WHITE_CONCRETE, loc1, loc2, 0.01, stayTime);
|
||||||
|
ent.setGlowColorOverride(color);
|
||||||
|
ent.setGlowing(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockDisplay trace(Material display, Location start, Location end, long stayTime) {
|
||||||
|
return trace(display, start, end.toVector().subtract(start.toVector()), 0.05, end.distance(start), stayTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockDisplay trace(Material display, Location start, Location end, double thickness, long stayTime) {
|
||||||
|
return trace(display, start, end.toVector().subtract(start.toVector()), thickness, end.distance(start), stayTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockDisplay trace(Material display, Location start, Vector direction, double thickness, double distance, long stayTime) {
|
||||||
|
World world = start.getWorld();
|
||||||
|
|
||||||
|
BlockDisplay entity = world.spawn(start, BlockDisplay.class);
|
||||||
|
AxisAngle4f angle = new AxisAngle4f(0, 0, 0, 1);
|
||||||
|
Vector3f transition = new Vector3f(-(float)(thickness / 2F));
|
||||||
|
Vector3f scale = new Vector3f((float)thickness, (float)thickness, (float)distance);
|
||||||
|
Transformation trans = new Transformation(transition, angle, scale, angle);
|
||||||
|
Location vector = entity.getLocation();
|
||||||
|
|
||||||
|
vector.setDirection(direction);
|
||||||
|
entity.teleport(vector);
|
||||||
|
entity.setBlock(display.createBlockData());
|
||||||
|
entity.setBrightness(new Display.Brightness(15, 15));
|
||||||
|
entity.setInterpolationDelay(0);
|
||||||
|
entity.setTransformation(trans);
|
||||||
|
entity.addScoreboardTag(context.getCommon().getTempTag());
|
||||||
|
|
||||||
|
Bukkit.getScheduler().runTaskLater(context.getPlugin(), entity::remove, stayTime);
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void transform(BlockDisplay display, Location start, Location end, double thickness) {
|
||||||
|
Vector direction = end.toVector().subtract(start.toVector());
|
||||||
|
double distance = direction.length();
|
||||||
|
|
||||||
|
Location loc = start.clone();
|
||||||
|
loc.setDirection(direction);
|
||||||
|
display.teleport(loc);
|
||||||
|
|
||||||
|
Vector3f translation = new Vector3f(-(float)(thickness / 2F), 0, 0); // Centered
|
||||||
|
Vector3f scale = new Vector3f((float)thickness, (float)thickness, (float)distance);
|
||||||
|
AxisAngle4f rotation = new AxisAngle4f(0, 0, 0, 1);
|
||||||
|
Transformation transformation = new Transformation(translation, rotation, scale, rotation);
|
||||||
|
|
||||||
|
display.setTransformation(transformation);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void transform(BlockDisplay display, Location start, Vector direction, double distance, double thickness) {
|
||||||
|
Location loc = start.clone();
|
||||||
|
loc.setDirection(direction);
|
||||||
|
display.teleport(loc);
|
||||||
|
|
||||||
|
Vector3f translation = new Vector3f(-(float)(thickness / 2F), 0, 0);
|
||||||
|
Vector3f scale = new Vector3f((float)thickness, (float)thickness, (float)distance);
|
||||||
|
AxisAngle4f rotation = new AxisAngle4f(0, 0, 0, 1);
|
||||||
|
Transformation transformation = new Transformation(translation, rotation, scale, rotation);
|
||||||
|
|
||||||
|
display.setTransformation(transformation);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void translate(BlockDisplay display, Vector3f offset) {
|
||||||
|
Transformation current = display.getTransformation();
|
||||||
|
Vector3f translation = new Vector3f(current.getTranslation()).add(offset);
|
||||||
|
display.setTransformation(new Transformation(
|
||||||
|
translation,
|
||||||
|
current.getLeftRotation(),
|
||||||
|
current.getScale(),
|
||||||
|
current.getRightRotation()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void scale(BlockDisplay display, Vector3f scale) {
|
||||||
|
Transformation current = display.getTransformation();
|
||||||
|
display.setTransformation(new Transformation(
|
||||||
|
current.getTranslation(),
|
||||||
|
current.getLeftRotation(),
|
||||||
|
scale,
|
||||||
|
current.getRightRotation()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void rotate(BlockDisplay display, AxisAngle4f rotation) {
|
||||||
|
Transformation current = display.getTransformation();
|
||||||
|
display.setTransformation(new Transformation(
|
||||||
|
current.getTranslation(),
|
||||||
|
rotation,
|
||||||
|
current.getScale(),
|
||||||
|
rotation
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void alignToDirection(BlockDisplay display, Vector direction) {
|
||||||
|
Location loc = display.getLocation().clone();
|
||||||
|
loc.setDirection(direction);
|
||||||
|
display.teleport(loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package me.trouper.alias.server.systems.tracing;
|
package me.trouper.alias.server.systems.display.tracing;
|
||||||
|
|
||||||
|
import me.trouper.alias.AliasContext;
|
||||||
import org.bukkit.FluidCollisionMode;
|
import org.bukkit.FluidCollisionMode;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
@@ -19,7 +20,13 @@ import java.util.Random;
|
|||||||
import java.util.function.BiPredicate;
|
import java.util.function.BiPredicate;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
public class CustomDisplayRaytracer {
|
public class CustomRaytracer {
|
||||||
|
|
||||||
|
private final AliasContext context;
|
||||||
|
|
||||||
|
public CustomRaytracer(AliasContext context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
public static final Predicate<Point> HIT_BLOCK = point -> {
|
public static final Predicate<Point> HIT_BLOCK = point -> {
|
||||||
Block b = point.getBlock();
|
Block b = point.getBlock();
|
||||||
@@ -77,22 +84,22 @@ public class CustomDisplayRaytracer {
|
|||||||
return point -> HIT_BLOCK.test(point) && !point.getNearbyEntities(null, 5, true, 0.1, e -> e instanceof LivingEntity le && !le.isDead() && condition.test(e)).isEmpty();
|
return point -> HIT_BLOCK.test(point) && !point.getNearbyEntities(null, 5, true, 0.1, e -> e instanceof LivingEntity le && !le.isDead() && condition.test(e)).isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Point trace(Location start, Location end, Predicate<Point> hitCondition) {
|
public Point trace(Location start, Location end, Predicate<Point> hitCondition) {
|
||||||
return trace(start, end, 0.5, hitCondition);
|
return trace(start, end, 0.5, hitCondition);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Point trace(Location start, Location end, double interval, Predicate<Point> hitCondition) {
|
public Point trace(Location start, Location end, double interval, Predicate<Point> hitCondition) {
|
||||||
Vector direction = end.toVector().subtract(start.toVector()).normalize();
|
Vector direction = end.toVector().subtract(start.toVector()).normalize();
|
||||||
double distance = end.distance(start);
|
double distance = end.distance(start);
|
||||||
return trace(start, direction, distance, interval, hitCondition);
|
return trace(start, direction, distance, interval, hitCondition);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Point trace(Location start, Vector direction, double distance, Predicate<Point> hitCondition) {
|
public Point trace(Location start, Vector direction, double distance, Predicate<Point> hitCondition) {
|
||||||
Vector normal = direction.clone().normalize();
|
Vector normal = direction.clone().normalize();
|
||||||
return trace(start, normal, distance, 0.5, hitCondition);
|
return trace(start, normal, distance, 0.5, hitCondition);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Point trace(Location start, Vector direction, double distance, double interval, Predicate<Point> hitCondition) {
|
public Point trace(Location start, Vector direction, double distance, double interval, Predicate<Point> hitCondition) {
|
||||||
if (interval < 0) throw new IllegalArgumentException("interval cannot be zero!");
|
if (interval < 0) throw new IllegalArgumentException("interval cannot be zero!");
|
||||||
if (distance < 0) throw new IllegalArgumentException("distance cannot be zero!");
|
if (distance < 0) throw new IllegalArgumentException("distance cannot be zero!");
|
||||||
|
|
||||||
@@ -106,7 +113,7 @@ public class CustomDisplayRaytracer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static BukkitTask traceDelayed(Plugin plugin, Location start, Vector direction, double distance, double interval, long tickDelay, int pointsPerTick, Predicate<Point> hitCondition) {
|
public BukkitTask traceDelayed(Location start, Vector direction, double distance, double interval, long tickDelay, int pointsPerTick, Predicate<Point> hitCondition) {
|
||||||
|
|
||||||
if (interval <= 0) throw new IllegalArgumentException("interval cannot be zero or negative!");
|
if (interval <= 0) throw new IllegalArgumentException("interval cannot be zero or negative!");
|
||||||
if (distance <= 0) throw new IllegalArgumentException("distance cannot be zero or negative!");
|
if (distance <= 0) throw new IllegalArgumentException("distance cannot be zero or negative!");
|
||||||
@@ -114,7 +121,6 @@ public class CustomDisplayRaytracer {
|
|||||||
|
|
||||||
Vector normalizedDir = direction.clone().normalize();
|
Vector normalizedDir = direction.clone().normalize();
|
||||||
|
|
||||||
|
|
||||||
return new BukkitRunnable() {
|
return new BukkitRunnable() {
|
||||||
private double currentDistance = 0.0;
|
private double currentDistance = 0.0;
|
||||||
private boolean hit = false;
|
private boolean hit = false;
|
||||||
@@ -139,33 +145,33 @@ public class CustomDisplayRaytracer {
|
|||||||
currentDistance += interval;
|
currentDistance += interval;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.runTaskTimer(plugin, 0, tickDelay);
|
}.runTaskTimer(context.getPlugin(), 0, tickDelay);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BukkitTask traceDelayed(Plugin plugin, Location start, Location end, double interval, long tickDelay, int pointsPerTick, Predicate<Point> hitCondition) {
|
public BukkitTask traceDelayed(Location start, Location end, double interval, long tickDelay, int pointsPerTick, Predicate<Point> hitCondition) {
|
||||||
Vector direction = end.toVector().subtract(start.toVector()).normalize();
|
Vector direction = end.toVector().subtract(start.toVector()).normalize();
|
||||||
double distance = start.distance(end);
|
double distance = start.distance(end);
|
||||||
return traceDelayed(plugin, start, direction, distance, interval, tickDelay,pointsPerTick, hitCondition);
|
return traceDelayed(start, direction, distance, interval, tickDelay,pointsPerTick, hitCondition);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BukkitTask traceDelayed(Plugin plugin,
|
public BukkitTask traceDelayed(Plugin plugin,
|
||||||
Location start,
|
Location start,
|
||||||
Location end,
|
Location end,
|
||||||
long tickDelay,
|
long tickDelay,
|
||||||
Predicate<Point> hitCondition) {
|
Predicate<Point> hitCondition) {
|
||||||
return traceDelayed(plugin, start, end,0.5, tickDelay, 1, hitCondition);
|
return traceDelayed(start, end,0.5, tickDelay, 1, hitCondition);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BukkitTask traceDelayed(Plugin plugin,
|
public BukkitTask traceDelayed(Plugin plugin,
|
||||||
Location start,
|
Location start,
|
||||||
Vector direction,
|
Vector direction,
|
||||||
double distance,
|
double distance,
|
||||||
long tickDelay,
|
long tickDelay,
|
||||||
Predicate<Point> hitCondition) {
|
Predicate<Point> hitCondition) {
|
||||||
return traceDelayed(plugin, start, direction, distance, 0.5, tickDelay,1, hitCondition);
|
return traceDelayed(start, direction, distance, 0.5, tickDelay,1, hitCondition);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Point traceWithReflection(Location start, Vector direction, double distance, double interval,
|
public Point traceWithReflection(Location start, Vector direction, double distance, double interval,
|
||||||
int maxReflections, Predicate<Point> hitCondition,
|
int maxReflections, Predicate<Point> hitCondition,
|
||||||
BiPredicate<Point, Block> blockReflectCondition,
|
BiPredicate<Point, Block> blockReflectCondition,
|
||||||
BiPredicate<Point, Entity> entityReflectCondition) {
|
BiPredicate<Point, Entity> entityReflectCondition) {
|
||||||
@@ -236,25 +242,23 @@ public class CustomDisplayRaytracer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (i + interval >= remainingDistance) {
|
if (i + interval >= remainingDistance) {
|
||||||
Point finalPoint = blocksInFrontOf(currentLocation, currentDirection, remainingDistance, true);
|
return blocksInFrontOf(currentLocation, currentDirection, remainingDistance, true);
|
||||||
return finalPoint;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reflections > maxReflections) {
|
if (reflections > maxReflections) {
|
||||||
Point finalPoint = blocksInFrontOf(currentLocation, currentDirection, remainingDistance, true);
|
return blocksInFrontOf(currentLocation, currentDirection, remainingDistance, true);
|
||||||
return finalPoint;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return blocksInFrontOf(start, normalizedDir, distance, true);
|
return blocksInFrontOf(start, normalizedDir, distance, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Vector glanceReflect(Vector incident) {
|
private Vector glanceReflect(Vector incident) {
|
||||||
return offsetVector(incident,4).multiply(-1);
|
return offsetVector(incident,4).multiply(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static BlockFace traceBlockFace(Location startLocation, Vector direction, double maxDistance) {
|
private BlockFace traceBlockFace(Location startLocation, Vector direction, double maxDistance) {
|
||||||
Predicate<Block> blockPredicate = block -> true;
|
Predicate<Block> blockPredicate = block -> true;
|
||||||
Predicate<Entity> entityPredicate = entity -> false;
|
Predicate<Entity> entityPredicate = entity -> false;
|
||||||
|
|
||||||
@@ -267,7 +271,7 @@ public class CustomDisplayRaytracer {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Vector calculateReflection(Vector incident, Vector normal) {
|
private Vector calculateReflection(Vector incident, Vector normal) {
|
||||||
// r = i - 2(i dot n)n
|
// r = i - 2(i dot n)n
|
||||||
double dot = incident.dot(normal);
|
double dot = incident.dot(normal);
|
||||||
Vector reflection = incident.clone().subtract(normal.clone().multiply(2 * dot));
|
Vector reflection = incident.clone().subtract(normal.clone().multiply(2 * dot));
|
||||||
@@ -275,7 +279,7 @@ public class CustomDisplayRaytracer {
|
|||||||
return reflection.normalize();
|
return reflection.normalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Vector getFaceNormal(BlockFace face) {
|
private Vector getFaceNormal(BlockFace face) {
|
||||||
return switch (face) {
|
return switch (face) {
|
||||||
case DOWN -> new Vector(0, -1, 0);
|
case DOWN -> new Vector(0, -1, 0);
|
||||||
case NORTH -> new Vector(0, 0, -1);
|
case NORTH -> new Vector(0, 0, -1);
|
||||||
@@ -286,12 +290,12 @@ public class CustomDisplayRaytracer {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Point blocksInFrontOf(Location loc, Vector dir, double blocks, boolean missed) {
|
public Point blocksInFrontOf(Location loc, Vector dir, double blocks, boolean missed) {
|
||||||
Vector normal = dir.clone().normalize();
|
Vector normal = dir.clone().normalize();
|
||||||
return new Point(loc.clone().add(normal.getX() * blocks, normal.getY() * blocks, normal.getZ() * blocks), blocks, missed);
|
return new Point(loc.clone().add(normal.getX() * blocks, normal.getY() * blocks, normal.getZ() * blocks), blocks, missed);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Vector offsetVector(Vector original, double angleDegrees) {
|
private Vector offsetVector(Vector original, double angleDegrees) {
|
||||||
Random random = new Random();
|
Random random = new Random();
|
||||||
original = original.clone().normalize();
|
original = original.clone().normalize();
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package me.trouper.alias.server.systems.tracing;
|
package me.trouper.alias.server.systems.display.tracing;
|
||||||
|
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
@@ -0,0 +1,169 @@
|
|||||||
|
package me.trouper.alias.server.systems.display.visual;
|
||||||
|
|
||||||
|
import me.trouper.alias.server.systems.display.tracing.BlockDisplayRaytracer;
|
||||||
|
import org.bukkit.Color;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.entity.BlockDisplay;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.util.BoundingBox;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
import org.bukkit.util.VoxelShape;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Outliner {
|
||||||
|
|
||||||
|
private final BlockDisplayRaytracer rt;
|
||||||
|
|
||||||
|
public Outliner(BlockDisplayRaytracer raytracer) {
|
||||||
|
this.rt = raytracer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void highlightCollisions(Block block, Color color, long stayTime) {
|
||||||
|
if (block == null || block.isEmpty() || !block.isCollidable())
|
||||||
|
return;
|
||||||
|
|
||||||
|
VoxelShape shape = block.getCollisionShape();
|
||||||
|
World world = block.getWorld();
|
||||||
|
Vector offset = block.getLocation().toVector();
|
||||||
|
|
||||||
|
for (BoundingBox box : shape.getBoundingBoxes()) {
|
||||||
|
highlight(box, offset, world, color, stayTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<BlockDisplay> outline(Material display, Location location, long stayTime) {
|
||||||
|
return outline(display, location, 0.05, stayTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<BlockDisplay> outline(Material display, Location location, double thickness, long stayTime) {
|
||||||
|
Location og = location.getBlock().getLocation();
|
||||||
|
|
||||||
|
Location a1 = og.clone().add(0, 0, 0);
|
||||||
|
Location a2 = og.clone().add(1, 0, 0);
|
||||||
|
Location a3 = og.clone().add(1, 0, 1);
|
||||||
|
Location a4 = og.clone().add(0, 0, 1);
|
||||||
|
|
||||||
|
Location b1 = og.clone().add(0, 1, 0);
|
||||||
|
Location b2 = og.clone().add(1, 1, 0);
|
||||||
|
Location b3 = og.clone().add(1, 1, 1);
|
||||||
|
Location b4 = og.clone().add(0, 1, 1);
|
||||||
|
|
||||||
|
List<BlockDisplay> a = new ArrayList<>();
|
||||||
|
|
||||||
|
a.add(rt.trace(display, a1, a2, thickness, stayTime));
|
||||||
|
a.add(rt.trace(display, a2, a3, thickness, stayTime));
|
||||||
|
a.add(rt.trace(display, a3, a4, thickness, stayTime));
|
||||||
|
a.add(rt.trace(display, a4, a1, thickness, stayTime));
|
||||||
|
|
||||||
|
a.add(rt.trace(display, b1, b2, thickness, stayTime));
|
||||||
|
a.add(rt.trace(display, b2, b3, thickness, stayTime));
|
||||||
|
a.add(rt.trace(display, b3, b4, thickness, stayTime));
|
||||||
|
a.add(rt.trace(display, b4, b1, thickness, stayTime));
|
||||||
|
|
||||||
|
a.add(rt.trace(display, a1, b1, thickness, stayTime));
|
||||||
|
a.add(rt.trace(display, a2, b2, thickness, stayTime));
|
||||||
|
a.add(rt.trace(display, a3, b3, thickness, stayTime));
|
||||||
|
a.add(rt.trace(display, a4, b4, thickness, stayTime));
|
||||||
|
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void highlight(BoundingBox box, Vector offset, World world, Color color, long stayTime) {
|
||||||
|
double x1 = box.getMinX() + offset.getX();
|
||||||
|
double y1 = box.getMinY() + offset.getY();
|
||||||
|
double z1 = box.getMinZ() + offset.getZ();
|
||||||
|
double x2 = box.getMaxX() + offset.getX();
|
||||||
|
double y2 = box.getMaxY() + offset.getY();
|
||||||
|
double z2 = box.getMaxZ() + offset.getZ();
|
||||||
|
|
||||||
|
rt.traceGlowing(world, x1, y1, z1, x2, y1, z1, color, stayTime);
|
||||||
|
rt.traceGlowing(world, x2, y1, z1, x2, y1, z2, color, stayTime);
|
||||||
|
rt.traceGlowing(world, x2, y1, z2, x1, y1, z2, color, stayTime);
|
||||||
|
rt.traceGlowing(world, x1, y1, z2, x1, y1, z1, color, stayTime);
|
||||||
|
|
||||||
|
rt.traceGlowing(world, x1, y2, z1, x2, y2, z1, color, stayTime);
|
||||||
|
rt.traceGlowing(world, x2, y2, z1, x2, y2, z2, color, stayTime);
|
||||||
|
rt.traceGlowing(world, x2, y2, z2, x1, y2, z2, color, stayTime);
|
||||||
|
rt.traceGlowing(world, x1, y2, z2, x1, y2, z1, color, stayTime);
|
||||||
|
|
||||||
|
rt.traceGlowing(world, x1, y1, z1, x1, y2, z1, color, stayTime);
|
||||||
|
rt.traceGlowing(world, x2, y1, z1, x2, y2, z1, color, stayTime);
|
||||||
|
rt.traceGlowing(world, x2, y1, z2, x2, y2, z2, color, stayTime);
|
||||||
|
rt.traceGlowing(world, x1, y1, z2, x1, y2, z2, color, stayTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void outline(Material display, Location location, long stayTime, List<Player> viewers) {
|
||||||
|
outline(display, location, 0.05, stayTime, viewers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void outline(Material display, Location corner1, Location corner2, double thickness, long stayTime, List<Player> viewers) {
|
||||||
|
World world = corner1.getWorld();
|
||||||
|
|
||||||
|
int minX = Math.min(corner1.getBlockX(), corner2.getBlockX());
|
||||||
|
int minY = Math.min(corner1.getBlockY(), corner2.getBlockY());
|
||||||
|
int minZ = Math.min(corner1.getBlockZ(), corner2.getBlockZ());
|
||||||
|
int maxX = Math.max(corner1.getBlockX(), corner2.getBlockX());
|
||||||
|
int maxY = Math.max(corner1.getBlockY(), corner2.getBlockY());
|
||||||
|
int maxZ = Math.max(corner1.getBlockZ(), corner2.getBlockZ());
|
||||||
|
|
||||||
|
Location a1 = new Location(world, minX, minY, minZ);
|
||||||
|
Location a2 = new Location(world, maxX + 1, minY, minZ);
|
||||||
|
Location a3 = new Location(world, maxX + 1, minY, maxZ + 1);
|
||||||
|
Location a4 = new Location(world, minX, minY, maxZ + 1);
|
||||||
|
|
||||||
|
Location b1 = new Location(world, minX, maxY + 1, minZ);
|
||||||
|
Location b2 = new Location(world, maxX + 1, maxY + 1, minZ);
|
||||||
|
Location b3 = new Location(world, maxX + 1, maxY + 1, maxZ + 1);
|
||||||
|
Location b4 = new Location(world, minX, maxY + 1, maxZ + 1);
|
||||||
|
|
||||||
|
rt.trace(display, a1, a2, thickness, stayTime, viewers);
|
||||||
|
rt.trace(display, a2, a3, thickness, stayTime, viewers);
|
||||||
|
rt.trace(display, a3, a4, thickness, stayTime, viewers);
|
||||||
|
rt.trace(display, a4, a1, thickness, stayTime, viewers);
|
||||||
|
|
||||||
|
rt.trace(display, b1, b2, thickness, stayTime, viewers);
|
||||||
|
rt.trace(display, b2, b3, thickness, stayTime, viewers);
|
||||||
|
rt.trace(display, b3, b4, thickness, stayTime, viewers);
|
||||||
|
rt.trace(display, b4, b1, thickness, stayTime, viewers);
|
||||||
|
|
||||||
|
rt.trace(display, a1, b1, thickness, stayTime, viewers);
|
||||||
|
rt.trace(display, a2, b2, thickness, stayTime, viewers);
|
||||||
|
rt.trace(display, a3, b3, thickness, stayTime, viewers);
|
||||||
|
rt.trace(display, a4, b4, thickness, stayTime, viewers);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void outline(Material display, Location location, double thickness, long stayTime, List<Player> viewers) {
|
||||||
|
Location og = location.getBlock().getLocation();
|
||||||
|
|
||||||
|
Location a1 = og.clone().add(0, 0, 0);
|
||||||
|
Location a2 = og.clone().add(1, 0, 0);
|
||||||
|
Location a3 = og.clone().add(1, 0, 1);
|
||||||
|
Location a4 = og.clone().add(0, 0, 1);
|
||||||
|
|
||||||
|
Location b1 = og.clone().add(0, 1, 0);
|
||||||
|
Location b2 = og.clone().add(1, 1, 0);
|
||||||
|
Location b3 = og.clone().add(1, 1, 1);
|
||||||
|
Location b4 = og.clone().add(0, 1, 1);
|
||||||
|
|
||||||
|
rt.trace(display, a1, a2, thickness, stayTime, viewers);
|
||||||
|
rt.trace(display, a2, a3, thickness, stayTime, viewers);
|
||||||
|
rt.trace(display, a3, a4, thickness, stayTime, viewers);
|
||||||
|
rt.trace(display, a4, a1, thickness, stayTime, viewers);
|
||||||
|
|
||||||
|
rt.trace(display, b1, b2, thickness, stayTime, viewers);
|
||||||
|
rt.trace(display, b2, b3, thickness, stayTime, viewers);
|
||||||
|
rt.trace(display, b3, b4, thickness, stayTime, viewers);
|
||||||
|
rt.trace(display, b4, b1, thickness, stayTime, viewers);
|
||||||
|
|
||||||
|
rt.trace(display, a1, b1, thickness, stayTime, viewers);
|
||||||
|
rt.trace(display, a2, b2, thickness, stayTime, viewers);
|
||||||
|
rt.trace(display, a3, b3, thickness, stayTime, viewers);
|
||||||
|
rt.trace(display, a4, b4, thickness, stayTime, viewers);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package me.trouper.alias.server.systems.visual;
|
package me.trouper.alias.server.systems.display.visual;
|
||||||
|
|
||||||
import me.trouper.alias.server.Main;
|
import me.trouper.alias.AliasContext;
|
||||||
import me.trouper.alias.utils.misc.Randomizer;
|
import me.trouper.alias.utils.misc.Randomizer;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Color;
|
import org.bukkit.Color;
|
||||||
@@ -16,22 +16,28 @@ import java.util.function.BiFunction;
|
|||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
public class DisplayUtils implements Main {
|
public class Patterns {
|
||||||
|
|
||||||
// This will 100% get Javadoc in the future when I try to use it. Everything in here is so convoluted.
|
// This will 100% get Javadoc in the future when I try to use it. Everything in here is so convoluted.
|
||||||
|
|
||||||
public static final Function<Particle, Consumer<Location>> PARTICLE_FACTORY = particle -> l -> l.getWorld().spawnParticle(particle, l, 1, 0, 0, 0, 0);
|
private final AliasContext context;
|
||||||
|
|
||||||
public static final BiFunction<Color, Float, Consumer<Location>> DUST_PARTICLE_FACTORY = (color, thickness) -> {
|
public final Function<Particle, Consumer<Location>> PARTICLE_FACTORY = particle -> l -> l.getWorld().spawnParticle(particle, l, 1, 0, 0, 0, 0);
|
||||||
|
|
||||||
|
public final BiFunction<Color, Float, Consumer<Location>> DUST_PARTICLE_FACTORY = (color, thickness) -> {
|
||||||
Particle.DustOptions dust = new Particle.DustOptions(color, thickness);
|
Particle.DustOptions dust = new Particle.DustOptions(color, thickness);
|
||||||
return l -> l.getWorld().spawnParticle(Particle.DUST, l, 1, 0, 0, 0, 0, dust);
|
return l -> l.getWorld().spawnParticle(Particle.DUST, l, 1, 0, 0, 0, 0, dust);
|
||||||
};
|
};
|
||||||
|
|
||||||
public static void ring(Location loc, double radius, Color color, float thickness) {
|
public Patterns(AliasContext context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ring(Location loc, double radius, Color color, float thickness) {
|
||||||
ring(loc, radius, DUST_PARTICLE_FACTORY.apply(color, thickness));
|
ring(loc, radius, DUST_PARTICLE_FACTORY.apply(color, thickness));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void sphere(Location center, double radius, double pointDistance, Consumer<Location> action) {
|
public void sphere(Location center, double radius, double pointDistance, Consumer<Location> action) {
|
||||||
double dPhi = pointDistance / radius;
|
double dPhi = pointDistance / radius;
|
||||||
|
|
||||||
for (double phi = 0.0; phi <= Math.PI; phi += dPhi) {
|
for (double phi = 0.0; phi <= Math.PI; phi += dPhi) {
|
||||||
@@ -55,10 +61,10 @@ public class DisplayUtils implements Main {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void sphereWave(Location center, double maxRadius, double radialStep, double maxDistanceBetweenPoints, Consumer<Location> action) {
|
public void sphereWave(Location center, double maxRadius, double radialStep, double maxDistanceBetweenPoints, Consumer<Location> action) {
|
||||||
AtomicReference<Double> currentRadius = new AtomicReference<>(radialStep);
|
AtomicReference<Double> currentRadius = new AtomicReference<>(radialStep);
|
||||||
|
|
||||||
Bukkit.getScheduler().runTaskTimer(main.getPlugin(), (task) -> {
|
Bukkit.getScheduler().runTaskTimer(context.getPlugin(), (task) -> {
|
||||||
double r = currentRadius.get();
|
double r = currentRadius.get();
|
||||||
if (r > maxRadius) {
|
if (r > maxRadius) {
|
||||||
task.cancel();
|
task.cancel();
|
||||||
@@ -70,7 +76,7 @@ public class DisplayUtils implements Main {
|
|||||||
}, 0L, 1L);
|
}, 0L, 1L);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ring(Location loc, double radius, Consumer<Location> action) {
|
public void ring(Location loc, double radius, Consumer<Location> action) {
|
||||||
for (int theta = 0; theta < 360; theta += 10) {
|
for (int theta = 0; theta < 360; theta += 10) {
|
||||||
double x = Math.cos(Math.toRadians(theta)) * radius;
|
double x = Math.cos(Math.toRadians(theta)) * radius;
|
||||||
double z = Math.sin(Math.toRadians(theta)) * radius;
|
double z = Math.sin(Math.toRadians(theta)) * radius;
|
||||||
@@ -79,17 +85,17 @@ public class DisplayUtils implements Main {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ring(Location loc, double radius, double maxDistanceBetweenPoints, Consumer<Location> action) {
|
public void ring(Location loc, double radius, double maxDistanceBetweenPoints, Consumer<Location> action) {
|
||||||
arc(loc, radius, 0, 360, maxDistanceBetweenPoints, action);
|
arc(loc, radius, 0, 360, maxDistanceBetweenPoints, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void wave(Location loc, double radius, Color color, float thickness, double gap) {
|
public void wave(Location loc, double radius, Color color, float thickness, double gap) {
|
||||||
wave(loc, radius, DUST_PARTICLE_FACTORY.apply(color, thickness), gap);
|
wave(loc, radius, DUST_PARTICLE_FACTORY.apply(color, thickness), gap);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void wave(Location loc, double radius, Consumer<Location> action, double gap) {
|
public void wave(Location loc, double radius, Consumer<Location> action, double gap) {
|
||||||
AtomicReference<Double> i = new AtomicReference<>(gap);
|
AtomicReference<Double> i = new AtomicReference<>(gap);
|
||||||
Bukkit.getScheduler().runTaskTimer(main.getPlugin(), (task) -> {
|
Bukkit.getScheduler().runTaskTimer(context.getPlugin(), (task) -> {
|
||||||
if (i.get() >= radius) {
|
if (i.get() >= radius) {
|
||||||
task.cancel();
|
task.cancel();
|
||||||
return;
|
return;
|
||||||
@@ -99,9 +105,9 @@ public class DisplayUtils implements Main {
|
|||||||
}, 0, 1);
|
}, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void wave(Location loc, double radius, double radialGap, double maxDistanceBetweenPoints, Consumer<Location> action) {
|
public void wave(Location loc, double radius, double radialGap, double maxDistanceBetweenPoints, Consumer<Location> action) {
|
||||||
AtomicReference<Double> r = new AtomicReference<>(radialGap);
|
AtomicReference<Double> r = new AtomicReference<>(radialGap);
|
||||||
Bukkit.getScheduler().runTaskTimer(main.getPlugin(), (task) -> {
|
Bukkit.getScheduler().runTaskTimer(context.getPlugin(), (task) -> {
|
||||||
if (r.get() > radius) {
|
if (r.get() > radius) {
|
||||||
task.cancel();
|
task.cancel();
|
||||||
return;
|
return;
|
||||||
@@ -111,19 +117,19 @@ public class DisplayUtils implements Main {
|
|||||||
}, 0, 1);
|
}, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void disc(Location loc, double radius, Consumer<Location> action, double gap) {
|
public void disc(Location loc, double radius, Consumer<Location> action, double gap) {
|
||||||
for (double i = gap; i < radius; i += gap) {
|
for (double i = gap; i < radius; i += gap) {
|
||||||
ring(loc, i, action);
|
ring(loc, i, action);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void disc(Location loc, double radius, double radialGap, double maxDistanceBetweenPoints, Consumer<Location> action) {
|
public void disc(Location loc, double radius, double radialGap, double maxDistanceBetweenPoints, Consumer<Location> action) {
|
||||||
for (double r = radialGap; r <= radius; r += radialGap) {
|
for (double r = radialGap; r <= radius; r += radialGap) {
|
||||||
ring(loc, r, maxDistanceBetweenPoints, action);
|
ring(loc, r, maxDistanceBetweenPoints, action);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void helix(Location loc, double radius, Consumer<Location> action, double gap, int height) {
|
public void helix(Location loc, double radius, Consumer<Location> action, double gap, int height) {
|
||||||
int theta = 0;
|
int theta = 0;
|
||||||
for (double y = 0; y <= height; y += gap) {
|
for (double y = 0; y <= height; y += gap) {
|
||||||
double x = Math.cos(Math.toRadians(theta)) * radius;
|
double x = Math.cos(Math.toRadians(theta)) * radius;
|
||||||
@@ -135,7 +141,7 @@ public class DisplayUtils implements Main {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void vortex(Location loc, double radius, Consumer<Location> action, double gapH, double gapV, int height) {
|
public void vortex(Location loc, double radius, Consumer<Location> action, double gapH, double gapV, int height) {
|
||||||
double r = radius;
|
double r = radius;
|
||||||
int theta = 0;
|
int theta = 0;
|
||||||
for (double y = 0; y <= height; y += gapV) {
|
for (double y = 0; y <= height; y += gapV) {
|
||||||
@@ -149,14 +155,14 @@ public class DisplayUtils implements Main {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void beam(Location loc, Consumer<Location> action, double gap, int height) {
|
public void beam(Location loc, Consumer<Location> action, double gap, int height) {
|
||||||
for (double y = 0; y <= height; y += gap) {
|
for (double y = 0; y <= height; y += gap) {
|
||||||
Location newLoc = loc.clone().add(0, y, 0);
|
Location newLoc = loc.clone().add(0, y, 0);
|
||||||
action.accept(newLoc);
|
action.accept(newLoc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void arc(Location loc, double radius, int angleFrom, int angleTo, Consumer<Location> action) {
|
public void arc(Location loc, double radius, int angleFrom, int angleTo, Consumer<Location> action) {
|
||||||
for (int theta = angleFrom; theta < angleTo; theta += 10) {
|
for (int theta = angleFrom; theta < angleTo; theta += 10) {
|
||||||
double x = Math.cos(Math.toRadians(theta)) * radius;
|
double x = Math.cos(Math.toRadians(theta)) * radius;
|
||||||
double z = Math.sin(Math.toRadians(theta)) * radius;
|
double z = Math.sin(Math.toRadians(theta)) * radius;
|
||||||
@@ -165,7 +171,7 @@ public class DisplayUtils implements Main {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void arc(Location loc, double radius, int angleFrom, int angleTo, double maxDistanceBetweenPoints, Consumer<Location> action) {
|
public void arc(Location loc, double radius, int angleFrom, int angleTo, double maxDistanceBetweenPoints, Consumer<Location> action) {
|
||||||
int angleSpan = angleTo - angleFrom;
|
int angleSpan = angleTo - angleFrom;
|
||||||
if (angleSpan <= 0) return;
|
if (angleSpan <= 0) return;
|
||||||
|
|
||||||
@@ -182,23 +188,23 @@ public class DisplayUtils implements Main {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void fan(Location loc, double radius, int angleFrom, int angleTo, Consumer<Location> action, double gap) {
|
public void fan(Location loc, double radius, int angleFrom, int angleTo, Consumer<Location> action, double gap) {
|
||||||
for (double i = gap; i < radius; i += gap) {
|
for (double i = gap; i < radius; i += gap) {
|
||||||
arc(loc, i, angleFrom, angleTo, action);
|
arc(loc, i, angleFrom, angleTo, action);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void fan(Location loc, double radius, int angleFrom, int angleTo, double maxDistanceBetweenPoints, Consumer<Location> action, double radialGap) {
|
public void fan(Location loc, double radius, int angleFrom, int angleTo, double maxDistanceBetweenPoints, Consumer<Location> action, double radialGap) {
|
||||||
for (double r = radialGap; r < radius; r += radialGap) {
|
for (double r = radialGap; r < radius; r += radialGap) {
|
||||||
arc(loc, r, angleFrom, angleTo, maxDistanceBetweenPoints, action);
|
arc(loc, r, angleFrom, angleTo, maxDistanceBetweenPoints, action);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void fanWave(Location loc, double radius, int sections, Consumer<Location> action, double gap) {
|
public void fanWave(Location loc, double radius, int sections, Consumer<Location> action, double gap) {
|
||||||
double arcLength = 360.0 / sections;
|
double arcLength = 360.0 / sections;
|
||||||
AtomicReference<Double> i = new AtomicReference<>(0.0);
|
AtomicReference<Double> i = new AtomicReference<>(0.0);
|
||||||
Bukkit.getScheduler().runTaskTimer(main.getPlugin(), (task) -> {
|
Bukkit.getScheduler().runTaskTimer(context.getPlugin(), (task) -> {
|
||||||
if (i.get() >= 360) {
|
if (i.get() >= 360) {
|
||||||
task.cancel();
|
task.cancel();
|
||||||
return;
|
return;
|
||||||
@@ -209,7 +215,7 @@ public class DisplayUtils implements Main {
|
|||||||
}, 0, 5);
|
}, 0, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void fanWaveRandom(Location loc, double radius, int sections, Consumer<Location> action, double gap) {
|
public void fanWaveRandom(Location loc, double radius, int sections, Consumer<Location> action, double gap) {
|
||||||
double arcLength = 360.0 / sections;
|
double arcLength = 360.0 / sections;
|
||||||
List<Double> ints = new ArrayList<>();
|
List<Double> ints = new ArrayList<>();
|
||||||
for (double start = 0; start < 360; start += arcLength) {
|
for (double start = 0; start < 360; start += arcLength) {
|
||||||
@@ -218,7 +224,7 @@ public class DisplayUtils implements Main {
|
|||||||
|
|
||||||
AtomicInteger i = new AtomicInteger(0);
|
AtomicInteger i = new AtomicInteger(0);
|
||||||
Randomizer random = new Randomizer();
|
Randomizer random = new Randomizer();
|
||||||
Bukkit.getScheduler().runTaskTimer(main.getPlugin(), (task) -> {
|
Bukkit.getScheduler().runTaskTimer(context.getPlugin(), (task) -> {
|
||||||
if (i.get() >= sections) {
|
if (i.get() >= sections) {
|
||||||
task.cancel();
|
task.cancel();
|
||||||
return;
|
return;
|
||||||
@@ -230,9 +236,9 @@ public class DisplayUtils implements Main {
|
|||||||
}, 0, 5);
|
}, 0, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void waveFan(Location loc, double radius, int angleFrom, int angleTo, double maxDistanceBetweenPoints, Consumer<Location> action, double radialGap) {
|
public void waveFan(Location loc, double radius, int angleFrom, int angleTo, double maxDistanceBetweenPoints, Consumer<Location> action, double radialGap) {
|
||||||
AtomicReference<Double> r = new AtomicReference<>(radialGap);
|
AtomicReference<Double> r = new AtomicReference<>(radialGap);
|
||||||
Bukkit.getScheduler().runTaskTimer(main.getPlugin(), (task) -> {
|
Bukkit.getScheduler().runTaskTimer(context.getPlugin(), (task) -> {
|
||||||
if (r.get() >= radius) {
|
if (r.get() >= radius) {
|
||||||
task.cancel();
|
task.cancel();
|
||||||
return;
|
return;
|
||||||
@@ -242,7 +248,7 @@ public class DisplayUtils implements Main {
|
|||||||
}, 0, 1);
|
}, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void waveFan(Location loc, double radius, Vector direction, int angle, double maxDistanceBetweenPoints, Consumer<Location> action, double radialGap) {
|
public void waveFan(Location loc, double radius, Vector direction, int angle, double maxDistanceBetweenPoints, Consumer<Location> action, double radialGap) {
|
||||||
double baseAngle = Math.toDegrees(Math.atan2(direction.getZ(), direction.getX()));
|
double baseAngle = Math.toDegrees(Math.atan2(direction.getZ(), direction.getX()));
|
||||||
int angleFrom = (int) (baseAngle - angle / 2.0);
|
int angleFrom = (int) (baseAngle - angle / 2.0);
|
||||||
int angleTo = (int) (baseAngle + angle / 2.0);
|
int angleTo = (int) (baseAngle + angle / 2.0);
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
package me.trouper.alias.server.systems.gui;
|
package me.trouper.alias.server.systems.gui;
|
||||||
|
|
||||||
import me.trouper.alias.server.Main;
|
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.format.NamedTextColor;
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
import net.kyori.adventure.text.format.TextDecoration;
|
import net.kyori.adventure.text.format.TextDecoration;
|
||||||
@@ -17,21 +16,18 @@ import org.bukkit.inventory.Inventory;
|
|||||||
import org.bukkit.inventory.InventoryHolder;
|
import org.bukkit.inventory.InventoryHolder;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.inventory.meta.ItemMeta;
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
import org.bukkit.scheduler.BukkitRunnable;
|
|
||||||
import org.bukkit.scheduler.BukkitTask;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
public class QuickGui implements InventoryHolder, Main {
|
public class QuickGui implements InventoryHolder {
|
||||||
|
|
||||||
private static final Map<String, QuickGui> registry = new ConcurrentHashMap<>();
|
private static final Map<String, QuickGui> registry = new ConcurrentHashMap<>();
|
||||||
private static final MiniMessage miniMessage = MiniMessage.miniMessage();
|
private static final MiniMessage miniMessage = MiniMessage.miniMessage();
|
||||||
|
|
||||||
private final Map<Integer, GuiAction> slotActions;
|
private final Map<Integer, GuiAction> slotActions;
|
||||||
private final Map<Integer, ItemStack> slotItems;
|
private final Map<Integer, ItemStack> slotItems;
|
||||||
private final Map<Integer, BukkitTask> animations;
|
|
||||||
private final GuiAction globalAction;
|
private final GuiAction globalAction;
|
||||||
private final GuiCreateAction createAction;
|
private final GuiCreateAction createAction;
|
||||||
private final GuiCloseAction closeAction;
|
private final GuiCloseAction closeAction;
|
||||||
@@ -62,7 +58,6 @@ public class QuickGui implements InventoryHolder, Main {
|
|||||||
this.clickSound = clickSound;
|
this.clickSound = clickSound;
|
||||||
this.soundVolume = soundVolume;
|
this.soundVolume = soundVolume;
|
||||||
this.soundPitch = soundPitch;
|
this.soundPitch = soundPitch;
|
||||||
this.animations = new HashMap<>();
|
|
||||||
this.viewers = ConcurrentHashMap.newKeySet();
|
this.viewers = ConcurrentHashMap.newKeySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,46 +136,6 @@ public class QuickGui implements InventoryHolder, Main {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startAnimation(int slot, List<ItemStack> frames, long interval) {
|
|
||||||
stopAnimation(slot);
|
|
||||||
|
|
||||||
if (frames.isEmpty()) return;
|
|
||||||
|
|
||||||
BukkitTask task = new BukkitRunnable() {
|
|
||||||
private int frameIndex = 0;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (getInventory().getViewers().isEmpty()) {
|
|
||||||
cancel();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ItemStack frame = frames.get(frameIndex);
|
|
||||||
getInventory().setItem(slot, frame);
|
|
||||||
frameIndex = (frameIndex + 1) % frames.size();
|
|
||||||
}
|
|
||||||
}.runTaskTimer(main.getPlugin(), 0L, interval);
|
|
||||||
|
|
||||||
animations.put(slot, task);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stopAnimation(int slot) {
|
|
||||||
BukkitTask task = animations.remove(slot);
|
|
||||||
if (task != null && !task.isCancelled()) {
|
|
||||||
task.cancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stopAllAnimations() {
|
|
||||||
animations.values().forEach(task -> {
|
|
||||||
if (!task.isCancelled()) {
|
|
||||||
task.cancel();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
animations.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
private int calculateSize() {
|
private int calculateSize() {
|
||||||
if (size > 0 && size % 9 == 0) {
|
if (size > 0 && size % 9 == 0) {
|
||||||
return Math.min(size, 54);
|
return Math.min(size, 54);
|
||||||
@@ -233,10 +188,6 @@ public class QuickGui implements InventoryHolder, Main {
|
|||||||
viewers.remove(player);
|
viewers.remove(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (viewers.isEmpty()) {
|
|
||||||
stopAllAnimations();
|
|
||||||
}
|
|
||||||
|
|
||||||
closeAction.onClose(this, event);
|
closeAction.onClose(this, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,351 +0,0 @@
|
|||||||
package me.trouper.alias.server.systems.tracing;
|
|
||||||
|
|
||||||
import me.trouper.alias.server.Main;
|
|
||||||
import org.bukkit.*;
|
|
||||||
import org.bukkit.block.Block;
|
|
||||||
import org.bukkit.entity.BlockDisplay;
|
|
||||||
import org.bukkit.entity.Display;
|
|
||||||
import org.bukkit.entity.Entity;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
|
||||||
import org.bukkit.util.BoundingBox;
|
|
||||||
import org.bukkit.util.Transformation;
|
|
||||||
import org.bukkit.util.Vector;
|
|
||||||
import org.bukkit.util.VoxelShape;
|
|
||||||
import org.joml.AxisAngle4f;
|
|
||||||
import org.joml.Vector3f;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
public class BlockDisplayRaytracer implements Main {
|
|
||||||
|
|
||||||
public static void cleanup() {
|
|
||||||
JavaPlugin plugin = main.getPlugin();
|
|
||||||
List<World> worlds = plugin.getServer().getWorlds();
|
|
||||||
List<Entity> entities = new ArrayList<>();
|
|
||||||
for (World world : worlds) {
|
|
||||||
entities.addAll(world.getEntities().stream().filter(entity -> entity.getScoreboardTags().contains(main.getCommon().getTempTag())).toList());
|
|
||||||
entities.forEach(entity -> {
|
|
||||||
if (entity != null) entity.remove();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void outline(Material display, Location location, long stayTime, List<Player> viewers) {
|
|
||||||
outline(display, location, 0.05, stayTime, viewers);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void outline(Material display, Location corner1, Location corner2, double thickness, long stayTime, List<Player> viewers) {
|
|
||||||
World world = corner1.getWorld();
|
|
||||||
|
|
||||||
int minX = Math.min(corner1.getBlockX(), corner2.getBlockX());
|
|
||||||
int minY = Math.min(corner1.getBlockY(), corner2.getBlockY());
|
|
||||||
int minZ = Math.min(corner1.getBlockZ(), corner2.getBlockZ());
|
|
||||||
int maxX = Math.max(corner1.getBlockX(), corner2.getBlockX());
|
|
||||||
int maxY = Math.max(corner1.getBlockY(), corner2.getBlockY());
|
|
||||||
int maxZ = Math.max(corner1.getBlockZ(), corner2.getBlockZ());
|
|
||||||
|
|
||||||
Location a1 = new Location(world, minX, minY, minZ);
|
|
||||||
Location a2 = new Location(world, maxX + 1, minY, minZ);
|
|
||||||
Location a3 = new Location(world, maxX + 1, minY, maxZ + 1);
|
|
||||||
Location a4 = new Location(world, minX, minY, maxZ + 1);
|
|
||||||
|
|
||||||
Location b1 = new Location(world, minX, maxY + 1, minZ);
|
|
||||||
Location b2 = new Location(world, maxX + 1, maxY + 1, minZ);
|
|
||||||
Location b3 = new Location(world, maxX + 1, maxY + 1, maxZ + 1);
|
|
||||||
Location b4 = new Location(world, minX, maxY + 1, maxZ + 1);
|
|
||||||
|
|
||||||
trace(display, a1, a2, thickness, stayTime, viewers);
|
|
||||||
trace(display, a2, a3, thickness, stayTime, viewers);
|
|
||||||
trace(display, a3, a4, thickness, stayTime, viewers);
|
|
||||||
trace(display, a4, a1, thickness, stayTime, viewers);
|
|
||||||
|
|
||||||
trace(display, b1, b2, thickness, stayTime, viewers);
|
|
||||||
trace(display, b2, b3, thickness, stayTime, viewers);
|
|
||||||
trace(display, b3, b4, thickness, stayTime, viewers);
|
|
||||||
trace(display, b4, b1, thickness, stayTime, viewers);
|
|
||||||
|
|
||||||
trace(display, a1, b1, thickness, stayTime, viewers);
|
|
||||||
trace(display, a2, b2, thickness, stayTime, viewers);
|
|
||||||
trace(display, a3, b3, thickness, stayTime, viewers);
|
|
||||||
trace(display, a4, b4, thickness, stayTime, viewers);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static void outline(Material display, Location location, double thickness, long stayTime, List<Player> viewers) {
|
|
||||||
Location og = location.getBlock().getLocation();
|
|
||||||
|
|
||||||
Location a1 = og.clone().add(0, 0, 0);
|
|
||||||
Location a2 = og.clone().add(1, 0, 0);
|
|
||||||
Location a3 = og.clone().add(1, 0, 1);
|
|
||||||
Location a4 = og.clone().add(0, 0, 1);
|
|
||||||
|
|
||||||
Location b1 = og.clone().add(0, 1, 0);
|
|
||||||
Location b2 = og.clone().add(1, 1, 0);
|
|
||||||
Location b3 = og.clone().add(1, 1, 1);
|
|
||||||
Location b4 = og.clone().add(0, 1, 1);
|
|
||||||
|
|
||||||
trace(display, a1, a2, thickness, stayTime, viewers);
|
|
||||||
trace(display, a2, a3, thickness, stayTime, viewers);
|
|
||||||
trace(display, a3, a4, thickness, stayTime, viewers);
|
|
||||||
trace(display, a4, a1, thickness, stayTime, viewers);
|
|
||||||
|
|
||||||
trace(display, b1, b2, thickness, stayTime, viewers);
|
|
||||||
trace(display, b2, b3, thickness, stayTime, viewers);
|
|
||||||
trace(display, b3, b4, thickness, stayTime, viewers);
|
|
||||||
trace(display, b4, b1, thickness, stayTime, viewers);
|
|
||||||
|
|
||||||
trace(display, a1, b1, thickness, stayTime, viewers);
|
|
||||||
trace(display, a2, b2, thickness, stayTime, viewers);
|
|
||||||
trace(display, a3, b3, thickness, stayTime, viewers);
|
|
||||||
trace(display, a4, b4, thickness, stayTime, viewers);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void trace(Material display, Location start, Location end, long stayTime, List<Player> viewers) {
|
|
||||||
trace(display, start, end.toVector().subtract(start.toVector()), 0.05, end.distance(start), stayTime, viewers);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void trace(Material display, Location start, Location end, double thickness, long stayTime, List<Player> viewers) {
|
|
||||||
trace(display, start, end.toVector().subtract(start.toVector()), thickness, end.distance(start), stayTime, viewers);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void trace(Material display, Location start, Vector direction, double thickness, double distance, long stayTime, List<Player> viewers) {
|
|
||||||
World world = start.getWorld();
|
|
||||||
|
|
||||||
BlockDisplay beam = world.spawn(start, BlockDisplay.class, entity -> {
|
|
||||||
AxisAngle4f angle = new AxisAngle4f(0, 0, 0, 1);
|
|
||||||
Vector3f transition = new Vector3f(-(float)(thickness / 2F));
|
|
||||||
Vector3f scale = new Vector3f((float)thickness, (float)thickness, (float)distance);
|
|
||||||
Transformation trans = new Transformation(transition, angle, scale, angle);
|
|
||||||
Location vector = entity.getLocation();
|
|
||||||
|
|
||||||
vector.setDirection(direction);
|
|
||||||
entity.teleport(vector);
|
|
||||||
entity.setBlock(display.createBlockData());
|
|
||||||
entity.setBrightness(new Display.Brightness(15, 15));
|
|
||||||
entity.setInterpolationDelay(0);
|
|
||||||
entity.setTransformation(trans);
|
|
||||||
entity.addScoreboardTag(main.getCommon().getTempTag());
|
|
||||||
|
|
||||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
|
||||||
if (!viewers.contains(player)) {
|
|
||||||
player.hideEntity(main.getPlugin(), entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Bukkit.getScheduler().runTaskLater(main.getPlugin(), entity::remove, stayTime);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void trace(Material display, Location start, Vector direction, double thickness, double distance, long stayTime, Consumer<BlockDisplay> onEntitySpawn, List<Player> viewers) {
|
|
||||||
World world = start.getWorld();
|
|
||||||
|
|
||||||
BlockDisplay beam = world.spawn(start, BlockDisplay.class, entity -> {
|
|
||||||
AxisAngle4f angle = new AxisAngle4f(0, 0, 0, 1);
|
|
||||||
Vector3f transition = new Vector3f(-(float)(thickness / 2F));
|
|
||||||
Vector3f scale = new Vector3f((float)thickness, (float)thickness, (float)distance);
|
|
||||||
Transformation trans = new Transformation(transition, angle, scale, angle);
|
|
||||||
Location vector = entity.getLocation();
|
|
||||||
|
|
||||||
vector.setDirection(direction);
|
|
||||||
entity.teleport(vector);
|
|
||||||
entity.setBlock(display.createBlockData());
|
|
||||||
entity.setBrightness(new Display.Brightness(15, 15));
|
|
||||||
entity.setInterpolationDelay(0);
|
|
||||||
entity.setTransformation(trans);
|
|
||||||
entity.addScoreboardTag(main.getCommon().getTempTag());
|
|
||||||
|
|
||||||
|
|
||||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
|
||||||
if (!viewers.contains(player)) {
|
|
||||||
player.hideEntity(main.getPlugin(), entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Bukkit.getScheduler().runTaskLater(main.getPlugin(), entity::remove, stayTime);
|
|
||||||
Bukkit.getScheduler().runTaskLater(main.getPlugin(), () -> onEntitySpawn.accept(entity), 5);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<BlockDisplay> outline(Material display, Location location, long stayTime) {
|
|
||||||
return outline(display, location, 0.05, stayTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<BlockDisplay> outline(Material display, Location location, double thickness, long stayTime) {
|
|
||||||
Location og = location.getBlock().getLocation();
|
|
||||||
|
|
||||||
Location a1 = og.clone().add(0, 0, 0);
|
|
||||||
Location a2 = og.clone().add(1, 0, 0);
|
|
||||||
Location a3 = og.clone().add(1, 0, 1);
|
|
||||||
Location a4 = og.clone().add(0, 0, 1);
|
|
||||||
|
|
||||||
Location b1 = og.clone().add(0, 1, 0);
|
|
||||||
Location b2 = og.clone().add(1, 1, 0);
|
|
||||||
Location b3 = og.clone().add(1, 1, 1);
|
|
||||||
Location b4 = og.clone().add(0, 1, 1);
|
|
||||||
|
|
||||||
List<BlockDisplay> a = new ArrayList<>();
|
|
||||||
|
|
||||||
a.add(trace(display, a1, a2, thickness, stayTime));
|
|
||||||
a.add(trace(display, a2, a3, thickness, stayTime));
|
|
||||||
a.add(trace(display, a3, a4, thickness, stayTime));
|
|
||||||
a.add(trace(display, a4, a1, thickness, stayTime));
|
|
||||||
|
|
||||||
a.add(trace(display, b1, b2, thickness, stayTime));
|
|
||||||
a.add(trace(display, b2, b3, thickness, stayTime));
|
|
||||||
a.add(trace(display, b3, b4, thickness, stayTime));
|
|
||||||
a.add(trace(display, b4, b1, thickness, stayTime));
|
|
||||||
|
|
||||||
a.add(trace(display, a1, b1, thickness, stayTime));
|
|
||||||
a.add(trace(display, a2, b2, thickness, stayTime));
|
|
||||||
a.add(trace(display, a3, b3, thickness, stayTime));
|
|
||||||
a.add(trace(display, a4, b4, thickness, stayTime));
|
|
||||||
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void highlightCollisions(Block block, Color color, long stayTime) {
|
|
||||||
if (block == null || block.isEmpty() || !block.isCollidable())
|
|
||||||
return;
|
|
||||||
|
|
||||||
VoxelShape shape = block.getCollisionShape();
|
|
||||||
World world = block.getWorld();
|
|
||||||
Vector offset = block.getLocation().toVector();
|
|
||||||
|
|
||||||
for (BoundingBox box : shape.getBoundingBoxes()) {
|
|
||||||
highlight(box, offset, world, color, stayTime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void highlight(BoundingBox box, Vector offset, World world, Color color, long stayTime) {
|
|
||||||
double x1 = box.getMinX() + offset.getX();
|
|
||||||
double y1 = box.getMinY() + offset.getY();
|
|
||||||
double z1 = box.getMinZ() + offset.getZ();
|
|
||||||
double x2 = box.getMaxX() + offset.getX();
|
|
||||||
double y2 = box.getMaxY() + offset.getY();
|
|
||||||
double z2 = box.getMaxZ() + offset.getZ();
|
|
||||||
|
|
||||||
traceGlowing(world, x1, y1, z1, x2, y1, z1, color, stayTime);
|
|
||||||
traceGlowing(world, x2, y1, z1, x2, y1, z2, color, stayTime);
|
|
||||||
traceGlowing(world, x2, y1, z2, x1, y1, z2, color, stayTime);
|
|
||||||
traceGlowing(world, x1, y1, z2, x1, y1, z1, color, stayTime);
|
|
||||||
|
|
||||||
traceGlowing(world, x1, y2, z1, x2, y2, z1, color, stayTime);
|
|
||||||
traceGlowing(world, x2, y2, z1, x2, y2, z2, color, stayTime);
|
|
||||||
traceGlowing(world, x2, y2, z2, x1, y2, z2, color, stayTime);
|
|
||||||
traceGlowing(world, x1, y2, z2, x1, y2, z1, color, stayTime);
|
|
||||||
|
|
||||||
traceGlowing(world, x1, y1, z1, x1, y2, z1, color, stayTime);
|
|
||||||
traceGlowing(world, x2, y1, z1, x2, y2, z1, color, stayTime);
|
|
||||||
traceGlowing(world, x2, y1, z2, x2, y2, z2, color, stayTime);
|
|
||||||
traceGlowing(world, x1, y1, z2, x1, y2, z2, color, stayTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void traceGlowing(World world, double x1, double y1, double z1, double x2, double y2, double z2, Color color, long stayTime) {
|
|
||||||
Location loc1 = new Location(world, x1, y1, z1);
|
|
||||||
Location loc2 = new Location(world, x2, y2, z2);
|
|
||||||
BlockDisplay ent = trace(Material.WHITE_CONCRETE, loc1, loc2, 0.01, stayTime);
|
|
||||||
ent.setGlowColorOverride(color);
|
|
||||||
ent.setGlowing(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static BlockDisplay trace(Material display, Location start, Location end, long stayTime) {
|
|
||||||
return trace(display, start, end.toVector().subtract(start.toVector()), 0.05, end.distance(start), stayTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static BlockDisplay trace(Material display, Location start, Location end, double thickness, long stayTime) {
|
|
||||||
return trace(display, start, end.toVector().subtract(start.toVector()), thickness, end.distance(start), stayTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static BlockDisplay trace(Material display, Location start, Vector direction, double thickness, double distance, long stayTime) {
|
|
||||||
World world = start.getWorld();
|
|
||||||
|
|
||||||
BlockDisplay entity = world.spawn(start, BlockDisplay.class);
|
|
||||||
AxisAngle4f angle = new AxisAngle4f(0, 0, 0, 1);
|
|
||||||
Vector3f transition = new Vector3f(-(float)(thickness / 2F));
|
|
||||||
Vector3f scale = new Vector3f((float)thickness, (float)thickness, (float)distance);
|
|
||||||
Transformation trans = new Transformation(transition, angle, scale, angle);
|
|
||||||
Location vector = entity.getLocation();
|
|
||||||
|
|
||||||
vector.setDirection(direction);
|
|
||||||
entity.teleport(vector);
|
|
||||||
entity.setBlock(display.createBlockData());
|
|
||||||
entity.setBrightness(new Display.Brightness(15, 15));
|
|
||||||
entity.setInterpolationDelay(0);
|
|
||||||
entity.setTransformation(trans);
|
|
||||||
entity.addScoreboardTag(main.getCommon().getTempTag());
|
|
||||||
|
|
||||||
Bukkit.getScheduler().runTaskLater(main.getPlugin(), entity::remove, stayTime);
|
|
||||||
return entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void transform(BlockDisplay display, Location start, Location end, double thickness) {
|
|
||||||
Vector direction = end.toVector().subtract(start.toVector());
|
|
||||||
double distance = direction.length();
|
|
||||||
|
|
||||||
Location loc = start.clone();
|
|
||||||
loc.setDirection(direction);
|
|
||||||
display.teleport(loc);
|
|
||||||
|
|
||||||
Vector3f translation = new Vector3f(-(float)(thickness / 2F), 0, 0); // Centered
|
|
||||||
Vector3f scale = new Vector3f((float)thickness, (float)thickness, (float)distance);
|
|
||||||
AxisAngle4f rotation = new AxisAngle4f(0, 0, 0, 1);
|
|
||||||
Transformation transformation = new Transformation(translation, rotation, scale, rotation);
|
|
||||||
|
|
||||||
display.setTransformation(transformation);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void transform(BlockDisplay display, Location start, Vector direction, double distance, double thickness) {
|
|
||||||
Location loc = start.clone();
|
|
||||||
loc.setDirection(direction);
|
|
||||||
display.teleport(loc);
|
|
||||||
|
|
||||||
Vector3f translation = new Vector3f(-(float)(thickness / 2F), 0, 0);
|
|
||||||
Vector3f scale = new Vector3f((float)thickness, (float)thickness, (float)distance);
|
|
||||||
AxisAngle4f rotation = new AxisAngle4f(0, 0, 0, 1);
|
|
||||||
Transformation transformation = new Transformation(translation, rotation, scale, rotation);
|
|
||||||
|
|
||||||
display.setTransformation(transformation);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static void translate(BlockDisplay display, Vector3f offset) {
|
|
||||||
Transformation current = display.getTransformation();
|
|
||||||
Vector3f translation = new Vector3f(current.getTranslation()).add(offset);
|
|
||||||
display.setTransformation(new Transformation(
|
|
||||||
translation,
|
|
||||||
current.getLeftRotation(),
|
|
||||||
current.getScale(),
|
|
||||||
current.getRightRotation()
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void scale(BlockDisplay display, Vector3f scale) {
|
|
||||||
Transformation current = display.getTransformation();
|
|
||||||
display.setTransformation(new Transformation(
|
|
||||||
current.getTranslation(),
|
|
||||||
current.getLeftRotation(),
|
|
||||||
scale,
|
|
||||||
current.getRightRotation()
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void rotate(BlockDisplay display, AxisAngle4f rotation) {
|
|
||||||
Transformation current = display.getTransformation();
|
|
||||||
display.setTransformation(new Transformation(
|
|
||||||
current.getTranslation(),
|
|
||||||
rotation,
|
|
||||||
current.getScale(),
|
|
||||||
rotation
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void alignToDirection(BlockDisplay display, Vector direction) {
|
|
||||||
Location loc = display.getLocation().clone();
|
|
||||||
loc.setDirection(direction);
|
|
||||||
display.teleport(loc);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
package me.trouper.alias.server.systems.tracing;
|
|
||||||
|
|
||||||
import org.bukkit.util.Vector;
|
|
||||||
|
|
||||||
public class ReflectionResult {
|
|
||||||
private final Point hitPoint;
|
|
||||||
private final boolean shouldReflect;
|
|
||||||
private final Vector reflectedDirection;
|
|
||||||
|
|
||||||
public ReflectionResult(Point hitPoint, boolean shouldReflect, Vector reflectedDirection) {
|
|
||||||
this.hitPoint = hitPoint;
|
|
||||||
this.shouldReflect = shouldReflect;
|
|
||||||
this.reflectedDirection = reflectedDirection;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Point getHitPoint() {
|
|
||||||
return hitPoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean shouldReflect() {
|
|
||||||
return shouldReflect;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vector getReflectedDirection() {
|
|
||||||
return reflectedDirection;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,20 +1,26 @@
|
|||||||
package me.trouper.alias.server.systems.world;
|
package me.trouper.alias.server.systems.world;
|
||||||
|
|
||||||
import me.trouper.alias.server.Main;
|
import me.trouper.alias.AliasContext;
|
||||||
import me.trouper.alias.server.systems.TaskManager;
|
import me.trouper.alias.server.systems.TaskManager;
|
||||||
import me.trouper.alias.server.systems.burning.BlockBurner;
|
import me.trouper.alias.server.systems.world.burning.BlockBurner;
|
||||||
|
import me.trouper.alias.utils.ParticleUtils;
|
||||||
import me.trouper.alias.utils.SoundPlayer;
|
import me.trouper.alias.utils.SoundPlayer;
|
||||||
import org.bukkit.*;
|
import org.bukkit.*;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.entity.LivingEntity;
|
import org.bukkit.entity.LivingEntity;
|
||||||
import org.bukkit.util.Vector;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ThreadLocalRandom;
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
public class ExplosionUtils implements Main {
|
public class Explosion {
|
||||||
|
|
||||||
public static ExplosionResult createExplosion(Location center, ExplosionOptions options) {
|
private final AliasContext context;
|
||||||
|
|
||||||
|
public Explosion(AliasContext context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExplosionResult createExplosion(Location center, ExplosionOptions options) {
|
||||||
World world = center.getWorld();
|
World world = center.getWorld();
|
||||||
if (world == null) throw new IllegalArgumentException("Center location must have a valid world");
|
if (world == null) throw new IllegalArgumentException("Center location must have a valid world");
|
||||||
|
|
||||||
@@ -24,8 +30,8 @@ public class ExplosionUtils implements Main {
|
|||||||
Map<Block, Double> affectedBlocks = getBlocksInRadius(center, maxBurnRadius);
|
Map<Block, Double> affectedBlocks = getBlocksInRadius(center, maxBurnRadius);
|
||||||
Map<UUID, Double> affectedEntities = getEntitiesInRadius(center, maxBurnRadius);
|
Map<UUID, Double> affectedEntities = getEntitiesInRadius(center, maxBurnRadius);
|
||||||
|
|
||||||
BlockBurner burner = new BlockBurner(options.getBurnOptions());
|
TaskManager sharedTaskManager = context.createTaskManager();
|
||||||
TaskManager sharedTaskManager = burner.getTaskManager();
|
BlockBurner burner = new BlockBurner(sharedTaskManager,options.getBurnOptions());
|
||||||
ExplosionResult result = new ExplosionResult(affectedBlocks.keySet(), sharedTaskManager);
|
ExplosionResult result = new ExplosionResult(affectedBlocks.keySet(), sharedTaskManager);
|
||||||
|
|
||||||
List<Block> blocksToDestroy = new ArrayList<>();
|
List<Block> blocksToDestroy = new ArrayList<>();
|
||||||
@@ -39,7 +45,7 @@ public class ExplosionUtils implements Main {
|
|||||||
scheduleDamage(affectedEntities, options, sharedTaskManager);
|
scheduleDamage(affectedEntities, options, sharedTaskManager);
|
||||||
|
|
||||||
if (options.isCreateParticles() || options.isPlaySound()) {
|
if (options.isCreateParticles() || options.isPlaySound()) {
|
||||||
createExplosionEffects(center, options);
|
createExplosionEffects(center, options, sharedTaskManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -50,7 +56,7 @@ public class ExplosionUtils implements Main {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Map<Block, Double> getBlocksInRadius(Location center, double radius) {
|
private Map<Block, Double> getBlocksInRadius(Location center, double radius) {
|
||||||
World world = center.getWorld();
|
World world = center.getWorld();
|
||||||
if (world == null) return Collections.emptyMap();
|
if (world == null) return Collections.emptyMap();
|
||||||
|
|
||||||
@@ -82,7 +88,7 @@ public class ExplosionUtils implements Main {
|
|||||||
return blocks;
|
return blocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Map<UUID, Double> getEntitiesInRadius(Location center, double radius) {
|
private Map<UUID, Double> getEntitiesInRadius(Location center, double radius) {
|
||||||
List<LivingEntity> rawList = center.getNearbyEntities(radius, radius, radius).stream()
|
List<LivingEntity> rawList = center.getNearbyEntities(radius, radius, radius).stream()
|
||||||
.filter(entity -> entity instanceof LivingEntity)
|
.filter(entity -> entity instanceof LivingEntity)
|
||||||
.map(entity -> (LivingEntity) entity)
|
.map(entity -> (LivingEntity) entity)
|
||||||
@@ -101,7 +107,7 @@ public class ExplosionUtils implements Main {
|
|||||||
return entities;
|
return entities;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void categorizeBlocks(Map<Block, Double> affectedBlocks, ExplosionOptions options,
|
private void categorizeBlocks(Map<Block, Double> affectedBlocks, ExplosionOptions options,
|
||||||
List<Block> blocksToDestroy, List<Block> blocksToBurn,
|
List<Block> blocksToDestroy, List<Block> blocksToBurn,
|
||||||
Map<Block, Float> blocksHeatMap) {
|
Map<Block, Float> blocksHeatMap) {
|
||||||
ThreadLocalRandom random = ThreadLocalRandom.current();
|
ThreadLocalRandom random = ThreadLocalRandom.current();
|
||||||
@@ -154,14 +160,14 @@ public class ExplosionUtils implements Main {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static float calculateHeat(double distance, ExplosionOptions options) {
|
private float calculateHeat(double distance, ExplosionOptions options) {
|
||||||
double normalizedDistance = distance / options.getMaxBurnRadius();
|
double normalizedDistance = distance / options.getMaxBurnRadius();
|
||||||
double heatRange = options.getMaxHeat() - options.getMinHeat();
|
double heatRange = options.getMaxHeat() - options.getMinHeat();
|
||||||
double heatFactor = Math.pow(1.0 - normalizedDistance, 2.0);
|
double heatFactor = Math.pow(1.0 - normalizedDistance, 2.0);
|
||||||
return (float) (options.getMinHeat() + heatRange * heatFactor);
|
return (float) (options.getMinHeat() + heatRange * heatFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void scheduleDestruction(List<Block> blocksToDestroy, ExplosionOptions options, TaskManager taskManager) {
|
private void scheduleDestruction(List<Block> blocksToDestroy, ExplosionOptions options, TaskManager taskManager) {
|
||||||
if (blocksToDestroy.isEmpty()) return;
|
if (blocksToDestroy.isEmpty()) return;
|
||||||
|
|
||||||
long destructionDelayTicks = (long) (options.getDestructionDelay() * 20);
|
long destructionDelayTicks = (long) (options.getDestructionDelay() * 20);
|
||||||
@@ -193,7 +199,7 @@ public class ExplosionUtils implements Main {
|
|||||||
}, destructionDelayTicks);
|
}, destructionDelayTicks);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void scheduleBurning(List<Block> blocksToMaybeBurn, Map<Block, Float> blocksHeatMap,
|
private void scheduleBurning(List<Block> blocksToMaybeBurn, Map<Block, Float> blocksHeatMap,
|
||||||
BlockBurner burner, Location center, ExplosionOptions options,
|
BlockBurner burner, Location center, ExplosionOptions options,
|
||||||
TaskManager taskManager) {
|
TaskManager taskManager) {
|
||||||
if (blocksToMaybeBurn.isEmpty()) return;
|
if (blocksToMaybeBurn.isEmpty()) return;
|
||||||
@@ -237,7 +243,7 @@ public class ExplosionUtils implements Main {
|
|||||||
}, burnDelayTicks);
|
}, burnDelayTicks);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void scheduleDamage(Map<UUID, Double> affected, ExplosionOptions options, TaskManager taskManager) {
|
private void scheduleDamage(Map<UUID, Double> affected, ExplosionOptions options, TaskManager taskManager) {
|
||||||
if (affected.isEmpty()) return;
|
if (affected.isEmpty()) return;
|
||||||
|
|
||||||
double baseDamage = options.getBaseDamage();
|
double baseDamage = options.getBaseDamage();
|
||||||
@@ -279,7 +285,7 @@ public class ExplosionUtils implements Main {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void createExplosionEffects(Location center, ExplosionOptions options) {
|
private void createExplosionEffects(Location center, ExplosionOptions options, TaskManager taskManager) {
|
||||||
World world = center.getWorld();
|
World world = center.getWorld();
|
||||||
if (world == null) return;
|
if (world == null) return;
|
||||||
|
|
||||||
@@ -297,15 +303,21 @@ public class ExplosionUtils implements Main {
|
|||||||
world.spawnParticle(Particle.LARGE_SMOKE, center, 15, 1, 1, 1, 0.05);
|
world.spawnParticle(Particle.LARGE_SMOKE, center, 15, 1, 1, 1, 0.05);
|
||||||
world.spawnParticle(Particle.FLAME, center, 30, 3, 3, 3, 0.1);
|
world.spawnParticle(Particle.FLAME, center, 30, 3, 3, 3, 0.1);
|
||||||
|
|
||||||
Bukkit.getScheduler().runTaskLater(main.getPlugin(), () -> {
|
taskManager.scheduleTask(()->{
|
||||||
if (center.getWorld() != null) {
|
if (center.getWorld() != null) {
|
||||||
center.getWorld().spawnParticle(Particle.SMOKE, center, 50, 4, 4, 4, 0.02);
|
center.getWorld().spawnParticle(Particle.SMOKE, center, 50, 4, 4, 4, 0.02);
|
||||||
|
ParticleUtils.builder()
|
||||||
|
.type(Particle.SMOKE)
|
||||||
|
.count((int) options.getCoreRadius()*10)
|
||||||
|
.offset(options.getCoreRadius()/2,options.getCoreRadius()/2,options.getCoreRadius()/2)
|
||||||
|
.speed(0.05F)
|
||||||
|
.spawn(center);
|
||||||
}
|
}
|
||||||
}, 20L);
|
},20L);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isOccluded(Block block, Set<Block> doesNotOcclude) {
|
private boolean isOccluded(Block block, Set<Block> doesNotOcclude) {
|
||||||
if (block == null) return true;
|
if (block == null) return true;
|
||||||
|
|
||||||
return isOccluding(block.getRelative(0, 1, 0), doesNotOcclude) &&
|
return isOccluding(block.getRelative(0, 1, 0), doesNotOcclude) &&
|
||||||
@@ -316,7 +328,7 @@ public class ExplosionUtils implements Main {
|
|||||||
isOccluding(block.getRelative(0, 0, -1), doesNotOcclude);
|
isOccluding(block.getRelative(0, 0, -1), doesNotOcclude);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isOccluding(Block block, Set<Block> doesNotOcclude) {
|
private boolean isOccluding(Block block, Set<Block> doesNotOcclude) {
|
||||||
return block != null && block.getType().isOccluding() && !doesNotOcclude.contains(block);
|
return block != null && block.getType().isOccluding() && !doesNotOcclude.contains(block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package me.trouper.alias.server.systems.world;
|
package me.trouper.alias.server.systems.world;
|
||||||
|
|
||||||
import me.trouper.alias.server.systems.burning.BurnOptions;
|
import me.trouper.alias.server.systems.world.burning.BurnOptions;
|
||||||
|
|
||||||
public class ExplosionOptions {
|
public class ExplosionOptions {
|
||||||
private double coreRadius = 3.0;
|
private double coreRadius = 3.0;
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
package me.trouper.alias.server.systems.world;
|
package me.trouper.alias.server.systems.world;
|
||||||
|
|
||||||
import me.trouper.alias.server.Main;
|
|
||||||
import me.trouper.alias.server.systems.TaskManager;
|
import me.trouper.alias.server.systems.TaskManager;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class ExplosionResult implements Closeable, Main {
|
public class ExplosionResult implements Closeable {
|
||||||
private State previousState;
|
private State previousState;
|
||||||
private TaskManager taskManager;
|
private TaskManager taskManager;
|
||||||
private volatile boolean closed = false;
|
private volatile boolean closed = false;
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
package me.trouper.alias.server.systems.world;
|
package me.trouper.alias.server.systems.world;
|
||||||
|
|
||||||
import me.trouper.alias.server.Main;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.BlockState;
|
import org.bukkit.block.BlockState;
|
||||||
import org.bukkit.inventory.Inventory;
|
import org.bukkit.inventory.Inventory;
|
||||||
@@ -50,7 +48,6 @@ public class Snapshot {
|
|||||||
public void restore(Block block) {
|
public void restore(Block block) {
|
||||||
if (block == null || state == null) return;
|
if (block == null || state == null) return;
|
||||||
|
|
||||||
Bukkit.getScheduler().runTask(Main.main.getPlugin(), () -> {
|
|
||||||
try {
|
try {
|
||||||
block.setBlockData(state.getBlockData());
|
block.setBlockData(state.getBlockData());
|
||||||
|
|
||||||
@@ -72,7 +69,6 @@ public class Snapshot {
|
|||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
System.err.println("Failed to restore block at " + block.getLocation() + ": " + e.getMessage());
|
System.err.println("Failed to restore block at " + block.getLocation() + ": " + e.getMessage());
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockState getState() {
|
public BlockState getState() {
|
||||||
|
|||||||
@@ -4,11 +4,7 @@ import org.bukkit.Location;
|
|||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.util.Collection;
|
import java.util.*;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class State implements Closeable {
|
public class State implements Closeable {
|
||||||
private Map<Location, Snapshot> snapshots;
|
private Map<Location, Snapshot> snapshots;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package me.trouper.alias.server.systems.burning;
|
package me.trouper.alias.server.systems.world.burning;
|
||||||
|
|
||||||
import me.trouper.alias.server.Main;
|
|
||||||
import me.trouper.alias.server.systems.TaskManager;
|
import me.trouper.alias.server.systems.TaskManager;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
@@ -13,17 +12,17 @@ import java.io.Closeable;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ThreadLocalRandom;
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
public class BlockBurner implements Closeable, Main {
|
public class BlockBurner implements Closeable {
|
||||||
private final BurnOptions options;
|
private final BurnOptions options;
|
||||||
private final BurnPalette palette;
|
private final BurnPalette palette;
|
||||||
private final TaskManager taskManager;
|
private final TaskManager taskManager;
|
||||||
private final Set<Block> visited = new HashSet<>();
|
private final Set<Block> visited = new HashSet<>();
|
||||||
private final Map<Block, Material> burning = new HashMap<>();
|
private final Map<Block, Material> burning = new HashMap<>();
|
||||||
|
|
||||||
public BlockBurner(BurnOptions options) {
|
public BlockBurner(TaskManager taskManager, BurnOptions options) {
|
||||||
|
this.taskManager = taskManager;
|
||||||
this.options = options;
|
this.options = options;
|
||||||
this.palette = new BurnPalette();
|
this.palette = new BurnPalette();
|
||||||
this.taskManager = new TaskManager();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package me.trouper.alias.server.systems.burning;
|
package me.trouper.alias.server.systems.world.burning;
|
||||||
|
|
||||||
public class BurnOptions {
|
public class BurnOptions {
|
||||||
private boolean disabled = false;
|
private boolean disabled = false;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package me.trouper.alias.server.systems.burning;
|
package me.trouper.alias.server.systems.world.burning;
|
||||||
|
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.Tag;
|
import org.bukkit.Tag;
|
||||||
@@ -30,7 +30,6 @@ public class BurnPalette {
|
|||||||
private final List<BlockData> burnWaveTrail;
|
private final List<BlockData> burnWaveTrail;
|
||||||
|
|
||||||
public BurnPalette() {
|
public BurnPalette() {
|
||||||
// Initialize burn wave trail
|
|
||||||
this.burnWaveTrail = Arrays.asList(
|
this.burnWaveTrail = Arrays.asList(
|
||||||
Material.ORANGE_STAINED_GLASS.createBlockData(),
|
Material.ORANGE_STAINED_GLASS.createBlockData(),
|
||||||
Material.BLACK_STAINED_GLASS.createBlockData(),
|
Material.BLACK_STAINED_GLASS.createBlockData(),
|
||||||
@@ -38,7 +37,6 @@ public class BurnPalette {
|
|||||||
Material.LIGHT_GRAY_STAINED_GLASS.createBlockData()
|
Material.LIGHT_GRAY_STAINED_GLASS.createBlockData()
|
||||||
);
|
);
|
||||||
|
|
||||||
// Initialize main burn wave
|
|
||||||
List<BlockData> baseBurnWave = new ArrayList<>();
|
List<BlockData> baseBurnWave = new ArrayList<>();
|
||||||
addRepeated(baseBurnWave, Material.ORANGE_STAINED_GLASS, 3);
|
addRepeated(baseBurnWave, Material.ORANGE_STAINED_GLASS, 3);
|
||||||
addRepeated(baseBurnWave, Material.SHROOMLIGHT, 2);
|
addRepeated(baseBurnWave, Material.SHROOMLIGHT, 2);
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package me.trouper.alias.server.systems.burning;
|
package me.trouper.alias.server.systems.world.burning;
|
||||||
|
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
|
|
||||||
@@ -1,41 +1,46 @@
|
|||||||
package me.trouper.alias.update;
|
package me.trouper.alias.server.update;
|
||||||
|
|
||||||
import me.trouper.alias.Alias;
|
import me.trouper.alias.AliasContext;
|
||||||
import me.trouper.alias.data.Common;
|
import me.trouper.alias.data.Common;
|
||||||
import org.bukkit.Bukkit;
|
import me.trouper.alias.utils.UpdateUtils;
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.security.MessageDigest;
|
|
||||||
import java.util.jar.JarEntry;
|
|
||||||
import java.util.jar.JarFile;
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
public class AutoUpdater {
|
public class AutoUpdater {
|
||||||
|
|
||||||
public static boolean checkUpdate(JavaPlugin plugin, Common common) {
|
private final AliasContext context;
|
||||||
|
|
||||||
|
public AutoUpdater(AliasContext context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean checkUpdate() {
|
||||||
try {
|
try {
|
||||||
if (UpdateUtils.isDevelopmentEnvironment(plugin)) {
|
if (UpdateUtils.isDevelopmentEnvironment(context.getPlugin())) {
|
||||||
plugin.getLogger().info("Development environment detected, bypassing update check.");
|
context.getPlugin().getLogger().info("Development environment detected, bypassing update check.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
String updateURL = common.getUpdateURL();
|
String updateURL = context.getCommon().getUpdateURL();
|
||||||
if (updateURL == null || updateURL.isEmpty()) {
|
if (updateURL == null || updateURL.isEmpty()) {
|
||||||
plugin.getLogger().warning("Update URL is not set.");
|
context.getPlugin().getLogger().warning("Update URL is not set.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
File updateDir = new File("plugins/update");
|
File updateDir = new File("plugins/update");
|
||||||
if (!updateDir.exists()) updateDir.mkdirs();
|
if (!updateDir.exists()) updateDir.mkdirs();
|
||||||
|
|
||||||
File currentFile = UpdateUtils.findPluginJar(plugin);
|
File currentFile = UpdateUtils.findPluginJar(context.getPlugin());
|
||||||
if (currentFile == null) {
|
if (currentFile == null) {
|
||||||
plugin.getLogger().severe("Could not locate plugin file in plugins folder.");
|
context.getPlugin().getLogger().severe("Could not locate plugin file in plugins folder.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,13 +49,13 @@ public class AutoUpdater {
|
|||||||
|
|
||||||
String remoteHashHex = UpdateUtils.fetchRemoteHash(remoteHashURL);
|
String remoteHashHex = UpdateUtils.fetchRemoteHash(remoteHashURL);
|
||||||
if (remoteHashHex == null) {
|
if (remoteHashHex == null) {
|
||||||
plugin.getLogger().warning("Failed to fetch remote hash from: " + remoteHashURL);
|
context.getPlugin().getLogger().warning("Failed to fetch remote hash from: " + remoteHashURL);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
String currentHashHex = UpdateUtils.bytesToHex(currentHash);
|
String currentHashHex = UpdateUtils.bytesToHex(currentHash);
|
||||||
if (remoteHashHex.equalsIgnoreCase(currentHashHex)) {
|
if (remoteHashHex.equalsIgnoreCase(currentHashHex)) {
|
||||||
plugin.getLogger().info("Plugin is up to date.");
|
context.getPlugin().getLogger().info("Plugin is up to date.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,35 +65,35 @@ public class AutoUpdater {
|
|||||||
String updateHashHex = UpdateUtils.bytesToHex(updateHash);
|
String updateHashHex = UpdateUtils.bytesToHex(updateHash);
|
||||||
|
|
||||||
if (remoteHashHex.equalsIgnoreCase(updateHashHex)) {
|
if (remoteHashHex.equalsIgnoreCase(updateHashHex)) {
|
||||||
plugin.getLogger().info("An update is already downloaded and ready.");
|
context.getPlugin().getLogger().info("An update is already downloaded and ready.");
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
plugin.getLogger().info("Found outdated update file in plugins/update/. It will be replaced.");
|
context.getPlugin().getLogger().info("Found outdated update file in plugins/update/. It will be replaced.");
|
||||||
updateFile.delete();
|
updateFile.delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin.getLogger().info("Update available. Downloading new version...");
|
context.getPlugin().getLogger().info("Update available. Downloading new version...");
|
||||||
File downloaded = downloadFile(updateURL);
|
File downloaded = downloadFile(updateURL);
|
||||||
if (downloaded == null) {
|
if (downloaded == null) {
|
||||||
plugin.getLogger().warning("Failed to download update file.");
|
context.getPlugin().getLogger().warning("Failed to download update file.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
File destination = new File(updateDir, currentFile.getName());
|
File destination = new File(updateDir, currentFile.getName());
|
||||||
Files.copy(downloaded.toPath(), destination.toPath(), java.nio.file.StandardCopyOption.REPLACE_EXISTING);
|
Files.copy(downloaded.toPath(), destination.toPath(), java.nio.file.StandardCopyOption.REPLACE_EXISTING);
|
||||||
plugin.getLogger().info("Saved updated plugin to: " + destination.getAbsolutePath());
|
context.getPlugin().getLogger().info("Saved updated plugin to: " + destination.getAbsolutePath());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
plugin.getLogger().log(Level.SEVERE, "Error during update check", e);
|
context.getPlugin().getLogger().log(Level.SEVERE, "Error during update check", e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static File downloadFile(String urlStr) throws IOException {
|
private File downloadFile(String urlStr) throws IOException {
|
||||||
URL url = new URL(urlStr);
|
URL url = new URL(urlStr);
|
||||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||||
conn.setRequestProperty("User-Agent", "AliasUpdater");
|
conn.setRequestProperty("User-Agent", "AliasUpdater");
|
||||||
@@ -4,13 +4,14 @@ import org.bukkit.block.BlockState;
|
|||||||
import org.bukkit.block.Container;
|
import org.bukkit.block.Container;
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.inventory.Inventory;
|
import org.bukkit.inventory.Inventory;
|
||||||
|
import org.bukkit.inventory.InventoryHolder;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.inventory.meta.BlockStateMeta;
|
import org.bukkit.inventory.meta.BlockStateMeta;
|
||||||
|
|
||||||
public final class InventoryUtils {
|
public class InventoryUtils {
|
||||||
|
|
||||||
public static Inventory getInventory(Entity entity) {
|
public static Inventory getInventory(Entity entity) {
|
||||||
if (entity instanceof org.bukkit.inventory.InventoryHolder inventoryHolder) {
|
if (entity instanceof InventoryHolder inventoryHolder) {
|
||||||
return inventoryHolder.getInventory();
|
return inventoryHolder.getInventory();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -1,19 +1,27 @@
|
|||||||
package me.trouper.alias.utils;
|
package me.trouper.alias.utils;
|
||||||
|
|
||||||
|
import com.destroystokyo.paper.profile.PlayerProfile;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.format.TextDecoration;
|
import net.kyori.adventure.text.format.TextDecoration;
|
||||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.OfflinePlayer;
|
||||||
import org.bukkit.attribute.Attribute;
|
import org.bukkit.attribute.Attribute;
|
||||||
import org.bukkit.attribute.AttributeModifier;
|
import org.bukkit.attribute.AttributeModifier;
|
||||||
import org.bukkit.enchantments.Enchantment;
|
import org.bukkit.enchantments.Enchantment;
|
||||||
import org.bukkit.inventory.ItemFlag;
|
import org.bukkit.inventory.ItemFlag;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.inventory.meta.ItemMeta;
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
|
import org.bukkit.inventory.meta.SkullMeta;
|
||||||
|
import org.bukkit.profile.PlayerTextures;
|
||||||
|
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
public class ItemBuilder {
|
public class ItemBuilder {
|
||||||
@@ -202,6 +210,78 @@ public class ItemBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ItemBuilder playerHead(String playerName) {
|
||||||
|
ensurePlayerHead();
|
||||||
|
if (this.meta instanceof SkullMeta skullMeta) {
|
||||||
|
OfflinePlayer player = Bukkit.getOfflinePlayer(playerName);
|
||||||
|
skullMeta.setOwningPlayer(player);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemBuilder playerHead(OfflinePlayer player) {
|
||||||
|
ensurePlayerHead();
|
||||||
|
if (this.meta instanceof SkullMeta skullMeta) {
|
||||||
|
skullMeta.setOwningPlayer(player);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemBuilder playerHead(UUID uuid) {
|
||||||
|
ensurePlayerHead();
|
||||||
|
if (this.meta instanceof SkullMeta skullMeta) {
|
||||||
|
OfflinePlayer player = Bukkit.getOfflinePlayer(uuid);
|
||||||
|
skullMeta.setOwningPlayer(player);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemBuilder skullTexture(String textureUrl) {
|
||||||
|
ensurePlayerHead();
|
||||||
|
if (this.meta instanceof SkullMeta skullMeta) {
|
||||||
|
try {
|
||||||
|
PlayerProfile profile = Bukkit.createProfile(UUID.randomUUID());
|
||||||
|
PlayerTextures textures = profile.getTextures();
|
||||||
|
textures.setSkin(new URL(textureUrl));
|
||||||
|
profile.setTextures(textures);
|
||||||
|
skullMeta.setPlayerProfile(profile);
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
throw new IllegalArgumentException("Invalid texture URL: " + textureUrl, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemBuilder skullProfile(PlayerProfile profile) {
|
||||||
|
ensurePlayerHead();
|
||||||
|
if (this.meta instanceof SkullMeta skullMeta) {
|
||||||
|
skullMeta.setPlayerProfile(profile);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemBuilder createPlayerHead(String playerName, String displayName) {
|
||||||
|
return material(Material.PLAYER_HEAD)
|
||||||
|
.playerHead(playerName)
|
||||||
|
.displayName(displayName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemBuilder createCustomHead(String textureUrl, String displayName) {
|
||||||
|
return material(Material.PLAYER_HEAD)
|
||||||
|
.skullTexture(textureUrl)
|
||||||
|
.displayName(displayName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ensurePlayerHead() {
|
||||||
|
if (this.stack.getType() != Material.PLAYER_HEAD) {
|
||||||
|
this.stack = this.stack.withType(Material.PLAYER_HEAD);
|
||||||
|
this.meta = this.stack.getItemMeta();
|
||||||
|
if (this.meta == null) {
|
||||||
|
throw new IllegalStateException("Failed to get SkullMeta after converting to player head");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public ItemStack build() {
|
public ItemStack build() {
|
||||||
this.stack.setItemMeta(this.meta);
|
this.stack.setItemMeta(this.meta);
|
||||||
return this.stack.clone();
|
return this.stack.clone();
|
||||||
@@ -246,4 +326,14 @@ public class ItemBuilder {
|
|||||||
public static ItemBuilder of(ItemStack stack) {
|
public static ItemBuilder of(ItemStack stack) {
|
||||||
return create(stack);
|
return create(stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ItemBuilder headOf(String playerName) {
|
||||||
|
return create(Material.PLAYER_HEAD)
|
||||||
|
.playerHead(playerName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ItemBuilder headOfTexture(String url) {
|
||||||
|
return create(Material.PLAYER_HEAD)
|
||||||
|
.skullTexture(url);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package me.trouper.alias.server.systems.visual;
|
package me.trouper.alias.utils;
|
||||||
|
|
||||||
import org.bukkit.*;
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.Particle;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package me.trouper.alias.update;
|
package me.trouper.alias.utils;
|
||||||
|
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
@@ -86,7 +86,6 @@ public class UpdateUtils {
|
|||||||
try {
|
try {
|
||||||
return "TRUE".equalsIgnoreCase(System.getenv("ALIAS_DEVELOPMENT"));
|
return "TRUE".equalsIgnoreCase(System.getenv("ALIAS_DEVELOPMENT"));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
plugin.getLogger().warning("Could not determine runtime environment, assuming production.");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,7 +3,6 @@ package me.trouper.alias.utils.misc;
|
|||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.net.URL;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.jar.JarEntry;
|
import java.util.jar.JarEntry;
|
||||||
|
|||||||
Reference in New Issue
Block a user