mirror of
https://github.com/TotalFreedomMC/PlayerParticles.git
synced 2025-07-24 06:24:00 +00:00
Version compatibility, craftbukkit error message
This commit is contained in:
parent
26cf3d2d33
commit
2d55d21a2a
39 changed files with 1744 additions and 587 deletions
|
@ -10,7 +10,7 @@ For information about how to use the plugin or API within the plugin, please ref
|
|||
### Server Compatibility
|
||||
This plugin is compatible with [Spigot](https://www.spigotmc.org/) and any forks, I recommend using [Paper](https://papermc.io/).
|
||||
Using CraftBukkit will not work.
|
||||
The versions of Minecraft that are currently supported are 1.9.4-1.15.x. Support for 1.8.8 will not be added.
|
||||
The versions of Minecraft that are currently supported are `1.15.2-1.7.10`.
|
||||
|
||||
### Compilation
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ sourceCompatibility = 1.8
|
|||
targetCompatibility = 1.8
|
||||
compileJava.options.encoding = 'UTF-8'
|
||||
group = 'dev.esophose'
|
||||
version = '7.10'
|
||||
version = '7.11'
|
||||
|
||||
java {
|
||||
withJavadocJar()
|
||||
|
@ -30,6 +30,8 @@ dependencies {
|
|||
compile 'org.slf4j:slf4j-api:1.7.25'
|
||||
compile 'org.slf4j:slf4j-nop:1.7.25'
|
||||
compile 'com.zaxxer:HikariCP:3.2.0'
|
||||
compile 'org.bstats:bstats-bukkit-lite:1.7'
|
||||
shadow 'com.googlecode.json-simple:json-simple:1.1.1'
|
||||
shadow 'org.jetbrains:annotations:16.0.2'
|
||||
shadow 'me.clip:placeholderapi:2.10.4'
|
||||
shadow 'org.xerial:sqlite-jdbc:3.23.1'
|
||||
|
@ -39,6 +41,10 @@ dependencies {
|
|||
shadowJar {
|
||||
archiveClassifier.set(null)
|
||||
minimize()
|
||||
|
||||
relocate('org.bstats', 'dev.esophose.playerparticles.libs.bstats')
|
||||
relocate('org.slf4j', 'dev.esophose.playerparticles.libs.slf4j')
|
||||
relocate('com.zaxxer.hikari', 'dev.esophose.playerparticles.libs.hikaricp')
|
||||
}
|
||||
|
||||
processResources {
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
=== v7.11 ===
|
||||
+ Added support for Spigot 1.8.8 and 1.7.10. I make no guarantees this will work perfectly.
|
||||
* The plugin will now disable and print an error message on startup if the server is running CraftBukkit
|
||||
* Removed deprecated API
|
||||
* Other API-breaking changes (Moved the color data classes to a different package)
|
||||
* Removed the version number from generating in new config.yml files
|
||||
=== v7.10 ===
|
||||
+ Added command '/pp reset <player>' to be able to reset the particles of an offline player
|
||||
- Permission: 'playerparticles.reset.others'
|
||||
|
|
|
@ -23,9 +23,11 @@ import dev.esophose.playerparticles.manager.PermissionManager;
|
|||
import dev.esophose.playerparticles.manager.PluginUpdateManager;
|
||||
import dev.esophose.playerparticles.particles.listener.PPlayerCombatListener;
|
||||
import dev.esophose.playerparticles.particles.listener.PPlayerMovementListener;
|
||||
import dev.esophose.playerparticles.util.Metrics;
|
||||
import dev.esophose.playerparticles.util.LegacyMetrics;
|
||||
import dev.esophose.playerparticles.util.NMSUtil;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import org.bstats.bukkit.MetricsLite;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
@ -55,6 +57,12 @@ public class PlayerParticles extends JavaPlugin {
|
|||
*/
|
||||
@Override
|
||||
public void onEnable() {
|
||||
if (!NMSUtil.isSpigot()) {
|
||||
this.getLogger().severe("This plugin is only compatible with Spigot and other forks. CraftBukkit is not supported. Disabling PlayerParticles.");
|
||||
Bukkit.getPluginManager().disablePlugin(this);
|
||||
return;
|
||||
}
|
||||
|
||||
this.reload();
|
||||
|
||||
PluginManager pm = Bukkit.getPluginManager();
|
||||
|
@ -62,8 +70,13 @@ public class PlayerParticles extends JavaPlugin {
|
|||
pm.registerEvents(new PPlayerCombatListener(), this);
|
||||
pm.registerEvents(new PlayerChatHook(), this);
|
||||
|
||||
if (Setting.SEND_METRICS.getBoolean())
|
||||
new Metrics(this);
|
||||
if (Setting.SEND_METRICS.getBoolean()) {
|
||||
if (NMSUtil.getVersionNumber() > 7) {
|
||||
new MetricsLite(this, 3531);
|
||||
} else {
|
||||
new LegacyMetrics(this);
|
||||
}
|
||||
}
|
||||
|
||||
if (PlaceholderAPIHook.enabled())
|
||||
new ParticlePlaceholderExpansion(this).register();
|
||||
|
|
|
@ -10,10 +10,10 @@ import dev.esophose.playerparticles.particles.ConsolePPlayer;
|
|||
import dev.esophose.playerparticles.particles.FixedParticleEffect;
|
||||
import dev.esophose.playerparticles.particles.PPlayer;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect.NoteColor;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect.OrdinaryColor;
|
||||
import dev.esophose.playerparticles.particles.ParticleGroup;
|
||||
import dev.esophose.playerparticles.particles.ParticlePair;
|
||||
import dev.esophose.playerparticles.particles.data.NoteColor;
|
||||
import dev.esophose.playerparticles.particles.data.OrdinaryColor;
|
||||
import dev.esophose.playerparticles.styles.ParticleStyle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
@ -1059,34 +1059,4 @@ public final class PlayerParticlesAPI {
|
|||
|
||||
//endregion
|
||||
|
||||
//region Registering Custom Styles
|
||||
|
||||
/**
|
||||
* Registers a particle style with the plugin
|
||||
*
|
||||
* @param particleStyle The particle style to register
|
||||
* @deprecated Use {@link ParticleStyleRegistrationEvent} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public void registerParticleStyle(@NotNull ParticleStyle particleStyle) {
|
||||
Objects.requireNonNull(particleStyle);
|
||||
|
||||
this.playerParticles.getManager(ParticleStyleManager.class).registerStyle(particleStyle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers an event-based particle style with the plugin
|
||||
*
|
||||
* @param particleStyle The particle style to register
|
||||
* @deprecated Use {@link ParticleStyleRegistrationEvent} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public void registerEventParticleStyle(@NotNull ParticleStyle particleStyle) {
|
||||
Objects.requireNonNull(particleStyle);
|
||||
|
||||
this.playerParticles.getManager(ParticleStyleManager.class).registerEventStyle(particleStyle);
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
}
|
||||
|
|
|
@ -7,11 +7,11 @@ import dev.esophose.playerparticles.manager.ParticleStyleManager;
|
|||
import dev.esophose.playerparticles.manager.PermissionManager;
|
||||
import dev.esophose.playerparticles.particles.PPlayer;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect.NoteColor;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect.OrdinaryColor;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect.ParticleProperty;
|
||||
import dev.esophose.playerparticles.particles.ParticleGroup;
|
||||
import dev.esophose.playerparticles.particles.ParticlePair;
|
||||
import dev.esophose.playerparticles.particles.data.NoteColor;
|
||||
import dev.esophose.playerparticles.particles.data.OrdinaryColor;
|
||||
import dev.esophose.playerparticles.styles.ParticleStyle;
|
||||
import dev.esophose.playerparticles.util.ParticleUtils;
|
||||
import dev.esophose.playerparticles.util.StringPlaceholders;
|
||||
|
|
|
@ -6,11 +6,11 @@ import dev.esophose.playerparticles.manager.LocaleManager;
|
|||
import dev.esophose.playerparticles.manager.PermissionManager;
|
||||
import dev.esophose.playerparticles.particles.PPlayer;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect.NoteColor;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect.OrdinaryColor;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect.ParticleProperty;
|
||||
import dev.esophose.playerparticles.particles.ParticleGroup;
|
||||
import dev.esophose.playerparticles.particles.ParticlePair;
|
||||
import dev.esophose.playerparticles.particles.data.NoteColor;
|
||||
import dev.esophose.playerparticles.particles.data.OrdinaryColor;
|
||||
import dev.esophose.playerparticles.styles.ParticleStyle;
|
||||
import dev.esophose.playerparticles.util.ParticleUtils;
|
||||
import dev.esophose.playerparticles.util.StringPlaceholders;
|
||||
|
|
|
@ -7,10 +7,10 @@ import dev.esophose.playerparticles.manager.PermissionManager;
|
|||
import dev.esophose.playerparticles.particles.FixedParticleEffect;
|
||||
import dev.esophose.playerparticles.particles.PPlayer;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect.NoteColor;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect.OrdinaryColor;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect.ParticleProperty;
|
||||
import dev.esophose.playerparticles.particles.ParticlePair;
|
||||
import dev.esophose.playerparticles.particles.data.NoteColor;
|
||||
import dev.esophose.playerparticles.particles.data.OrdinaryColor;
|
||||
import dev.esophose.playerparticles.styles.ParticleStyle;
|
||||
import dev.esophose.playerparticles.util.ParticleUtils;
|
||||
import dev.esophose.playerparticles.util.StringPlaceholders;
|
||||
|
|
|
@ -3,6 +3,7 @@ package dev.esophose.playerparticles.gui;
|
|||
import dev.esophose.playerparticles.gui.GuiInventoryEditData.ColorData;
|
||||
import dev.esophose.playerparticles.hook.PlaceholderAPIHook;
|
||||
import dev.esophose.playerparticles.particles.PPlayer;
|
||||
import dev.esophose.playerparticles.util.NMSUtil;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.bukkit.ChatColor;
|
||||
|
@ -107,7 +108,9 @@ public class GuiActionButton {
|
|||
if (this.colors[0].getMaterial() != null) { // Use Materials
|
||||
itemStack = new ItemStack(this.colors[this.iconIndex].getMaterial());
|
||||
} else { // Use Dyes
|
||||
itemStack = new Dye(this.colors[this.iconIndex].getDyeColor()).toItemStack(1);
|
||||
Dye dye = new Dye();
|
||||
dye.setColor(this.colors[this.iconIndex].getDyeColor());
|
||||
itemStack = dye.toItemStack(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,7 +118,8 @@ public class GuiActionButton {
|
|||
if (itemMeta != null) {
|
||||
itemMeta.setDisplayName(PlaceholderAPIHook.applyPlaceholders(pplayer.getPlayer(), this.name));
|
||||
itemMeta.setLore(parseLore(pplayer, this.lore));
|
||||
itemMeta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES, ItemFlag.HIDE_POTION_EFFECTS);
|
||||
if (NMSUtil.getVersionNumber() > 7)
|
||||
itemMeta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES, ItemFlag.HIDE_POTION_EFFECTS);
|
||||
itemStack.setItemMeta(itemMeta);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package dev.esophose.playerparticles.gui;
|
|||
import dev.esophose.playerparticles.PlayerParticles;
|
||||
import dev.esophose.playerparticles.manager.ConfigurationManager.Setting;
|
||||
import dev.esophose.playerparticles.particles.PPlayer;
|
||||
import dev.esophose.playerparticles.util.NMSUtil;
|
||||
import dev.esophose.playerparticles.util.ParticleUtils;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -56,7 +57,8 @@ public abstract class GuiInventory {
|
|||
ItemMeta meta = borderIcon.getItemMeta();
|
||||
if (meta != null) {
|
||||
meta.setDisplayName(" ");
|
||||
meta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES, ItemFlag.HIDE_POTION_EFFECTS, ItemFlag.HIDE_ENCHANTS);
|
||||
if (NMSUtil.getVersionNumber() > 7)
|
||||
meta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES, ItemFlag.HIDE_POTION_EFFECTS, ItemFlag.HIDE_ENCHANTS);
|
||||
borderIcon.setItemMeta(meta);
|
||||
}
|
||||
|
||||
|
@ -155,7 +157,11 @@ public abstract class GuiInventory {
|
|||
button.handleClick(isShiftClick);
|
||||
if (Setting.GUI_BUTTON_SOUND.getBoolean() && event.getWhoClicked() instanceof Player) {
|
||||
Player player = (Player) event.getWhoClicked();
|
||||
player.playSound(player.getLocation(), Sound.UI_BUTTON_CLICK, 0.5f, 1);
|
||||
if (NMSUtil.getVersionNumber() > 8) {
|
||||
player.playSound(player.getLocation(), Sound.UI_BUTTON_CLICK, 0.5f, 1);
|
||||
} else {
|
||||
player.playSound(player.getLocation(), Sound.valueOf("CLICK"), 0.5f, 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -6,10 +6,10 @@ import dev.esophose.playerparticles.manager.GuiManager;
|
|||
import dev.esophose.playerparticles.manager.LocaleManager;
|
||||
import dev.esophose.playerparticles.particles.PPlayer;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect.NoteColor;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect.OrdinaryColor;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect.ParticleProperty;
|
||||
import dev.esophose.playerparticles.particles.ParticlePair;
|
||||
import dev.esophose.playerparticles.particles.data.NoteColor;
|
||||
import dev.esophose.playerparticles.particles.data.OrdinaryColor;
|
||||
import dev.esophose.playerparticles.util.NMSUtil;
|
||||
import dev.esophose.playerparticles.util.ParticleUtils;
|
||||
import dev.esophose.playerparticles.util.StringPlaceholders;
|
||||
|
|
|
@ -16,11 +16,11 @@ import org.bukkit.Material;
|
|||
public class ConfigurationManager extends Manager {
|
||||
|
||||
private static final String[] HEADER = new String[] {
|
||||
" _________ __ __________ __ __ __ _________",
|
||||
" \\______ \\ | _____ ___ __ __________\\______ \\_____ ________/ |_|__| ____ | | ____ ______ \\______ \\",
|
||||
" | ___/ | \\__ \\< | |/ __ \\_ __ \\ ___/\\__ \\\\_ __ \\ __\\ |/ ___\\| | _/ __ \\ / ___/ / /",
|
||||
" | | | |__/ __ \\\\___ \\ ___/| | \\/ | / __ \\| | \\/| | | \\ \\___| |_\\ ___/ \\___ \\ / /",
|
||||
" |____| |____(____ / ____|\\___ >__| |____| (____ /__| |__| |__|\\___ >____/\\___ >____ > /____/",
|
||||
" _________ __ __________ __ __ __",
|
||||
" \\______ \\ | _____ ___ __ __________\\______ \\_____ ________/ |_|__| ____ | | ____ ______",
|
||||
" | ___/ | \\__ \\< | |/ __ \\_ __ \\ ___/\\__ \\\\_ __ \\ __\\ |/ ___\\| | _/ __ \\ / ___/",
|
||||
" | | | |__/ __ \\\\___ \\ ___/| | \\/ | / __ \\| | \\/| | | \\ \\___| |_\\ ___/ \\___ \\",
|
||||
" |____| |____(____ / ____|\\___ >__| |____| (____ /__| |__| |__|\\___ >____/\\___ >____ >",
|
||||
" \\/\\/ \\/ \\/ \\/ \\/ \\/"
|
||||
};
|
||||
|
||||
|
@ -332,7 +332,7 @@ public class ConfigurationManager extends Manager {
|
|||
}
|
||||
|
||||
if (material == null)
|
||||
material = Material.BARRIER;
|
||||
material = ParticleUtils.FALLBACK_MATERIAL;
|
||||
|
||||
this.materials.put(configPath, material);
|
||||
|
||||
|
|
|
@ -9,10 +9,10 @@ import dev.esophose.playerparticles.particles.ConsolePPlayer;
|
|||
import dev.esophose.playerparticles.particles.FixedParticleEffect;
|
||||
import dev.esophose.playerparticles.particles.PPlayer;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect.NoteColor;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect.OrdinaryColor;
|
||||
import dev.esophose.playerparticles.particles.ParticleGroup;
|
||||
import dev.esophose.playerparticles.particles.ParticlePair;
|
||||
import dev.esophose.playerparticles.particles.data.NoteColor;
|
||||
import dev.esophose.playerparticles.particles.data.OrdinaryColor;
|
||||
import dev.esophose.playerparticles.styles.ParticleStyle;
|
||||
import dev.esophose.playerparticles.util.ParticleUtils;
|
||||
import java.sql.PreparedStatement;
|
||||
|
|
|
@ -3,12 +3,12 @@ package dev.esophose.playerparticles.manager;
|
|||
import dev.esophose.playerparticles.PlayerParticles;
|
||||
import dev.esophose.playerparticles.particles.PPlayer;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect.NoteColor;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect.OrdinaryColor;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect.ParticleProperty;
|
||||
import dev.esophose.playerparticles.particles.ParticleGroup;
|
||||
import dev.esophose.playerparticles.particles.ParticleGroupPreset;
|
||||
import dev.esophose.playerparticles.particles.ParticlePair;
|
||||
import dev.esophose.playerparticles.particles.data.NoteColor;
|
||||
import dev.esophose.playerparticles.particles.data.OrdinaryColor;
|
||||
import dev.esophose.playerparticles.styles.ParticleStyle;
|
||||
import dev.esophose.playerparticles.util.inputparser.InputParser;
|
||||
import java.io.File;
|
||||
|
|
|
@ -7,10 +7,11 @@ import dev.esophose.playerparticles.particles.FixedParticleEffect;
|
|||
import dev.esophose.playerparticles.particles.PParticle;
|
||||
import dev.esophose.playerparticles.particles.PPlayer;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect.NoteColor;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect.OrdinaryColor;
|
||||
import dev.esophose.playerparticles.particles.ParticlePair;
|
||||
import dev.esophose.playerparticles.particles.data.NoteColor;
|
||||
import dev.esophose.playerparticles.particles.data.OrdinaryColor;
|
||||
import dev.esophose.playerparticles.styles.DefaultStyles;
|
||||
import dev.esophose.playerparticles.util.NMSUtil;
|
||||
import java.awt.Color;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
@ -151,7 +152,7 @@ public class ParticleManager extends Manager implements Listener, Runnable {
|
|||
|
||||
// Don't show their particles if they are in spectator mode
|
||||
// Don't spawn particles if the world doesn't allow it
|
||||
if (player != null && player.getGameMode() != GameMode.SPECTATOR && permissionManager.isWorldEnabled(player.getWorld().getName()))
|
||||
if (player != null && (NMSUtil.getVersionNumber() < 8 || player.getGameMode() != GameMode.SPECTATOR) && permissionManager.isWorldEnabled(player.getWorld().getName()))
|
||||
for (ParticlePair particles : pplayer.getActiveParticles())
|
||||
this.displayParticles(pplayer, particles, player.getLocation().clone().add(0, 1, 0));
|
||||
|
||||
|
@ -214,7 +215,7 @@ public class ParticleManager extends Manager implements Listener, Runnable {
|
|||
*/
|
||||
public void displayParticles(Player player, World world, ParticlePair particle, List<PParticle> particles, boolean isLongRange) {
|
||||
PermissionManager permissionManager = this.playerParticles.getManager(PermissionManager.class);
|
||||
if ((player != null && player.getGameMode() == GameMode.SPECTATOR) || !permissionManager.isWorldEnabled(world.getName()))
|
||||
if ((player != null && (NMSUtil.getVersionNumber() < 8 || player.getGameMode() == GameMode.SPECTATOR)) || !permissionManager.isWorldEnabled(world.getName()))
|
||||
return;
|
||||
|
||||
for (PParticle pparticle : particles)
|
||||
|
|
|
@ -74,43 +74,6 @@ public class ParticleStyleManager extends Manager {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a style that is put into the plugin's update loop
|
||||
*
|
||||
* @param style The style to add
|
||||
*/
|
||||
@Deprecated
|
||||
public void registerStyle(ParticleStyle style) {
|
||||
if (style == null) {
|
||||
throw new IllegalArgumentException("Tried to register a null style");
|
||||
}
|
||||
|
||||
if (style.getInternalName() == null || style.getInternalName().trim().equals("")) {
|
||||
throw new IllegalArgumentException("Tried to register a style with a null or empty name: '" + style.getInternalName() + "'");
|
||||
}
|
||||
|
||||
for (ParticleStyle testAgainst : this.styles) {
|
||||
if (testAgainst.equals(style)) {
|
||||
throw new IllegalArgumentException("Tried to register the same style twice: '" + style.getInternalName() + "'");
|
||||
} else if (testAgainst.getInternalName().equalsIgnoreCase(style.getInternalName())) {
|
||||
throw new IllegalArgumentException("Tried to register two styles with the same internal name spelling: '" + style.getInternalName() + "'");
|
||||
}
|
||||
}
|
||||
|
||||
this.styles.add(style);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a style that isn't updated on the normal update loop
|
||||
*
|
||||
* @param style The style to register
|
||||
*/
|
||||
@Deprecated
|
||||
public void registerEventStyle(ParticleStyle style) {
|
||||
this.registerStyle(style);
|
||||
this.eventStyles.add(style);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if a given style is customly handled
|
||||
*
|
||||
|
|
|
@ -3,8 +3,13 @@ package dev.esophose.playerparticles.particles;
|
|||
import com.google.common.collect.ObjectArrays;
|
||||
import dev.esophose.playerparticles.PlayerParticles;
|
||||
import dev.esophose.playerparticles.config.CommentedFileConfiguration;
|
||||
import dev.esophose.playerparticles.manager.ConfigurationManager.Setting;
|
||||
import dev.esophose.playerparticles.manager.ParticleManager;
|
||||
import dev.esophose.playerparticles.particles.data.ParticleColor;
|
||||
import dev.esophose.playerparticles.particles.spawning.ParticleSpawner;
|
||||
import dev.esophose.playerparticles.particles.spawning.ParticleSpawner.ParticleColorException;
|
||||
import dev.esophose.playerparticles.particles.spawning.ParticleSpawner.ParticleDataException;
|
||||
import dev.esophose.playerparticles.particles.spawning.ReflectiveParticleSpawner;
|
||||
import dev.esophose.playerparticles.particles.spawning.SpigotParticleSpawner;
|
||||
import dev.esophose.playerparticles.particles.spawning.reflective.ReflectiveParticleEffectMapping;
|
||||
import dev.esophose.playerparticles.util.NMSUtil;
|
||||
import dev.esophose.playerparticles.util.ParticleUtils;
|
||||
import java.io.File;
|
||||
|
@ -12,19 +17,12 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Stream;
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.Particle.DustOptions;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.material.MaterialData;
|
||||
import org.bukkit.metadata.MetadataValue;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public enum ParticleEffect {
|
||||
|
||||
// Ordered and named by their Minecraft 1.13+ internal names
|
||||
|
@ -92,8 +90,14 @@ public enum ParticleEffect {
|
|||
UNDERWATER("SUSPENDED_DEPTH", Arrays.asList("TURTLE_HELMET", "SPONGE")),
|
||||
WITCH("SPELL_WITCH", Collections.singletonList("CAULDRON"));
|
||||
|
||||
private final static ParticleSpawner particleSpawner;
|
||||
static {
|
||||
particleSpawner = NMSUtil.getVersionNumber() >= 9 ? new SpigotParticleSpawner() : new ReflectiveParticleSpawner();
|
||||
}
|
||||
|
||||
private Particle internalEnum;
|
||||
private List<ParticleProperty> properties;
|
||||
private boolean supported;
|
||||
|
||||
private CommentedFileConfiguration config;
|
||||
private boolean enabledByDefault;
|
||||
|
@ -128,7 +132,16 @@ public enum ParticleEffect {
|
|||
this.properties = Arrays.asList(properties);
|
||||
|
||||
// Will be null if this server's version doesn't support this particle type
|
||||
this.internalEnum = Stream.of(Particle.values()).filter(x -> x.name().equals(enumName)).findFirst().orElse(null);
|
||||
if (NMSUtil.getVersionNumber() > 8) {
|
||||
this.internalEnum = Stream.of(Particle.values()).filter(x -> x.name().equals(enumName)).findFirst().orElse(null);
|
||||
this.supported = this.internalEnum != null;
|
||||
} else {
|
||||
try {
|
||||
this.supported = ReflectiveParticleEffectMapping.valueOf(this.name()).isSupported();
|
||||
} catch (Exception e) {
|
||||
this.supported = false;
|
||||
}
|
||||
}
|
||||
|
||||
this.setDefaultSettings();
|
||||
this.loadSettings(false);
|
||||
|
@ -217,6 +230,13 @@ public enum ParticleEffect {
|
|||
return this.effectName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the Spigot enum this represents
|
||||
*/
|
||||
public Particle getSpigotEnum() {
|
||||
return this.internalEnum;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The Material icon that represents this style in the GUI
|
||||
*/
|
||||
|
@ -240,7 +260,7 @@ public enum ParticleEffect {
|
|||
* @return Whether the particle effect is supported or not
|
||||
*/
|
||||
public boolean isSupported() {
|
||||
return this.internalEnum != null;
|
||||
return this.supported;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -317,12 +337,8 @@ public enum ParticleEffect {
|
|||
* @param owner The player that owns the particles
|
||||
* @throws ParticleDataException If the particle effect requires additional data
|
||||
*/
|
||||
public void display(double offsetX, double offsetY, double offsetZ, double speed, int amount, Location center, boolean isLongRange, Player owner) throws ParticleDataException {
|
||||
if (this.hasProperty(ParticleProperty.REQUIRES_MATERIAL_DATA))
|
||||
throw new ParticleDataException("This particle effect requires additional data");
|
||||
|
||||
for (Player player : this.getPlayersInRange(center, isLongRange, owner))
|
||||
player.spawnParticle(this.internalEnum, center.getX(), center.getY(), center.getZ(), amount, offsetX, offsetY, offsetZ, speed);
|
||||
public void display(double offsetX, double offsetY, double offsetZ, double speed, int amount, Location center, boolean isLongRange, Player owner) {
|
||||
particleSpawner.display(this, offsetX, offsetY, offsetZ, speed, amount, center, isLongRange, owner);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -334,21 +350,8 @@ public enum ParticleEffect {
|
|||
* @param owner The player that owns the particles
|
||||
* @throws ParticleColorException If the particle effect is not colorable or the color type is incorrect
|
||||
*/
|
||||
public void display(ParticleColor color, Location center, boolean isLongRange, Player owner) throws ParticleColorException {
|
||||
if (!this.hasProperty(ParticleProperty.COLORABLE))
|
||||
throw new ParticleColorException("This particle effect is not colorable");
|
||||
|
||||
if (this == DUST && NMSUtil.getVersionNumber() >= 13) { // DUST uses a special data object for spawning in 1.13+
|
||||
OrdinaryColor dustColor = (OrdinaryColor) color;
|
||||
DustOptions dustOptions = new DustOptions(Color.fromRGB(dustColor.getRed(), dustColor.getGreen(), dustColor.getBlue()), Setting.DUST_SIZE.getFloat());
|
||||
for (Player player : this.getPlayersInRange(center, isLongRange, owner))
|
||||
player.spawnParticle(this.internalEnum, center.getX(), center.getY(), center.getZ(), 1, 0, 0, 0, 0, dustOptions);
|
||||
} else {
|
||||
for (Player player : this.getPlayersInRange(center, isLongRange, owner)) {
|
||||
// Minecraft clients require that you pass a non-zero value if the Red value should be zero
|
||||
player.spawnParticle(this.internalEnum, center.getX(), center.getY(), center.getZ(), 0, this == ParticleEffect.DUST && color.getValueX() == 0 ? Float.MIN_VALUE : color.getValueX(), color.getValueY(), color.getValueZ(), 1);
|
||||
}
|
||||
}
|
||||
public void display(ParticleColor color, Location center, boolean isLongRange, Player owner) {
|
||||
particleSpawner.display(this, color, center, isLongRange, owner);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -367,65 +370,8 @@ public enum ParticleEffect {
|
|||
* @param owner The player that owns the particles
|
||||
* @throws ParticleDataException If the particle effect does not require additional data or if the data type is incorrect
|
||||
*/
|
||||
public void display(Material spawnMaterial, double offsetX, double offsetY, double offsetZ, double speed, int amount, Location center, boolean isLongRange, Player owner) throws ParticleDataException {
|
||||
if (!this.hasProperty(ParticleProperty.REQUIRES_MATERIAL_DATA)) {
|
||||
throw new ParticleDataException("This particle effect does not require additional data");
|
||||
}
|
||||
|
||||
Object extraData = null;
|
||||
if (this.internalEnum.getDataType().getTypeName().equals("org.bukkit.block.data.BlockData")) {
|
||||
extraData = spawnMaterial.createBlockData();
|
||||
} else if (this.internalEnum.getDataType() == ItemStack.class) {
|
||||
extraData = new ItemStack(spawnMaterial);
|
||||
} else if (this.internalEnum.getDataType() == MaterialData.class) {
|
||||
extraData = new MaterialData(spawnMaterial); // Deprecated, only used in versions < 1.13
|
||||
}
|
||||
|
||||
for (Player player : this.getPlayersInRange(center, isLongRange, owner))
|
||||
player.spawnParticle(this.internalEnum, center.getX(), center.getY(), center.getZ(), amount, offsetX, offsetY, offsetZ, speed, extraData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a List of Players within the particle display range
|
||||
*
|
||||
* @param center The center of the radius to check around
|
||||
* @param isLongRange If the particle can be viewed from long range
|
||||
* @param owner The player that owns the particles
|
||||
* @return A List of Players within the particle display range
|
||||
*/
|
||||
private List<Player> getPlayersInRange(Location center, boolean isLongRange, Player owner) {
|
||||
List<Player> players = new ArrayList<>();
|
||||
int range = !isLongRange ? Setting.PARTICLE_RENDER_RANGE_PLAYER.getInt() : Setting.PARTICLE_RENDER_RANGE_FIXED_EFFECT.getInt();
|
||||
range *= range;
|
||||
|
||||
for (PPlayer pplayer : PlayerParticles.getInstance().getManager(ParticleManager.class).getPPlayers()) {
|
||||
Player p = pplayer.getPlayer();
|
||||
if (!this.canSee(p, owner))
|
||||
continue;
|
||||
|
||||
if (p != null && pplayer.canSeeParticles() && p.getWorld().equals(center.getWorld()) && center.distanceSquared(p.getLocation()) <= range)
|
||||
players.add(p);
|
||||
}
|
||||
|
||||
return players;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a player can see another player
|
||||
*
|
||||
* @param player The player
|
||||
* @param target The target
|
||||
* @return True if player can see target, otherwise false
|
||||
*/
|
||||
private boolean canSee(Player player, Player target) {
|
||||
if (player == null || target == null)
|
||||
return true;
|
||||
|
||||
for (MetadataValue meta : target.getMetadata("vanished"))
|
||||
if (meta.asBoolean())
|
||||
return false;
|
||||
|
||||
return player.canSee(target);
|
||||
public void display(Material spawnMaterial, double offsetX, double offsetY, double offsetZ, double speed, int amount, Location center, boolean isLongRange, Player owner) {
|
||||
particleSpawner.display(this, spawnMaterial, offsetX, offsetY, offsetZ, speed, amount, center, isLongRange, owner);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -448,310 +394,4 @@ public enum ParticleEffect {
|
|||
COLORABLE
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the color for effects like {@link ParticleEffect#ENTITY_EFFECT},
|
||||
* {@link ParticleEffect#AMBIENT_ENTITY_EFFECT}, {@link ParticleEffect#DUST}
|
||||
* and {@link ParticleEffect#NOTE}
|
||||
* <p>
|
||||
* This class is part of the <b>ParticleEffect Library</b> and follows the
|
||||
* same usage conditions
|
||||
*
|
||||
* @author DarkBlade12
|
||||
* @since 1.7
|
||||
*/
|
||||
public static abstract class ParticleColor {
|
||||
/**
|
||||
* Returns the value for the offsetX field
|
||||
*
|
||||
* @return The offsetX value
|
||||
*/
|
||||
public abstract float getValueX();
|
||||
|
||||
/**
|
||||
* Returns the value for the offsetY field
|
||||
*
|
||||
* @return The offsetY value
|
||||
*/
|
||||
public abstract float getValueY();
|
||||
|
||||
/**
|
||||
* Returns the value for the offsetZ field
|
||||
*
|
||||
* @return The offsetZ value
|
||||
*/
|
||||
public abstract float getValueZ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the color for effects like {@link ParticleEffect#ENTITY_EFFECT},
|
||||
* {@link ParticleEffect#AMBIENT_ENTITY_EFFECT} and {@link ParticleEffect#NOTE}
|
||||
* <p>
|
||||
* This class is part of the <b>ParticleEffect Library</b> and follows the
|
||||
* same usage conditions
|
||||
*
|
||||
* @author DarkBlade12
|
||||
* @since 1.7
|
||||
*/
|
||||
public static final class OrdinaryColor extends ParticleColor {
|
||||
public static final OrdinaryColor RAINBOW = new OrdinaryColor(999, 999, 999);
|
||||
public static final OrdinaryColor RANDOM = new OrdinaryColor(998, 998, 998);
|
||||
|
||||
private final int red;
|
||||
private final int green;
|
||||
private final int blue;
|
||||
|
||||
/**
|
||||
* Construct a new ordinary color
|
||||
*
|
||||
* @param red Red value of the RGB format
|
||||
* @param green Green value of the RGB format
|
||||
* @param blue Blue value of the RGB format
|
||||
* @throws IllegalArgumentException If one of the values is lower than 0
|
||||
* or higher than 255
|
||||
*/
|
||||
public OrdinaryColor(int red, int green, int blue) throws IllegalArgumentException {
|
||||
if ((red == 999 && green == 999 && blue == 999) || (red == 998 && green == 998 && blue == 998)) { // Allow rainbow and random values
|
||||
this.red = red;
|
||||
this.green = green;
|
||||
this.blue = blue;
|
||||
} else {
|
||||
if (red < 0) {
|
||||
throw new IllegalArgumentException("The red value is lower than 0");
|
||||
}
|
||||
if (red > 255) {
|
||||
throw new IllegalArgumentException("The red value is higher than 255");
|
||||
}
|
||||
this.red = red;
|
||||
if (green < 0) {
|
||||
throw new IllegalArgumentException("The green value is lower than 0");
|
||||
}
|
||||
if (green > 255) {
|
||||
throw new IllegalArgumentException("The green value is higher than 255");
|
||||
}
|
||||
this.green = green;
|
||||
if (blue < 0) {
|
||||
throw new IllegalArgumentException("The blue value is lower than 0");
|
||||
}
|
||||
if (blue > 255) {
|
||||
throw new IllegalArgumentException("The blue value is higher than 255");
|
||||
}
|
||||
this.blue = blue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the red value of the RGB format
|
||||
*
|
||||
* @return The red value
|
||||
*/
|
||||
public int getRed() {
|
||||
return this.red;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the green value of the RGB format
|
||||
*
|
||||
* @return The green value
|
||||
*/
|
||||
public int getGreen() {
|
||||
return this.green;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the blue value of the RGB format
|
||||
*
|
||||
* @return The blue value
|
||||
*/
|
||||
public int getBlue() {
|
||||
return this.blue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the red value divided by 255
|
||||
*
|
||||
* @return The offsetX value
|
||||
*/
|
||||
@Override
|
||||
public float getValueX() {
|
||||
if (this.equals(OrdinaryColor.RAINBOW) || this.equals(OrdinaryColor.RANDOM))
|
||||
return 0F;
|
||||
return (float) this.red / 255F;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the green value divided by 255
|
||||
*
|
||||
* @return The offsetY value
|
||||
*/
|
||||
@Override
|
||||
public float getValueY() {
|
||||
if (this.equals(OrdinaryColor.RAINBOW) || this.equals(OrdinaryColor.RANDOM))
|
||||
return 0F;
|
||||
return (float) this.green / 255F;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the blue value divided by 255
|
||||
*
|
||||
* @return The offsetZ value
|
||||
*/
|
||||
@Override
|
||||
public float getValueZ() {
|
||||
if (this.equals(OrdinaryColor.RAINBOW) || this.equals(OrdinaryColor.RANDOM))
|
||||
return 0F;
|
||||
return (float) this.blue / 255F;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof OrdinaryColor))
|
||||
return false;
|
||||
OrdinaryColor otherColor = (OrdinaryColor) other;
|
||||
return this.red == otherColor.red && this.green == otherColor.green && this.blue == otherColor.blue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.red, this.green, this.blue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the color for the {@link ParticleEffect#NOTE} effect
|
||||
* <p>
|
||||
* This class is part of the <b>ParticleEffect Library</b> and follows the
|
||||
* same usage conditions
|
||||
*
|
||||
* @author DarkBlade12
|
||||
* @since 1.7
|
||||
*/
|
||||
public static final class NoteColor extends ParticleColor {
|
||||
public static final NoteColor RAINBOW = new NoteColor(99);
|
||||
public static final NoteColor RANDOM = new NoteColor(98);
|
||||
|
||||
private final int note;
|
||||
|
||||
/**
|
||||
* Construct a new note color
|
||||
*
|
||||
* @param note Note id which determines color
|
||||
* @throws IllegalArgumentException If the note value is lower than 0 or
|
||||
* higher than 24
|
||||
*/
|
||||
public NoteColor(int note) throws IllegalArgumentException {
|
||||
if (note == 99 || note == 98) { // Allow rainbow and random values
|
||||
this.note = note;
|
||||
} else {
|
||||
if (note < 0) {
|
||||
throw new IllegalArgumentException("The note value is lower than 0");
|
||||
}
|
||||
if (note > 24) {
|
||||
throw new IllegalArgumentException("The note value is higher than 24");
|
||||
}
|
||||
this.note = note;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the note value
|
||||
*
|
||||
* @return The note value
|
||||
*/
|
||||
public int getNote() {
|
||||
return this.note;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the note value divided by 24
|
||||
*
|
||||
* @return The offsetX value
|
||||
*/
|
||||
@Override
|
||||
public float getValueX() {
|
||||
return (float) this.note / 24F;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns zero because the offsetY value is unused
|
||||
*
|
||||
* @return zero
|
||||
*/
|
||||
@Override
|
||||
public float getValueY() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns zero because the offsetZ value is unused
|
||||
*
|
||||
* @return zero
|
||||
*/
|
||||
@Override
|
||||
public float getValueZ() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof NoteColor))
|
||||
return false;
|
||||
NoteColor otherColor = (NoteColor) other;
|
||||
return this.note == otherColor.note;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(this.note);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a runtime exception that is thrown either if the displayed
|
||||
* particle effect requires data and has none or vice-versa or if the data
|
||||
* type is incorrect
|
||||
* <p>
|
||||
* This class is part of the <b>ParticleEffect Library</b> and follows the
|
||||
* same usage conditions
|
||||
*
|
||||
* @author DarkBlade12
|
||||
* @since 1.6
|
||||
*/
|
||||
private static final class ParticleDataException extends RuntimeException {
|
||||
private static final long serialVersionUID = 3203085387160737484L;
|
||||
|
||||
/**
|
||||
* Construct a new particle data exception
|
||||
*
|
||||
* @param message Message that will be logged
|
||||
*/
|
||||
public ParticleDataException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a runtime exception that is thrown either if the displayed
|
||||
* particle effect is not colorable or if the particle color type is
|
||||
* incorrect
|
||||
* <p>
|
||||
* This class is part of the <b>ParticleEffect Library</b> and follows the
|
||||
* same usage conditions
|
||||
*
|
||||
* @author DarkBlade12
|
||||
* @since 1.7
|
||||
*/
|
||||
private static final class ParticleColorException extends RuntimeException {
|
||||
private static final long serialVersionUID = 3203085387160737485L;
|
||||
|
||||
/**
|
||||
* Construct a new particle color exception
|
||||
*
|
||||
* @param message Message that will be logged
|
||||
*/
|
||||
public ParticleColorException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,10 +3,10 @@ package dev.esophose.playerparticles.particles;
|
|||
import dev.esophose.playerparticles.PlayerParticles;
|
||||
import dev.esophose.playerparticles.manager.LocaleManager;
|
||||
import dev.esophose.playerparticles.manager.ParticleManager;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect.NoteColor;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect.OrdinaryColor;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect.ParticleColor;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect.ParticleProperty;
|
||||
import dev.esophose.playerparticles.particles.data.NoteColor;
|
||||
import dev.esophose.playerparticles.particles.data.OrdinaryColor;
|
||||
import dev.esophose.playerparticles.particles.data.ParticleColor;
|
||||
import dev.esophose.playerparticles.styles.DefaultStyles;
|
||||
import dev.esophose.playerparticles.styles.ParticleStyle;
|
||||
import dev.esophose.playerparticles.util.ParticleUtils;
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
package dev.esophose.playerparticles.particles.data;
|
||||
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Represents the color for the {@link ParticleEffect#NOTE} effect
|
||||
* <p>
|
||||
* This class is part of the <b>ParticleEffect Library</b> and follows the
|
||||
* same usage conditions
|
||||
*
|
||||
* @author DarkBlade12
|
||||
* @since 1.7
|
||||
*/
|
||||
public final class NoteColor extends ParticleColor {
|
||||
public static final NoteColor RAINBOW = new NoteColor(99);
|
||||
public static final NoteColor RANDOM = new NoteColor(98);
|
||||
|
||||
private final int note;
|
||||
|
||||
/**
|
||||
* Construct a new note color
|
||||
*
|
||||
* @param note Note id which determines color
|
||||
* @throws IllegalArgumentException If the note value is lower than 0 or
|
||||
* higher than 24
|
||||
*/
|
||||
public NoteColor(int note) throws IllegalArgumentException {
|
||||
if (note == 99 || note == 98) { // Allow rainbow and random values
|
||||
this.note = note;
|
||||
} else {
|
||||
if (note < 0) {
|
||||
throw new IllegalArgumentException("The note value is lower than 0");
|
||||
}
|
||||
if (note > 24) {
|
||||
throw new IllegalArgumentException("The note value is higher than 24");
|
||||
}
|
||||
this.note = note;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the note value
|
||||
*
|
||||
* @return The note value
|
||||
*/
|
||||
public int getNote() {
|
||||
return this.note;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the note value divided by 24
|
||||
*
|
||||
* @return The offsetX value
|
||||
*/
|
||||
@Override
|
||||
public float getValueX() {
|
||||
return (float) this.note / 24F;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns zero because the offsetY value is unused
|
||||
*
|
||||
* @return zero
|
||||
*/
|
||||
@Override
|
||||
public float getValueY() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns zero because the offsetZ value is unused
|
||||
*
|
||||
* @return zero
|
||||
*/
|
||||
@Override
|
||||
public float getValueZ() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof NoteColor))
|
||||
return false;
|
||||
NoteColor otherColor = (NoteColor) other;
|
||||
return this.note == otherColor.note;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(this.note);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,138 @@
|
|||
package dev.esophose.playerparticles.particles.data;
|
||||
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Represents the color for effects like {@link ParticleEffect#ENTITY_EFFECT},
|
||||
* {@link ParticleEffect#AMBIENT_ENTITY_EFFECT} and {@link ParticleEffect#NOTE}
|
||||
* <p>
|
||||
* This class is part of the <b>ParticleEffect Library</b> and follows the
|
||||
* same usage conditions
|
||||
*
|
||||
* @author DarkBlade12
|
||||
* @since 1.7
|
||||
*/
|
||||
public final class OrdinaryColor extends ParticleColor {
|
||||
public static final OrdinaryColor RAINBOW = new OrdinaryColor(999, 999, 999);
|
||||
public static final OrdinaryColor RANDOM = new OrdinaryColor(998, 998, 998);
|
||||
|
||||
private final int red;
|
||||
private final int green;
|
||||
private final int blue;
|
||||
|
||||
/**
|
||||
* Construct a new ordinary color
|
||||
*
|
||||
* @param red Red value of the RGB format
|
||||
* @param green Green value of the RGB format
|
||||
* @param blue Blue value of the RGB format
|
||||
* @throws IllegalArgumentException If one of the values is lower than 0
|
||||
* or higher than 255
|
||||
*/
|
||||
public OrdinaryColor(int red, int green, int blue) throws IllegalArgumentException {
|
||||
if ((red == 999 && green == 999 && blue == 999) || (red == 998 && green == 998 && blue == 998)) { // Allow rainbow and random values
|
||||
this.red = red;
|
||||
this.green = green;
|
||||
this.blue = blue;
|
||||
} else {
|
||||
if (red < 0) {
|
||||
throw new IllegalArgumentException("The red value is lower than 0");
|
||||
}
|
||||
if (red > 255) {
|
||||
throw new IllegalArgumentException("The red value is higher than 255");
|
||||
}
|
||||
this.red = red;
|
||||
if (green < 0) {
|
||||
throw new IllegalArgumentException("The green value is lower than 0");
|
||||
}
|
||||
if (green > 255) {
|
||||
throw new IllegalArgumentException("The green value is higher than 255");
|
||||
}
|
||||
this.green = green;
|
||||
if (blue < 0) {
|
||||
throw new IllegalArgumentException("The blue value is lower than 0");
|
||||
}
|
||||
if (blue > 255) {
|
||||
throw new IllegalArgumentException("The blue value is higher than 255");
|
||||
}
|
||||
this.blue = blue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the red value of the RGB format
|
||||
*
|
||||
* @return The red value
|
||||
*/
|
||||
public int getRed() {
|
||||
return this.red;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the green value of the RGB format
|
||||
*
|
||||
* @return The green value
|
||||
*/
|
||||
public int getGreen() {
|
||||
return this.green;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the blue value of the RGB format
|
||||
*
|
||||
* @return The blue value
|
||||
*/
|
||||
public int getBlue() {
|
||||
return this.blue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the red value divided by 255
|
||||
*
|
||||
* @return The offsetX value
|
||||
*/
|
||||
@Override
|
||||
public float getValueX() {
|
||||
if (this.equals(OrdinaryColor.RAINBOW) || this.equals(OrdinaryColor.RANDOM))
|
||||
return 0F;
|
||||
return (float) this.red / 255F;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the green value divided by 255
|
||||
*
|
||||
* @return The offsetY value
|
||||
*/
|
||||
@Override
|
||||
public float getValueY() {
|
||||
if (this.equals(OrdinaryColor.RAINBOW) || this.equals(OrdinaryColor.RANDOM))
|
||||
return 0F;
|
||||
return (float) this.green / 255F;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the blue value divided by 255
|
||||
*
|
||||
* @return The offsetZ value
|
||||
*/
|
||||
@Override
|
||||
public float getValueZ() {
|
||||
if (this.equals(OrdinaryColor.RAINBOW) || this.equals(OrdinaryColor.RANDOM))
|
||||
return 0F;
|
||||
return (float) this.blue / 255F;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof OrdinaryColor))
|
||||
return false;
|
||||
OrdinaryColor otherColor = (OrdinaryColor) other;
|
||||
return this.red == otherColor.red && this.green == otherColor.green && this.blue == otherColor.blue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.red, this.green, this.blue);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package dev.esophose.playerparticles.particles.data;
|
||||
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect;
|
||||
|
||||
/**
|
||||
* Represents the color for effects like {@link ParticleEffect#ENTITY_EFFECT},
|
||||
* {@link ParticleEffect#AMBIENT_ENTITY_EFFECT}, {@link ParticleEffect#DUST}
|
||||
* and {@link ParticleEffect#NOTE}
|
||||
* <p>
|
||||
* This class is part of the <b>ParticleEffect Library</b> and follows the
|
||||
* same usage conditions
|
||||
*
|
||||
* @author DarkBlade12
|
||||
* @since 1.7
|
||||
*/
|
||||
public abstract class ParticleColor {
|
||||
/**
|
||||
* Returns the value for the offsetX field
|
||||
*
|
||||
* @return The offsetX value
|
||||
*/
|
||||
public abstract float getValueX();
|
||||
|
||||
/**
|
||||
* Returns the value for the offsetY field
|
||||
*
|
||||
* @return The offsetY value
|
||||
*/
|
||||
public abstract float getValueY();
|
||||
|
||||
/**
|
||||
* Returns the value for the offsetZ field
|
||||
*
|
||||
* @return The offsetZ value
|
||||
*/
|
||||
public abstract float getValueZ();
|
||||
}
|
|
@ -0,0 +1,156 @@
|
|||
package dev.esophose.playerparticles.particles.spawning;
|
||||
|
||||
import dev.esophose.playerparticles.PlayerParticles;
|
||||
import dev.esophose.playerparticles.manager.ConfigurationManager.Setting;
|
||||
import dev.esophose.playerparticles.manager.ParticleManager;
|
||||
import dev.esophose.playerparticles.particles.PPlayer;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect;
|
||||
import dev.esophose.playerparticles.particles.data.ParticleColor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.metadata.MetadataValue;
|
||||
|
||||
public abstract class ParticleSpawner {
|
||||
|
||||
/**
|
||||
* Displays a particle effect
|
||||
*
|
||||
* @param particleEffect The particle type to display
|
||||
* @param offsetX Maximum distance particles can fly away from the center on the x-axis
|
||||
* @param offsetY Maximum distance particles can fly away from the center on the y-axis
|
||||
* @param offsetZ Maximum distance particles can fly away from the center on the z-axis
|
||||
* @param speed Display speed of the particles
|
||||
* @param amount Amount of particles
|
||||
* @param center Center location of the effect
|
||||
* @param isLongRange If the particle can be viewed from long range
|
||||
* @param owner The player that owns the particles
|
||||
* @throws ParticleDataException If the particle effect requires additional data
|
||||
*/
|
||||
public abstract void display(ParticleEffect particleEffect, double offsetX, double offsetY, double offsetZ, double speed, int amount, Location center, boolean isLongRange, Player owner);
|
||||
|
||||
/**
|
||||
* Displays a single particle which is colored
|
||||
*
|
||||
* @param particleEffect The particle type to display
|
||||
* @param color Color of the particle
|
||||
* @param center Center location of the effect
|
||||
* @param isLongRange If the particle can be viewed from long range
|
||||
* @param owner The player that owns the particles
|
||||
* @throws ParticleColorException If the particle effect is not colorable or the color type is incorrect
|
||||
*/
|
||||
public abstract void display(ParticleEffect particleEffect, ParticleColor color, Location center, boolean isLongRange, Player owner);
|
||||
|
||||
/**
|
||||
* Displays a particle effect which requires additional data and is only
|
||||
* visible for all players within a certain range in the world of @param
|
||||
* center
|
||||
*
|
||||
* @param particleEffect The particle type to display
|
||||
* @param spawnMaterial Material of the effect
|
||||
* @param offsetX Maximum distance particles can fly away from the center on the x-axis
|
||||
* @param offsetY Maximum distance particles can fly away from the center on the y-axis
|
||||
* @param offsetZ Maximum distance particles can fly away from the center on the z-axis
|
||||
* @param speed Display speed of the particles
|
||||
* @param amount Amount of particles
|
||||
* @param center Center location of the effect
|
||||
* @param isLongRange If the particle can be viewed from long range
|
||||
* @param owner The player that owns the particles
|
||||
* @throws ParticleDataException If the particle effect does not require additional data or if the data type is incorrect
|
||||
*/
|
||||
public abstract void display(ParticleEffect particleEffect, Material spawnMaterial, double offsetX, double offsetY, double offsetZ, double speed, int amount, Location center, boolean isLongRange, Player owner);
|
||||
|
||||
/**
|
||||
* Gets a List of Players within the particle display range
|
||||
*
|
||||
* @param center The center of the radius to check around
|
||||
* @param isLongRange If the particle can be viewed from long range
|
||||
* @param owner The player that owns the particles
|
||||
* @return A List of Players within the particle display range
|
||||
*/
|
||||
protected List<Player> getPlayersInRange(Location center, boolean isLongRange, Player owner) {
|
||||
List<Player> players = new ArrayList<>();
|
||||
int range = !isLongRange ? Setting.PARTICLE_RENDER_RANGE_PLAYER.getInt() : Setting.PARTICLE_RENDER_RANGE_FIXED_EFFECT.getInt();
|
||||
range *= range;
|
||||
|
||||
for (PPlayer pplayer : PlayerParticles.getInstance().getManager(ParticleManager.class).getPPlayers()) {
|
||||
Player p = pplayer.getPlayer();
|
||||
if (p != owner && !this.canSee(p, owner))
|
||||
continue;
|
||||
|
||||
if (p != null && pplayer.canSeeParticles() && p.getWorld().equals(center.getWorld()) && center.distanceSquared(p.getLocation()) <= range)
|
||||
players.add(p);
|
||||
}
|
||||
|
||||
return players;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a player can see another player
|
||||
*
|
||||
* @param player The player
|
||||
* @param target The target
|
||||
* @return True if player can see target, otherwise false
|
||||
*/
|
||||
private boolean canSee(Player player, Player target) {
|
||||
if (player == null || target == null)
|
||||
return true;
|
||||
|
||||
for (MetadataValue meta : target.getMetadata("vanished"))
|
||||
if (meta.asBoolean())
|
||||
return false;
|
||||
|
||||
return player.canSee(target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a runtime exception that is thrown either if the displayed
|
||||
* particle effect requires data and has none or vice-versa or if the data
|
||||
* type is incorrect
|
||||
* <p>
|
||||
* This class is part of the <b>ParticleEffect Library</b> and follows the
|
||||
* same usage conditions
|
||||
*
|
||||
* @author DarkBlade12
|
||||
* @since 1.6
|
||||
*/
|
||||
public static final class ParticleDataException extends RuntimeException {
|
||||
private static final long serialVersionUID = 3203085387160737484L;
|
||||
|
||||
/**
|
||||
* Construct a new particle data exception
|
||||
*
|
||||
* @param message Message that will be logged
|
||||
*/
|
||||
public ParticleDataException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a runtime exception that is thrown either if the displayed
|
||||
* particle effect is not colorable or if the particle color type is
|
||||
* incorrect
|
||||
* <p>
|
||||
* This class is part of the <b>ParticleEffect Library</b> and follows the
|
||||
* same usage conditions
|
||||
*
|
||||
* @author DarkBlade12
|
||||
* @since 1.7
|
||||
*/
|
||||
public static final class ParticleColorException extends RuntimeException {
|
||||
private static final long serialVersionUID = 3203085387160737485L;
|
||||
|
||||
/**
|
||||
* Construct a new particle color exception
|
||||
*
|
||||
* @param message Message that will be logged
|
||||
*/
|
||||
public ParticleColorException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,284 @@
|
|||
package dev.esophose.playerparticles.particles.spawning;
|
||||
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect.ParticleProperty;
|
||||
import dev.esophose.playerparticles.particles.data.OrdinaryColor;
|
||||
import dev.esophose.playerparticles.particles.data.ParticleColor;
|
||||
import dev.esophose.playerparticles.particles.spawning.reflective.ReflectionUtils;
|
||||
import dev.esophose.playerparticles.particles.spawning.reflective.ReflectionUtils.PackageType;
|
||||
import dev.esophose.playerparticles.particles.spawning.reflective.ReflectiveParticleEffectMapping;
|
||||
import dev.esophose.playerparticles.util.NMSUtil;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class ReflectiveParticleSpawner extends ParticleSpawner {
|
||||
|
||||
@Override
|
||||
public void display(ParticleEffect particleEffect, double offsetX, double offsetY, double offsetZ, double speed, int amount, Location center, boolean isLongRange, Player owner) {
|
||||
if (particleEffect.hasProperty(ParticleProperty.REQUIRES_MATERIAL_DATA))
|
||||
throw new ParticleDataException("This particle effect requires additional data");
|
||||
|
||||
new ParticlePacket(particleEffect, offsetX, offsetY, offsetZ, speed, amount, true, null).sendTo(center, this.getPlayersInRange(center, isLongRange, owner));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void display(ParticleEffect particleEffect, ParticleColor color, Location center, boolean isLongRange, Player owner) {
|
||||
if (!particleEffect.hasProperty(ParticleProperty.COLORABLE))
|
||||
throw new ParticleColorException("This particle effect is not colorable");
|
||||
|
||||
new ParticlePacket(particleEffect, color, true).sendTo(center, this.getPlayersInRange(center, isLongRange, owner));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void display(ParticleEffect particleEffect, Material spawnMaterial, double offsetX, double offsetY, double offsetZ, double speed, int amount, Location center, boolean isLongRange, Player owner) {
|
||||
if (!particleEffect.hasProperty(ParticleProperty.REQUIRES_MATERIAL_DATA))
|
||||
throw new ParticleDataException("This particle effect does not require additional data");
|
||||
|
||||
new ParticlePacket(particleEffect, offsetX, offsetY, offsetZ, speed, amount, true, spawnMaterial).sendTo(center, this.getPlayersInRange(center, isLongRange, owner));
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a particle effect packet with all attributes which is used for
|
||||
* sending packets to the players
|
||||
* <p>
|
||||
* This class is part of the <b>ParticleEffect Library</b> and follows the
|
||||
* same usage conditions
|
||||
*
|
||||
* @author DarkBlade12, Esophose
|
||||
* @since 1.5
|
||||
*/
|
||||
public static final class ParticlePacket {
|
||||
private static Class<?> enumParticle;
|
||||
private static Constructor<?> packetConstructor;
|
||||
private static Method getHandle;
|
||||
private static Field playerConnection;
|
||||
private static Method sendPacket;
|
||||
static {
|
||||
try {
|
||||
if (NMSUtil.getVersionNumber() > 7) {
|
||||
enumParticle = PackageType.MINECRAFT_SERVER.getClass("EnumParticle");
|
||||
}
|
||||
Class<?> packetClass = PackageType.MINECRAFT_SERVER.getClass(NMSUtil.getVersionNumber() < 7 ? "Packet63WorldParticles" : "PacketPlayOutWorldParticles");
|
||||
packetConstructor = ReflectionUtils.getConstructor(packetClass);
|
||||
getHandle = ReflectionUtils.getMethod("CraftPlayer", PackageType.CRAFTBUKKIT_ENTITY, "getHandle");
|
||||
playerConnection = ReflectionUtils.getField("EntityPlayer", PackageType.MINECRAFT_SERVER, false, "playerConnection");
|
||||
sendPacket = ReflectionUtils.getMethod(playerConnection.getType(), "sendPacket", PackageType.MINECRAFT_SERVER.getClass("Packet"));
|
||||
} catch (ReflectiveOperationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private final ParticleEffect effect;
|
||||
private float offsetX;
|
||||
private final float offsetY;
|
||||
private final float offsetZ;
|
||||
private final float speed;
|
||||
private final int amount;
|
||||
private final boolean longDistance;
|
||||
private final Material data;
|
||||
private Object packet;
|
||||
|
||||
/**
|
||||
* Construct a new particle packet
|
||||
*
|
||||
* @param effect Particle effect
|
||||
* @param offsetX Maximum distance particles can fly away from the center on the x-axis
|
||||
* @param offsetY Maximum distance particles can fly away from the center on the y-axis
|
||||
* @param offsetZ Maximum distance particles can fly away from the center on the z-axis
|
||||
* @param speed Display speed of the particles
|
||||
* @param amount Amount of particles
|
||||
* @param longDistance Indicates whether the maximum distance is increased from 256 to 65536
|
||||
* @param data Data of the effect
|
||||
* @throws IllegalArgumentException If the speed or amount is lower than 0
|
||||
*/
|
||||
public ParticlePacket(ParticleEffect effect, double offsetX, double offsetY, double offsetZ, double speed, int amount, boolean longDistance, Material data) throws IllegalArgumentException {
|
||||
if (speed < 0)
|
||||
throw new IllegalArgumentException("The speed is lower than 0");
|
||||
|
||||
if (amount < 0)
|
||||
throw new IllegalArgumentException("The amount is lower than 0");
|
||||
|
||||
this.effect = effect;
|
||||
this.offsetX = (float) offsetX;
|
||||
this.offsetY = (float) offsetY;
|
||||
this.offsetZ = (float) offsetZ;
|
||||
this.speed = (float) speed;
|
||||
this.amount = amount;
|
||||
this.longDistance = longDistance;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new particle packet of a single colored particle
|
||||
*
|
||||
* @param effect Particle effect
|
||||
* @param color Color of the particle
|
||||
* @param longDistance Indicates whether the maximum distance is increased from 256 to 65536
|
||||
*/
|
||||
public ParticlePacket(ParticleEffect effect, ParticleColor color, boolean longDistance) {
|
||||
this(effect, color.getValueX(), color.getValueY(), color.getValueZ(), 1, 0, longDistance, null);
|
||||
|
||||
if (effect == ParticleEffect.DUST && color instanceof OrdinaryColor && ((OrdinaryColor) color).getRed() == 0)
|
||||
this.offsetX = Float.MIN_NORMAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes {@link #packet} with all set values
|
||||
*
|
||||
* @param center Center location of the effect
|
||||
* @throws PacketInstantiationException If instantion fails due to an unknown error
|
||||
*/
|
||||
private void initializePacket(Location center) throws PacketInstantiationException {
|
||||
if (this.packet != null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
this.packet = packetConstructor.newInstance();
|
||||
if (NMSUtil.getVersionNumber() < 8) {
|
||||
String name = ReflectiveParticleEffectMapping.valueOf(this.effect.name()).getName();
|
||||
if (this.data != null) {
|
||||
name += getPacketDataString(this.data);
|
||||
}
|
||||
ReflectionUtils.setValue(this.packet, true, "a", name);
|
||||
} else {
|
||||
ReflectionUtils.setValue(this.packet, true, "a", enumParticle.getEnumConstants()[ReflectiveParticleEffectMapping.valueOf(this.effect.name()).getId()]);
|
||||
ReflectionUtils.setValue(this.packet, true, "j", this.longDistance);
|
||||
if (this.data != null) {
|
||||
int[] packetData = getPacketData(this.data);
|
||||
ReflectionUtils.setValue(this.packet, true, "k", this.effect == ParticleEffect.ITEM ? packetData : new int[] { packetData[0] | (packetData[1] << 12) });
|
||||
}
|
||||
}
|
||||
ReflectionUtils.setValue(this.packet, true, "b", (float) center.getX());
|
||||
ReflectionUtils.setValue(this.packet, true, "c", (float) center.getY());
|
||||
ReflectionUtils.setValue(this.packet, true, "d", (float) center.getZ());
|
||||
ReflectionUtils.setValue(this.packet, true, "e", this.offsetX);
|
||||
ReflectionUtils.setValue(this.packet, true, "f", this.offsetY);
|
||||
ReflectionUtils.setValue(this.packet, true, "g", this.offsetZ);
|
||||
ReflectionUtils.setValue(this.packet, true, "h", this.speed);
|
||||
ReflectionUtils.setValue(this.packet, true, "i", this.amount);
|
||||
} catch (Exception exception) {
|
||||
throw new PacketInstantiationException("Packet instantiation failed", exception);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the packet to a single player and caches it
|
||||
*
|
||||
* @param center Center location of the effect
|
||||
* @param player Receiver of the packet
|
||||
* @throws PacketInstantiationException If instantion fails due to an unknown error
|
||||
* @throws PacketSendingException If sending fails due to an unknown error
|
||||
* @see #initializePacket(Location)
|
||||
*/
|
||||
public void sendTo(Location center, Player player) throws PacketInstantiationException, PacketSendingException {
|
||||
this.initializePacket(center);
|
||||
try {
|
||||
sendPacket.invoke(playerConnection.get(getHandle.invoke(player)), this.packet);
|
||||
} catch (Exception exception) {
|
||||
throw new PacketSendingException("Failed to send the packet to player '" + player.getName() + "'", exception);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the packet to all players in the list
|
||||
*
|
||||
* @param center Center location of the effect
|
||||
* @param players Receivers of the packet
|
||||
* @throws IllegalArgumentException If the player list is empty
|
||||
* @see #sendTo(Location center, Player player)
|
||||
*/
|
||||
public void sendTo(Location center, List<Player> players) throws IllegalArgumentException {
|
||||
if (players.isEmpty()) {
|
||||
throw new IllegalArgumentException("The player list is empty");
|
||||
}
|
||||
for (Player player : players) {
|
||||
this.sendTo(center, player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the packet to all players in a certain range
|
||||
*
|
||||
* @param center Center location of the effect
|
||||
* @param range Range in which players will receive the packet (Maximum range for particles is usually 16, but it can differ for some types)
|
||||
* @throws IllegalArgumentException If the range is lower than 1
|
||||
* @see #sendTo(Location center, Player player)
|
||||
*/
|
||||
public void sendTo(Location center, double range) throws IllegalArgumentException {
|
||||
if (range < 1) {
|
||||
throw new IllegalArgumentException("The range is lower than 1");
|
||||
}
|
||||
String worldName = center.getWorld().getName();
|
||||
double squared = range * range;
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
if (!player.getWorld().getName().equals(worldName) || player.getLocation().distanceSquared(center) > squared) {
|
||||
continue;
|
||||
}
|
||||
this.sendTo(center, player);
|
||||
}
|
||||
}
|
||||
|
||||
private static String getPacketDataString(Material data) {
|
||||
int[] packetData = getPacketData(data);
|
||||
return "_" + packetData[0] + "_" + packetData[1];
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private static int[] getPacketData(Material data) {
|
||||
return new int[] { data.getId(), 0 };
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a runtime exception that is thrown if packet instantiation fails
|
||||
* <p>
|
||||
* This class is part of the <b>ParticleEffect Library</b> and follows the same usage conditions
|
||||
* </p>
|
||||
*
|
||||
* @author DarkBlade12
|
||||
* @since 1.4
|
||||
*/
|
||||
private static final class PacketInstantiationException extends RuntimeException {
|
||||
private static final long serialVersionUID = 3203085387160737484L;
|
||||
|
||||
/**
|
||||
* Construct a new packet instantiation exception
|
||||
*
|
||||
* @param message Message that will be logged
|
||||
* @param cause Cause of the exception
|
||||
*/
|
||||
public PacketInstantiationException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a runtime exception that is thrown if packet sending fails
|
||||
* <p>
|
||||
* This class is part of the <b>ParticleEffect Library</b> and follows the same usage conditions
|
||||
* </p>
|
||||
*
|
||||
* @author DarkBlade12
|
||||
* @since 1.4
|
||||
*/
|
||||
private static final class PacketSendingException extends RuntimeException {
|
||||
private static final long serialVersionUID = 3203085387160737484L;
|
||||
|
||||
/**
|
||||
* Construct a new packet sending exception
|
||||
*
|
||||
* @param message Message that will be logged
|
||||
* @param cause Cause of the exception
|
||||
*/
|
||||
public PacketSendingException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
package dev.esophose.playerparticles.particles.spawning;
|
||||
|
||||
import dev.esophose.playerparticles.manager.ConfigurationManager.Setting;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect.ParticleProperty;
|
||||
import dev.esophose.playerparticles.particles.data.OrdinaryColor;
|
||||
import dev.esophose.playerparticles.particles.data.ParticleColor;
|
||||
import dev.esophose.playerparticles.util.NMSUtil;
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Particle.DustOptions;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.material.MaterialData;
|
||||
|
||||
public class SpigotParticleSpawner extends ParticleSpawner {
|
||||
|
||||
@Override
|
||||
public void display(ParticleEffect particleEffect, double offsetX, double offsetY, double offsetZ, double speed, int amount, Location center, boolean isLongRange, Player owner) {
|
||||
if (particleEffect.hasProperty(ParticleProperty.REQUIRES_MATERIAL_DATA))
|
||||
throw new ParticleDataException("This particle effect requires additional data");
|
||||
|
||||
for (Player player : this.getPlayersInRange(center, isLongRange, owner))
|
||||
player.spawnParticle(particleEffect.getSpigotEnum(), center.getX(), center.getY(), center.getZ(), amount, offsetX, offsetY, offsetZ, speed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void display(ParticleEffect particleEffect, ParticleColor color, Location center, boolean isLongRange, Player owner) {
|
||||
if (!particleEffect.hasProperty(ParticleProperty.COLORABLE))
|
||||
throw new ParticleColorException("This particle effect is not colorable");
|
||||
|
||||
if (particleEffect == ParticleEffect.DUST && NMSUtil.getVersionNumber() >= 13) { // DUST uses a special data object for spawning in 1.13+
|
||||
OrdinaryColor dustColor = (OrdinaryColor) color;
|
||||
DustOptions dustOptions = new DustOptions(Color.fromRGB(dustColor.getRed(), dustColor.getGreen(), dustColor.getBlue()), Setting.DUST_SIZE.getFloat());
|
||||
for (Player player : this.getPlayersInRange(center, isLongRange, owner))
|
||||
player.spawnParticle(particleEffect.getSpigotEnum(), center.getX(), center.getY(), center.getZ(), 1, 0, 0, 0, 0, dustOptions);
|
||||
} else {
|
||||
for (Player player : this.getPlayersInRange(center, isLongRange, owner)) {
|
||||
// Minecraft clients require that you pass a non-zero value if the Red value should be zero
|
||||
player.spawnParticle(particleEffect.getSpigotEnum(), center.getX(), center.getY(), center.getZ(), 0, particleEffect == ParticleEffect.DUST && color.getValueX() == 0 ? Float.MIN_VALUE : color.getValueX(), color.getValueY(), color.getValueZ(), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public void display(ParticleEffect particleEffect, Material spawnMaterial, double offsetX, double offsetY, double offsetZ, double speed, int amount, Location center, boolean isLongRange, Player owner) {
|
||||
if (!particleEffect.hasProperty(ParticleProperty.REQUIRES_MATERIAL_DATA))
|
||||
throw new ParticleDataException("This particle effect does not require additional data");
|
||||
|
||||
Object extraData = null;
|
||||
if (particleEffect.getSpigotEnum().getDataType().getTypeName().equals("org.bukkit.block.data.BlockData")) {
|
||||
extraData = spawnMaterial.createBlockData();
|
||||
} else if (particleEffect.getSpigotEnum().getDataType() == ItemStack.class) {
|
||||
extraData = new ItemStack(spawnMaterial);
|
||||
} else if (particleEffect.getSpigotEnum().getDataType() == MaterialData.class) {
|
||||
extraData = new MaterialData(spawnMaterial); // Deprecated, only used in versions < 1.13
|
||||
}
|
||||
|
||||
for (Player player : this.getPlayersInRange(center, isLongRange, owner))
|
||||
player.spawnParticle(particleEffect.getSpigotEnum(), center.getX(), center.getY(), center.getZ(), amount, offsetX, offsetY, offsetZ, speed, extraData);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,649 @@
|
|||
package dev.esophose.playerparticles.particles.spawning.reflective;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
/**
|
||||
* <b>ReflectionUtils</b>
|
||||
* <p>
|
||||
* This class provides useful methods which makes dealing with reflection much
|
||||
* easier, especially when working with Bukkit
|
||||
* <p>
|
||||
* You are welcome to use it, modify it and redistribute it under the following
|
||||
* conditions:
|
||||
* <ul>
|
||||
* <li>Don't claim this class as your own
|
||||
* <li>Don't remove this disclaimer
|
||||
* </ul>
|
||||
* <p>
|
||||
* <i>It would be nice if you provide credit to me if you use this class in a
|
||||
* published project</i>
|
||||
*
|
||||
* @author DarkBlade12
|
||||
* @version 1.1
|
||||
*/
|
||||
public final class ReflectionUtils {
|
||||
// Prevent accidental construction
|
||||
private ReflectionUtils() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the constructor of a given class with the given parameter types
|
||||
*
|
||||
* @param clazz Target class
|
||||
* @param parameterTypes Parameter types of the desired constructor
|
||||
* @return The constructor of the target class with the specified parameter
|
||||
* types
|
||||
* @throws NoSuchMethodException If the desired constructor with the
|
||||
* specified parameter types cannot be found
|
||||
* @see DataType
|
||||
* @see DataType#getPrimitive(Class[])
|
||||
* @see DataType#compare(Class[], Class[])
|
||||
*/
|
||||
public static Constructor<?> getConstructor(Class<?> clazz, Class<?>... parameterTypes) throws NoSuchMethodException {
|
||||
Class<?>[] primitiveTypes = DataType.getPrimitive(parameterTypes);
|
||||
for (Constructor<?> constructor : clazz.getConstructors()) {
|
||||
if (!DataType.compare(DataType.getPrimitive(constructor.getParameterTypes()), primitiveTypes)) {
|
||||
continue;
|
||||
}
|
||||
return constructor;
|
||||
}
|
||||
throw new NoSuchMethodException("There is no such constructor in this class with the specified parameter types");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the constructor of a desired class with the given parameter types
|
||||
*
|
||||
* @param className Name of the desired target class
|
||||
* @param packageType Package where the desired target class is located
|
||||
* @param parameterTypes Parameter types of the desired constructor
|
||||
* @return The constructor of the desired target class with the specified
|
||||
* parameter types
|
||||
* @throws NoSuchMethodException If the desired constructor with the
|
||||
* specified parameter types cannot be found
|
||||
* @throws ClassNotFoundException ClassNotFoundException If the desired
|
||||
* target class with the specified name and package cannot be
|
||||
* found
|
||||
*/
|
||||
public static Constructor<?> getConstructor(String className, PackageType packageType, Class<?>... parameterTypes) throws NoSuchMethodException, ClassNotFoundException {
|
||||
return getConstructor(packageType.getClass(className), parameterTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an instance of a class with the given arguments
|
||||
*
|
||||
* @param clazz Target class
|
||||
* @param arguments Arguments which are used to construct an object of the
|
||||
* target class
|
||||
* @return The instance of the target class with the specified arguments
|
||||
* @throws InstantiationException If you cannot create an instance of the
|
||||
* target class due to certain circumstances
|
||||
* @throws IllegalAccessException If the desired constructor cannot be
|
||||
* accessed due to certain circumstances
|
||||
* @throws IllegalArgumentException If the types of the arguments do not
|
||||
* match the parameter types of the constructor (this should not
|
||||
* occur since it searches for a constructor with the types of
|
||||
* the arguments)
|
||||
* @throws InvocationTargetException If the desired constructor cannot be
|
||||
* invoked
|
||||
* @throws NoSuchMethodException If the desired constructor with the
|
||||
* specified arguments cannot be found
|
||||
*/
|
||||
public static Object instantiateObject(Class<?> clazz, Object... arguments) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException {
|
||||
return getConstructor(clazz, DataType.getPrimitive(arguments)).newInstance(arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an instance of a desired class with the given arguments
|
||||
*
|
||||
* @param className Name of the desired target class
|
||||
* @param packageType Package where the desired target class is located
|
||||
* @param arguments Arguments which are used to construct an object of the
|
||||
* desired target class
|
||||
* @return The instance of the desired target class with the specified
|
||||
* arguments
|
||||
* @throws InstantiationException If you cannot create an instance of the
|
||||
* desired target class due to certain circumstances
|
||||
* @throws IllegalAccessException If the desired constructor cannot be
|
||||
* accessed due to certain circumstances
|
||||
* @throws IllegalArgumentException If the types of the arguments do not
|
||||
* match the parameter types of the constructor (this should not
|
||||
* occur since it searches for a constructor with the types of
|
||||
* the arguments)
|
||||
* @throws InvocationTargetException If the desired constructor cannot be
|
||||
* invoked
|
||||
* @throws NoSuchMethodException If the desired constructor with the
|
||||
* specified arguments cannot be found
|
||||
* @throws ClassNotFoundException If the desired target class with the
|
||||
* specified name and package cannot be found
|
||||
*/
|
||||
public static Object instantiateObject(String className, PackageType packageType, Object... arguments) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, ClassNotFoundException {
|
||||
return instantiateObject(packageType.getClass(className), arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a method of a class with the given parameter types
|
||||
*
|
||||
* @param clazz Target class
|
||||
* @param methodName Name of the desired method
|
||||
* @param parameterTypes Parameter types of the desired method
|
||||
* @return The method of the target class with the specified name and
|
||||
* parameter types
|
||||
* @throws NoSuchMethodException If the desired method of the target class
|
||||
* with the specified name and parameter types cannot be found
|
||||
* @see DataType#getPrimitive(Class[])
|
||||
* @see DataType#compare(Class[], Class[])
|
||||
*/
|
||||
public static Method getMethod(Class<?> clazz, String methodName, Class<?>... parameterTypes) throws NoSuchMethodException {
|
||||
Class<?>[] primitiveTypes = DataType.getPrimitive(parameterTypes);
|
||||
for (Method method : clazz.getMethods()) {
|
||||
if (!method.getName().equals(methodName) || !DataType.compare(DataType.getPrimitive(method.getParameterTypes()), primitiveTypes)) {
|
||||
continue;
|
||||
}
|
||||
return method;
|
||||
}
|
||||
throw new NoSuchMethodException("There is no such method in this class with the specified name and parameter types");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a method of a desired class with the given parameter types
|
||||
*
|
||||
* @param className Name of the desired target class
|
||||
* @param packageType Package where the desired target class is located
|
||||
* @param methodName Name of the desired method
|
||||
* @param parameterTypes Parameter types of the desired method
|
||||
* @return The method of the desired target class with the specified name
|
||||
* and parameter types
|
||||
* @throws NoSuchMethodException If the desired method of the desired target
|
||||
* class with the specified name and parameter types cannot be
|
||||
* found
|
||||
* @throws ClassNotFoundException If the desired target class with the
|
||||
* specified name and package cannot be found
|
||||
*/
|
||||
public static Method getMethod(String className, PackageType packageType, String methodName, Class<?>... parameterTypes) throws NoSuchMethodException, ClassNotFoundException {
|
||||
return getMethod(packageType.getClass(className), methodName, parameterTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes a method on an object with the given arguments
|
||||
*
|
||||
* @param instance Target object
|
||||
* @param methodName Name of the desired method
|
||||
* @param arguments Arguments which are used to invoke the desired method
|
||||
* @return The result of invoking the desired method on the target object
|
||||
* @throws IllegalAccessException If the desired method cannot be accessed
|
||||
* due to certain circumstances
|
||||
* @throws IllegalArgumentException If the types of the arguments do not
|
||||
* match the parameter types of the method (this should not
|
||||
* occur since it searches for a method with the types of the
|
||||
* arguments)
|
||||
* @throws InvocationTargetException If the desired method cannot be invoked
|
||||
* on the target object
|
||||
* @throws NoSuchMethodException If the desired method of the class of the
|
||||
* target object with the specified name and arguments cannot be
|
||||
* found
|
||||
*/
|
||||
public static Object invokeMethod(Object instance, String methodName, Object... arguments) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException {
|
||||
return getMethod(instance.getClass(), methodName, DataType.getPrimitive(arguments)).invoke(instance, arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes a method of the target class on an object with the given
|
||||
* arguments
|
||||
*
|
||||
* @param instance Target object
|
||||
* @param clazz Target class
|
||||
* @param methodName Name of the desired method
|
||||
* @param arguments Arguments which are used to invoke the desired method
|
||||
* @return The result of invoking the desired method on the target object
|
||||
* @throws IllegalAccessException If the desired method cannot be accessed
|
||||
* due to certain circumstances
|
||||
* @throws IllegalArgumentException If the types of the arguments do not
|
||||
* match the parameter types of the method (this should not
|
||||
* occur since it searches for a method with the types of the
|
||||
* arguments)
|
||||
* @throws InvocationTargetException If the desired method cannot be invoked
|
||||
* on the target object
|
||||
* @throws NoSuchMethodException If the desired method of the target class
|
||||
* with the specified name and arguments cannot be found
|
||||
* @see #getMethod(Class, String, Class...)
|
||||
* @see DataType#getPrimitive(Object[])
|
||||
*/
|
||||
public static Object invokeMethod(Object instance, Class<?> clazz, String methodName, Object... arguments) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException {
|
||||
return getMethod(clazz, methodName, DataType.getPrimitive(arguments)).invoke(instance, arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes a method of a desired class on an object with the given arguments
|
||||
*
|
||||
* @param instance Target object
|
||||
* @param className Name of the desired target class
|
||||
* @param packageType Package where the desired target class is located
|
||||
* @param methodName Name of the desired method
|
||||
* @param arguments Arguments which are used to invoke the desired method
|
||||
* @return The result of invoking the desired method on the target object
|
||||
* @throws IllegalAccessException If the desired method cannot be accessed
|
||||
* due to certain circumstances
|
||||
* @throws IllegalArgumentException If the types of the arguments do not
|
||||
* match the parameter types of the method (this should not
|
||||
* occur since it searches for a method with the types of the
|
||||
* arguments)
|
||||
* @throws InvocationTargetException If the desired method cannot be invoked
|
||||
* on the target object
|
||||
* @throws NoSuchMethodException If the desired method of the desired target
|
||||
* class with the specified name and arguments cannot be found
|
||||
* @throws ClassNotFoundException If the desired target class with the
|
||||
* specified name and package cannot be found
|
||||
*/
|
||||
public static Object invokeMethod(Object instance, String className, PackageType packageType, String methodName, Object... arguments) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, ClassNotFoundException {
|
||||
return invokeMethod(instance, packageType.getClass(className), methodName, arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a field of the target class with the given name
|
||||
*
|
||||
* @param clazz Target class
|
||||
* @param declared Whether the desired field is declared or not
|
||||
* @param fieldName Name of the desired field
|
||||
* @return The field of the target class with the specified name
|
||||
* @throws NoSuchFieldException If the desired field of the given class
|
||||
* cannot be found
|
||||
* @throws SecurityException If the desired field cannot be made accessible
|
||||
*/
|
||||
public static Field getField(Class<?> clazz, boolean declared, String fieldName) throws NoSuchFieldException, SecurityException {
|
||||
Field field = declared ? clazz.getDeclaredField(fieldName) : clazz.getField(fieldName);
|
||||
field.setAccessible(true);
|
||||
return field;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a field of a desired class with the given name
|
||||
*
|
||||
* @param className Name of the desired target class
|
||||
* @param packageType Package where the desired target class is located
|
||||
* @param declared Whether the desired field is declared or not
|
||||
* @param fieldName Name of the desired field
|
||||
* @return The field of the desired target class with the specified name
|
||||
* @throws NoSuchFieldException If the desired field of the desired class
|
||||
* cannot be found
|
||||
* @throws SecurityException If the desired field cannot be made accessible
|
||||
* @throws ClassNotFoundException If the desired target class with the
|
||||
* specified name and package cannot be found
|
||||
* @see #getField(Class, boolean, String)
|
||||
*/
|
||||
public static Field getField(String className, PackageType packageType, boolean declared, String fieldName) throws NoSuchFieldException, SecurityException, ClassNotFoundException {
|
||||
return getField(packageType.getClass(className), declared, fieldName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of a field of the given class of an object
|
||||
*
|
||||
* @param instance Target object
|
||||
* @param clazz Target class
|
||||
* @param declared Whether the desired field is declared or not
|
||||
* @param fieldName Name of the desired field
|
||||
* @return The value of field of the target object
|
||||
* @throws IllegalArgumentException If the target object does not feature
|
||||
* the desired field
|
||||
* @throws IllegalAccessException If the desired field cannot be accessed
|
||||
* @throws NoSuchFieldException If the desired field of the target class
|
||||
* cannot be found
|
||||
* @throws SecurityException If the desired field cannot be made accessible
|
||||
* @see #getField(Class, boolean, String)
|
||||
*/
|
||||
public static Object getValue(Object instance, Class<?> clazz, boolean declared, String fieldName) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
|
||||
return getField(clazz, declared, fieldName).get(instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of a field of a desired class of an object
|
||||
*
|
||||
* @param instance Target object
|
||||
* @param className Name of the desired target class
|
||||
* @param packageType Package where the desired target class is located
|
||||
* @param declared Whether the desired field is declared or not
|
||||
* @param fieldName Name of the desired field
|
||||
* @return The value of field of the target object
|
||||
* @throws IllegalArgumentException If the target object does not feature
|
||||
* the desired field
|
||||
* @throws IllegalAccessException If the desired field cannot be accessed
|
||||
* @throws NoSuchFieldException If the desired field of the desired class
|
||||
* cannot be found
|
||||
* @throws SecurityException If the desired field cannot be made accessible
|
||||
* @throws ClassNotFoundException If the desired target class with the
|
||||
* specified name and package cannot be found
|
||||
* @see #getValue(Object, Class, boolean, String)
|
||||
*/
|
||||
public static Object getValue(Object instance, String className, PackageType packageType, boolean declared, String fieldName) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, ClassNotFoundException {
|
||||
return getValue(instance, packageType.getClass(className), declared, fieldName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of a field with the given name of an object
|
||||
*
|
||||
* @param instance Target object
|
||||
* @param declared Whether the desired field is declared or not
|
||||
* @param fieldName Name of the desired field
|
||||
* @return The value of field of the target object
|
||||
* @throws IllegalArgumentException If the target object does not feature
|
||||
* the desired field (should not occur since it searches for a
|
||||
* field with the given name in the class of the object)
|
||||
* @throws IllegalAccessException If the desired field cannot be accessed
|
||||
* @throws NoSuchFieldException If the desired field of the target object
|
||||
* cannot be found
|
||||
* @throws SecurityException If the desired field cannot be made accessible
|
||||
* @see #getValue(Object, Class, boolean, String)
|
||||
*/
|
||||
public static Object getValue(Object instance, boolean declared, String fieldName) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
|
||||
return getValue(instance, instance.getClass(), declared, fieldName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of a field of the given class of an object
|
||||
*
|
||||
* @param instance Target object
|
||||
* @param clazz Target class
|
||||
* @param declared Whether the desired field is declared or not
|
||||
* @param fieldName Name of the desired field
|
||||
* @param value New value
|
||||
* @throws IllegalArgumentException If the type of the value does not match
|
||||
* the type of the desired field
|
||||
* @throws IllegalAccessException If the desired field cannot be accessed
|
||||
* @throws NoSuchFieldException If the desired field of the target class
|
||||
* cannot be found
|
||||
* @throws SecurityException If the desired field cannot be made accessible
|
||||
* @see #getField(Class, boolean, String)
|
||||
*/
|
||||
public static void setValue(Object instance, Class<?> clazz, boolean declared, String fieldName, Object value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
|
||||
getField(clazz, declared, fieldName).set(instance, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of a field of a desired class of an object
|
||||
*
|
||||
* @param instance Target object
|
||||
* @param className Name of the desired target class
|
||||
* @param packageType Package where the desired target class is located
|
||||
* @param declared Whether the desired field is declared or not
|
||||
* @param fieldName Name of the desired field
|
||||
* @param value New value
|
||||
* @throws IllegalArgumentException If the type of the value does not match
|
||||
* the type of the desired field
|
||||
* @throws IllegalAccessException If the desired field cannot be accessed
|
||||
* @throws NoSuchFieldException If the desired field of the desired class
|
||||
* cannot be found
|
||||
* @throws SecurityException If the desired field cannot be made accessible
|
||||
* @throws ClassNotFoundException If the desired target class with the
|
||||
* specified name and package cannot be found
|
||||
* @see #setValue(Object, Class, boolean, String, Object)
|
||||
*/
|
||||
public static void setValue(Object instance, String className, PackageType packageType, boolean declared, String fieldName, Object value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, ClassNotFoundException {
|
||||
setValue(instance, packageType.getClass(className), declared, fieldName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of a field with the given name of an object
|
||||
*
|
||||
* @param instance Target object
|
||||
* @param declared Whether the desired field is declared or not
|
||||
* @param fieldName Name of the desired field
|
||||
* @param value New value
|
||||
* @throws IllegalArgumentException If the type of the value does not match
|
||||
* the type of the desired field
|
||||
* @throws IllegalAccessException If the desired field cannot be accessed
|
||||
* @throws NoSuchFieldException If the desired field of the target object
|
||||
* cannot be found
|
||||
* @throws SecurityException If the desired field cannot be made accessible
|
||||
* @see #setValue(Object, Class, boolean, String, Object)
|
||||
*/
|
||||
public static void setValue(Object instance, boolean declared, String fieldName, Object value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
|
||||
setValue(instance, instance.getClass(), declared, fieldName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an enumeration of dynamic packages of NMS and CraftBukkit
|
||||
* <p>
|
||||
* This class is part of the <b>ReflectionUtils</b> and follows the same
|
||||
* usage conditions
|
||||
*
|
||||
* @author DarkBlade12
|
||||
* @since 1.0
|
||||
*/
|
||||
public enum PackageType {
|
||||
MINECRAFT_SERVER("net.minecraft.server." + getServerVersion()), CRAFTBUKKIT("org.bukkit.craftbukkit." + getServerVersion()), CRAFTBUKKIT_BLOCK(CRAFTBUKKIT, "block"), CRAFTBUKKIT_CHUNKIO(CRAFTBUKKIT, "chunkio"), CRAFTBUKKIT_COMMAND(CRAFTBUKKIT, "command"), CRAFTBUKKIT_CONVERSATIONS(CRAFTBUKKIT, "conversations"), CRAFTBUKKIT_ENCHANTMENS(CRAFTBUKKIT, "enchantments"), CRAFTBUKKIT_ENTITY(CRAFTBUKKIT, "entity"), CRAFTBUKKIT_EVENT(CRAFTBUKKIT, "event"), CRAFTBUKKIT_GENERATOR(CRAFTBUKKIT, "generator"), CRAFTBUKKIT_HELP(CRAFTBUKKIT, "help"), CRAFTBUKKIT_INVENTORY(CRAFTBUKKIT, "inventory"), CRAFTBUKKIT_MAP(CRAFTBUKKIT, "map"), CRAFTBUKKIT_METADATA(CRAFTBUKKIT, "metadata"), CRAFTBUKKIT_POTION(CRAFTBUKKIT, "potion"), CRAFTBUKKIT_PROJECTILES(CRAFTBUKKIT, "projectiles"), CRAFTBUKKIT_SCHEDULER(CRAFTBUKKIT, "scheduler"), CRAFTBUKKIT_SCOREBOARD(CRAFTBUKKIT, "scoreboard"), CRAFTBUKKIT_UPDATER(CRAFTBUKKIT, "updater"), CRAFTBUKKIT_UTIL(CRAFTBUKKIT, "util");
|
||||
|
||||
private final String path;
|
||||
|
||||
/**
|
||||
* Construct a new package type
|
||||
*
|
||||
* @param path Path of the package
|
||||
*/
|
||||
private PackageType(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new package type
|
||||
*
|
||||
* @param parent Parent package of the package
|
||||
* @param path Path of the package
|
||||
*/
|
||||
private PackageType(PackageType parent, String path) {
|
||||
this(parent + "." + path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path of this package type
|
||||
*
|
||||
* @return The path
|
||||
*/
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the class with the given name
|
||||
*
|
||||
* @param className Name of the desired class
|
||||
* @return The class with the specified name
|
||||
* @throws ClassNotFoundException If the desired class with the
|
||||
* specified name and package cannot be found
|
||||
*/
|
||||
public Class<?> getClass(String className) throws ClassNotFoundException {
|
||||
return Class.forName(this + "." + className);
|
||||
}
|
||||
|
||||
// Override for convenience
|
||||
@Override
|
||||
public String toString() {
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the version of your server
|
||||
*
|
||||
* @return The server version
|
||||
*/
|
||||
public static String getServerVersion() {
|
||||
return Bukkit.getServer().getClass().getPackage().getName().substring(23);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an enumeration of Java data types with corresponding classes
|
||||
* <p>
|
||||
* This class is part of the <b>ReflectionUtils</b> and follows the same
|
||||
* usage conditions
|
||||
*
|
||||
* @author DarkBlade12
|
||||
* @since 1.0
|
||||
*/
|
||||
public enum DataType {
|
||||
BYTE(byte.class, Byte.class), SHORT(short.class, Short.class), INTEGER(int.class, Integer.class), LONG(long.class, Long.class), CHARACTER(char.class, Character.class), FLOAT(float.class, Float.class), DOUBLE(double.class, Double.class), BOOLEAN(boolean.class, Boolean.class);
|
||||
|
||||
private static final Map<Class<?>, DataType> CLASS_MAP = new HashMap<Class<?>, DataType>();
|
||||
private final Class<?> primitive;
|
||||
private final Class<?> reference;
|
||||
|
||||
// Initialize map for quick class lookup
|
||||
static {
|
||||
for (DataType type : values()) {
|
||||
CLASS_MAP.put(type.primitive, type);
|
||||
CLASS_MAP.put(type.reference, type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new data type
|
||||
*
|
||||
* @param primitive Primitive class of this data type
|
||||
* @param reference Reference class of this data type
|
||||
*/
|
||||
private DataType(Class<?> primitive, Class<?> reference) {
|
||||
this.primitive = primitive;
|
||||
this.reference = reference;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the primitive class of this data type
|
||||
*
|
||||
* @return The primitive class
|
||||
*/
|
||||
public Class<?> getPrimitive() {
|
||||
return primitive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the reference class of this data type
|
||||
*
|
||||
* @return The reference class
|
||||
*/
|
||||
public Class<?> getReference() {
|
||||
return reference;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data type with the given primitive/reference class
|
||||
*
|
||||
* @param clazz Primitive/Reference class of the data type
|
||||
* @return The data type
|
||||
*/
|
||||
public static DataType fromClass(Class<?> clazz) {
|
||||
return CLASS_MAP.get(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the primitive class of the data type with the given reference
|
||||
* class
|
||||
*
|
||||
* @param clazz Reference class of the data type
|
||||
* @return The primitive class
|
||||
*/
|
||||
public static Class<?> getPrimitive(Class<?> clazz) {
|
||||
DataType type = fromClass(clazz);
|
||||
return type == null ? clazz : type.getPrimitive();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the reference class of the data type with the given primitive
|
||||
* class
|
||||
*
|
||||
* @param clazz Primitive class of the data type
|
||||
* @return The reference class
|
||||
*/
|
||||
public static Class<?> getReference(Class<?> clazz) {
|
||||
DataType type = fromClass(clazz);
|
||||
return type == null ? clazz : type.getReference();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the primitive class array of the given class array
|
||||
*
|
||||
* @param classes Given class array
|
||||
* @return The primitive class array
|
||||
*/
|
||||
public static Class<?>[] getPrimitive(Class<?>[] classes) {
|
||||
int length = classes == null ? 0 : classes.length;
|
||||
Class<?>[] types = new Class<?>[length];
|
||||
for (int index = 0; index < length; index++) {
|
||||
types[index] = getPrimitive(classes[index]);
|
||||
}
|
||||
return types;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the reference class array of the given class array
|
||||
*
|
||||
* @param classes Given class array
|
||||
* @return The reference class array
|
||||
*/
|
||||
public static Class<?>[] getReference(Class<?>[] classes) {
|
||||
int length = classes == null ? 0 : classes.length;
|
||||
Class<?>[] types = new Class<?>[length];
|
||||
for (int index = 0; index < length; index++) {
|
||||
types[index] = getReference(classes[index]);
|
||||
}
|
||||
return types;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the primitive class array of the given object array
|
||||
*
|
||||
* @param objects Given object array
|
||||
* @return The primitive class array
|
||||
*/
|
||||
public static Class<?>[] getPrimitive(Object[] objects) {
|
||||
int length = objects == null ? 0 : objects.length;
|
||||
Class<?>[] types = new Class<?>[length];
|
||||
for (int index = 0; index < length; index++) {
|
||||
types[index] = getPrimitive(objects[index].getClass());
|
||||
}
|
||||
return types;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the reference class array of the given object array
|
||||
*
|
||||
* @param objects Given object array
|
||||
* @return The reference class array
|
||||
*/
|
||||
public static Class<?>[] getReference(Object[] objects) {
|
||||
int length = objects == null ? 0 : objects.length;
|
||||
Class<?>[] types = new Class<?>[length];
|
||||
for (int index = 0; index < length; index++) {
|
||||
types[index] = getReference(objects[index].getClass());
|
||||
}
|
||||
return types;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two class arrays on equivalence
|
||||
*
|
||||
* @param primary Primary class array
|
||||
* @param secondary Class array which is compared to the primary array
|
||||
* @return Whether these arrays are equal or not
|
||||
*/
|
||||
public static boolean compare(Class<?>[] primary, Class<?>[] secondary) {
|
||||
if (primary == null || secondary == null || primary.length != secondary.length) {
|
||||
return false;
|
||||
}
|
||||
for (int index = 0; index < primary.length; index++) {
|
||||
Class<?> primaryClass = primary[index];
|
||||
Class<?> secondaryClass = secondary[index];
|
||||
if (primaryClass.equals(secondaryClass) || primaryClass.isAssignableFrom(secondaryClass)) {
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
package dev.esophose.playerparticles.particles.spawning.reflective;
|
||||
|
||||
import dev.esophose.playerparticles.util.NMSUtil;
|
||||
|
||||
public enum ReflectiveParticleEffectMapping {
|
||||
|
||||
POOF("explode", 0),
|
||||
EXPLOSION("largeexplode", 1),
|
||||
EXPLOSION_EMITTER("hugeexplosion", 2),
|
||||
FIREWORK("fireworksSpark", 3),
|
||||
BUBBLE("bubble", 4),
|
||||
SPLASH("splash", 5),
|
||||
FISHING("wake", 6),
|
||||
//SUSPENDED("suspended", 7),
|
||||
MYCELIUM("depthSuspend", 8),
|
||||
CRIT("crit", 9),
|
||||
ENCHANTED_HIT("magicCrit", 10),
|
||||
SMOKE("smoke", 11),
|
||||
LARGE_SMOKE("largesmoke", 12),
|
||||
SPELL("spell", 13),
|
||||
INSTANT_EFFECT("instantSpell", 14),
|
||||
ENTITY_EFFECT("mobSpell", 15),
|
||||
AMBIENT_ENTITY_EFFECT("mobSpellAmbient", 16),
|
||||
WITCH("witchMagic", 17),
|
||||
DRIPPING_WATER("dripWater", 18),
|
||||
DRIPPING_LAVA("dripLava", 19),
|
||||
ANGRY_VILLAGER("angryVillager", 20),
|
||||
HAPPY_VILLAGER("happyVillager", 21),
|
||||
NOTE("note", 23),
|
||||
PORTAL("portal", 24),
|
||||
ENCHANT("enchantmenttable", 25),
|
||||
FLAME("flame", 26),
|
||||
LAVA("lava", 27),
|
||||
FOOTSTEP("footstep", 28),
|
||||
CLOUD("cloud", 29),
|
||||
DUST("reddust", 30),
|
||||
ITEM_SNOWBALL("snowballpoof", 31),
|
||||
//SNOW_SHOVEL("snowshovel", 32),
|
||||
ITEM_SLIME("slime", 33),
|
||||
HEART("heart", 34),
|
||||
BARRIER("barrier", 35, 8),
|
||||
ITEM("iconcrack", 36),
|
||||
BLOCK("blockcrack", 37),
|
||||
//BLOCK_DUST("blockdust", 38),
|
||||
RAIN("droplet", 39, 8),
|
||||
//ITEM_TAKE("take", 40, 8),
|
||||
ELDER_GUARDIAN("mobappearance", 41, 8);
|
||||
|
||||
private final String name;
|
||||
private final int id;
|
||||
private final boolean supported;
|
||||
|
||||
ReflectiveParticleEffectMapping(String name, int id, int requiredVersion) {
|
||||
this.name = name;
|
||||
this.id = id;
|
||||
this.supported = NMSUtil.getVersionNumber() >= requiredVersion;
|
||||
}
|
||||
|
||||
ReflectiveParticleEffectMapping(String name, int id) {
|
||||
this(name, id, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the name of the internal minecraft particle effect
|
||||
*/
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the id of the internal minecraft particle effect
|
||||
*/
|
||||
public int getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if this particle effect is supported, otherwise false
|
||||
*/
|
||||
public boolean isSupported() {
|
||||
return this.supported;
|
||||
}
|
||||
|
||||
}
|
|
@ -4,6 +4,7 @@ import dev.esophose.playerparticles.PlayerParticles;
|
|||
import dev.esophose.playerparticles.manager.ParticleStyleManager;
|
||||
import dev.esophose.playerparticles.particles.PParticle;
|
||||
import dev.esophose.playerparticles.particles.ParticlePair;
|
||||
import dev.esophose.playerparticles.util.ParticleUtils;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import org.bukkit.Location;
|
||||
|
@ -48,7 +49,7 @@ public interface ParticleStyle {
|
|||
* @return The Material icon that represents this style in the GUI
|
||||
*/
|
||||
default Material getGuiIconMaterial() {
|
||||
return Material.BARRIER;
|
||||
return ParticleUtils.FALLBACK_MATERIAL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -10,6 +10,7 @@ import dev.esophose.playerparticles.particles.PPlayer;
|
|||
import dev.esophose.playerparticles.particles.ParticleEffect;
|
||||
import dev.esophose.playerparticles.particles.ParticlePair;
|
||||
import dev.esophose.playerparticles.util.MathL;
|
||||
import dev.esophose.playerparticles.util.NMSUtil;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
@ -60,7 +61,7 @@ public class ParticleStyleCelebration extends DefaultParticleStyle {
|
|||
Random random = new Random();
|
||||
for (PPlayer pplayer : particleManager.getPPlayers()) {
|
||||
Player player = pplayer.getPlayer();
|
||||
if (player != null && player.getGameMode() != GameMode.SPECTATOR && permissionManager.isWorldEnabled(player.getWorld().getName()))
|
||||
if (player != null && (NMSUtil.getVersionNumber() < 8 || player.getGameMode() != GameMode.SPECTATOR) && permissionManager.isWorldEnabled(player.getWorld().getName()))
|
||||
for (ParticlePair particle : pplayer.getActiveParticles())
|
||||
if (particle.getStyle() == this)
|
||||
this.spawnFirework(player.getLocation(), pplayer, pplayer.getPlayer(), particle, random);
|
||||
|
|
|
@ -54,7 +54,7 @@ public class ParticleStylePopper extends DefaultParticleStyle {
|
|||
|
||||
@Override
|
||||
protected List<String> getGuiIconMaterialNames() {
|
||||
return Arrays.asList("POPPED_CHORUS_FRUIT", "CHORUS_FRUIT_POPPED");
|
||||
return Arrays.asList("POPPED_CHORUS_FRUIT", "CHORUS_FRUIT_POPPED", "PUMPKIN_SEEDS");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -7,6 +7,7 @@ import dev.esophose.playerparticles.manager.ParticleManager;
|
|||
import dev.esophose.playerparticles.particles.PParticle;
|
||||
import dev.esophose.playerparticles.particles.PPlayer;
|
||||
import dev.esophose.playerparticles.particles.ParticlePair;
|
||||
import dev.esophose.playerparticles.util.NMSUtil;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
@ -76,9 +77,17 @@ public class ParticleStyleSwords extends DefaultParticleStyle implements Listene
|
|||
Player player = (Player) event.getDamager();
|
||||
LivingEntity entity = (LivingEntity) event.getEntity();
|
||||
PPlayer pplayer = PlayerParticles.getInstance().getManager(DataManager.class).getPPlayer(player.getUniqueId());
|
||||
if (pplayer == null || !this.isSword(player.getInventory().getItemInMainHand()))
|
||||
if (pplayer == null)
|
||||
return;
|
||||
|
||||
if (NMSUtil.getVersionNumber() > 8) {
|
||||
if (!this.isSword(player.getInventory().getItemInMainHand()))
|
||||
return;
|
||||
} else {
|
||||
if (!this.isSword(player.getInventory().getItemInHand()))
|
||||
return;
|
||||
}
|
||||
|
||||
for (ParticlePair particle : pplayer.getActiveParticlesForStyle(DefaultStyles.SWORDS)) {
|
||||
Location loc = entity.getLocation().clone().add(0, 1, 0);
|
||||
particleManager.displayParticles(player, player.getWorld(), particle, DefaultStyles.SWORDS.getParticles(particle, loc), false);
|
||||
|
|
|
@ -6,6 +6,7 @@ import dev.esophose.playerparticles.particles.ParticlePair;
|
|||
import dev.esophose.playerparticles.util.MathL;
|
||||
import dev.esophose.playerparticles.util.VectorUtils;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import org.bukkit.Location;
|
||||
|
@ -44,7 +45,7 @@ public class ParticleStyleWings extends DefaultParticleStyle {
|
|||
|
||||
@Override
|
||||
protected List<String> getGuiIconMaterialNames() {
|
||||
return Collections.singletonList("ELYTRA");
|
||||
return Arrays.asList("ELYTRA", "RAW_CHICKEN");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
package dev.esophose.playerparticles.util;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
|
@ -27,6 +24,8 @@ import org.bukkit.entity.Player;
|
|||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.RegisteredServiceProvider;
|
||||
import org.bukkit.plugin.ServicePriority;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
/**
|
||||
* bStats collects some data for plugin authors.
|
||||
|
@ -34,7 +33,7 @@ import org.bukkit.plugin.ServicePriority;
|
|||
* Check out https://bStats.org/ to learn more about bStats!
|
||||
*/
|
||||
@SuppressWarnings({"WeakerAccess", "unused"})
|
||||
public class Metrics {
|
||||
public class LegacyMetrics {
|
||||
|
||||
static {
|
||||
// You can use the property to disable the check in your test environment
|
||||
|
@ -44,7 +43,7 @@ public class Metrics {
|
|||
new byte[]{'o', 'r', 'g', '.', 'b', 's', 't', 'a', 't', 's', '.', 'b', 'u', 'k', 'k', 'i', 't'});
|
||||
final String examplePackage = new String(new byte[]{'y', 'o', 'u', 'r', '.', 'p', 'a', 'c', 'k', 'a', 'g', 'e'});
|
||||
// We want to make sure nobody just copy & pastes the example and use the wrong package names
|
||||
if (Metrics.class.getPackage().getName().equals(defaultPackage) || Metrics.class.getPackage().getName().equals(examplePackage)) {
|
||||
if (LegacyMetrics.class.getPackage().getName().equals(defaultPackage) || LegacyMetrics.class.getPackage().getName().equals(examplePackage)) {
|
||||
throw new IllegalStateException("bStats Metrics class has not been relocated correctly!");
|
||||
}
|
||||
}
|
||||
|
@ -79,7 +78,7 @@ public class Metrics {
|
|||
*
|
||||
* @param plugin The plugin which stats should be submitted.
|
||||
*/
|
||||
public Metrics(Plugin plugin) {
|
||||
public LegacyMetrics(Plugin plugin) {
|
||||
if (plugin == null) {
|
||||
throw new IllegalArgumentException("Plugin cannot be null!");
|
||||
}
|
||||
|
@ -119,10 +118,8 @@ public class Metrics {
|
|||
// Load the data
|
||||
serverUUID = config.getString("serverUuid");
|
||||
logFailedRequests = config.getBoolean("logFailedRequests", false);
|
||||
this.enabled = config.getBoolean("enabled", true);
|
||||
logSentData = config.getBoolean("logSentData", false);
|
||||
logResponseStatusText = config.getBoolean("logResponseStatusText", false);
|
||||
if (this.enabled) {
|
||||
enabled = config.getBoolean("enabled", true);
|
||||
if (enabled) {
|
||||
boolean found = false;
|
||||
// Search for all other bStats Metrics classes to see if we are the first one
|
||||
for (Class<?> service : Bukkit.getServicesManager().getKnownServices()) {
|
||||
|
@ -133,10 +130,10 @@ public class Metrics {
|
|||
} catch (NoSuchFieldException ignored) { }
|
||||
}
|
||||
// Register our service
|
||||
Bukkit.getServicesManager().register(Metrics.class, this, plugin, ServicePriority.Normal);
|
||||
Bukkit.getServicesManager().register(LegacyMetrics.class, this, plugin, ServicePriority.Normal);
|
||||
if (!found) {
|
||||
// We are the first!
|
||||
this.startSubmitting();
|
||||
startSubmitting();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -147,7 +144,7 @@ public class Metrics {
|
|||
* @return Whether bStats is enabled or not.
|
||||
*/
|
||||
public boolean isEnabled() {
|
||||
return this.enabled;
|
||||
return enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -158,13 +155,13 @@ public class Metrics {
|
|||
timer.scheduleAtFixedRate(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!Metrics.this.plugin.isEnabled()) { // Plugin was disabled
|
||||
if (!plugin.isEnabled()) { // Plugin was disabled
|
||||
timer.cancel();
|
||||
return;
|
||||
}
|
||||
// Nevertheless we want our code to run in the Bukkit main thread, so we have to use the Bukkit scheduler
|
||||
// Don't be afraid! The connection to the bStats server is still async, only the stats collection is sync ;)
|
||||
Bukkit.getScheduler().runTask(Metrics.this.plugin, Metrics.this::submitData);
|
||||
Bukkit.getScheduler().runTask(plugin, () -> submitData());
|
||||
}
|
||||
}, 1000 * 60 * 5, 1000 * 60 * 30);
|
||||
// Submit the data every 30 minutes, first time after 5 minutes to give other plugins enough time to start
|
||||
|
@ -178,15 +175,16 @@ public class Metrics {
|
|||
*
|
||||
* @return The plugin specific data.
|
||||
*/
|
||||
public JsonObject getPluginData() {
|
||||
JsonObject data = new JsonObject();
|
||||
public JSONObject getPluginData() {
|
||||
JSONObject data = new JSONObject();
|
||||
|
||||
String pluginName = this.plugin.getDescription().getName();
|
||||
String pluginVersion = this.plugin.getDescription().getVersion();
|
||||
String pluginName = plugin.getDescription().getName();
|
||||
String pluginVersion = plugin.getDescription().getVersion();
|
||||
|
||||
data.addProperty("pluginName", pluginName); // Append the name of the plugin
|
||||
data.addProperty("pluginVersion", pluginVersion); // Append the version of the plugin
|
||||
data.add("customCharts", new JsonArray());
|
||||
data.put("pluginName", pluginName); // Append the name of the plugin
|
||||
data.put("pluginVersion", pluginVersion); // Append the version of the plugin
|
||||
JSONArray customCharts = new JSONArray();
|
||||
data.put("customCharts", customCharts);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
@ -196,7 +194,7 @@ public class Metrics {
|
|||
*
|
||||
* @return The server specific data.
|
||||
*/
|
||||
private JsonObject getServerData() {
|
||||
private JSONObject getServerData() {
|
||||
// Minecraft specific data
|
||||
int playerAmount;
|
||||
try {
|
||||
|
@ -211,7 +209,6 @@ public class Metrics {
|
|||
}
|
||||
int onlineMode = Bukkit.getOnlineMode() ? 1 : 0;
|
||||
String bukkitVersion = Bukkit.getVersion();
|
||||
String bukkitName = Bukkit.getName();
|
||||
|
||||
// OS/Java specific data
|
||||
String javaVersion = System.getProperty("java.version");
|
||||
|
@ -220,20 +217,19 @@ public class Metrics {
|
|||
String osVersion = System.getProperty("os.version");
|
||||
int coreCount = Runtime.getRuntime().availableProcessors();
|
||||
|
||||
JsonObject data = new JsonObject();
|
||||
JSONObject data = new JSONObject();
|
||||
|
||||
data.addProperty("serverUUID", serverUUID);
|
||||
data.put("serverUUID", serverUUID);
|
||||
|
||||
data.addProperty("playerAmount", playerAmount);
|
||||
data.addProperty("onlineMode", onlineMode);
|
||||
data.addProperty("bukkitVersion", bukkitVersion);
|
||||
data.addProperty("bukkitName", bukkitName);
|
||||
data.put("playerAmount", playerAmount);
|
||||
data.put("onlineMode", onlineMode);
|
||||
data.put("bukkitVersion", bukkitVersion);
|
||||
|
||||
data.addProperty("javaVersion", javaVersion);
|
||||
data.addProperty("osName", osName);
|
||||
data.addProperty("osArch", osArch);
|
||||
data.addProperty("osVersion", osVersion);
|
||||
data.addProperty("coreCount", coreCount);
|
||||
data.put("javaVersion", javaVersion);
|
||||
data.put("osName", osName);
|
||||
data.put("osArch", osArch);
|
||||
data.put("osVersion", osVersion);
|
||||
data.put("coreCount", coreCount);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
@ -242,9 +238,9 @@ public class Metrics {
|
|||
* Collects the data and sends it afterwards.
|
||||
*/
|
||||
private void submitData() {
|
||||
final JsonObject data = this.getServerData();
|
||||
final JSONObject data = getServerData();
|
||||
|
||||
JsonArray pluginData = new JsonArray();
|
||||
JSONArray pluginData = new JSONArray();
|
||||
// Search for all other bStats Metrics classes to get their plugin data
|
||||
for (Class<?> service : Bukkit.getServicesManager().getKnownServices()) {
|
||||
try {
|
||||
|
@ -252,43 +248,27 @@ public class Metrics {
|
|||
|
||||
for (RegisteredServiceProvider<?> provider : Bukkit.getServicesManager().getRegistrations(service)) {
|
||||
try {
|
||||
Object plugin = provider.getService().getMethod("getPluginData").invoke(provider.getProvider());
|
||||
if (plugin instanceof JsonObject) {
|
||||
pluginData.add((JsonObject) plugin);
|
||||
} else { // old bstats version compatibility
|
||||
try {
|
||||
Class<?> jsonObjectJsonSimple = Class.forName("org.json.simple.JSONObject");
|
||||
if (plugin.getClass().isAssignableFrom(jsonObjectJsonSimple)) {
|
||||
Method jsonStringGetter = jsonObjectJsonSimple.getDeclaredMethod("toJSONString");
|
||||
jsonStringGetter.setAccessible(true);
|
||||
String jsonString = (String) jsonStringGetter.invoke(plugin);
|
||||
JsonObject object = new JsonParser().parse(jsonString).getAsJsonObject();
|
||||
pluginData.add(object);
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
// minecraft version 1.14+
|
||||
if (logFailedRequests) {
|
||||
this.plugin.getLogger().log(Level.SEVERE, "Encountered unexpected exception ", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
pluginData.add(provider.getService().getMethod("getPluginData").invoke(provider.getProvider()));
|
||||
} catch (NullPointerException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) {
|
||||
}
|
||||
}
|
||||
} catch (NoSuchFieldException ignored) { }
|
||||
}
|
||||
|
||||
data.add("plugins", pluginData);
|
||||
data.put("plugins", pluginData);
|
||||
|
||||
// Create a new thread for the connection to the bStats server
|
||||
new Thread(() -> {
|
||||
try {
|
||||
// Send the data
|
||||
sendData(this.plugin, data);
|
||||
} catch (Exception e) {
|
||||
// Something went wrong! :(
|
||||
if (logFailedRequests) {
|
||||
this.plugin.getLogger().log(Level.WARNING, "Could not submit plugin stats of " + this.plugin.getName(), e);
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
// Send the data
|
||||
sendData(plugin, data);
|
||||
} catch (Exception e) {
|
||||
// Something went wrong! :(
|
||||
if (logFailedRequests) {
|
||||
plugin.getLogger().log(Level.WARNING, "Could not submit plugin stats of " + plugin.getName(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
|
@ -301,7 +281,7 @@ public class Metrics {
|
|||
* @param data The data to send.
|
||||
* @throws Exception If the request failed.
|
||||
*/
|
||||
private static void sendData(Plugin plugin, JsonObject data) throws Exception {
|
||||
private static void sendData(Plugin plugin, JSONObject data) throws Exception {
|
||||
if (data == null) {
|
||||
throw new IllegalArgumentException("Data cannot be null!");
|
||||
}
|
|
@ -33,4 +33,16 @@ public final class NMSUtil {
|
|||
return cachedVersionNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the server is running Spigot or a fork, false otherwise
|
||||
*/
|
||||
public static boolean isSpigot() {
|
||||
try {
|
||||
Class.forName("org.spigotmc.SpigotConfig");
|
||||
return true;
|
||||
} catch (ClassNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,15 +1,25 @@
|
|||
package dev.esophose.playerparticles.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import org.apache.commons.lang.WordUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public final class ParticleUtils {
|
||||
|
||||
public final static Material FALLBACK_MATERIAL;
|
||||
private static List<String> blockMaterials, itemMaterials;
|
||||
|
||||
static {
|
||||
if (NMSUtil.getVersionNumber() > 7) {
|
||||
FALLBACK_MATERIAL = Material.BARRIER;
|
||||
} else {
|
||||
FALLBACK_MATERIAL = Material.BEDROCK;
|
||||
}
|
||||
|
||||
blockMaterials = new ArrayList<>();
|
||||
itemMaterials = new ArrayList<>();
|
||||
|
||||
|
@ -43,19 +53,19 @@ public final class ParticleUtils {
|
|||
* Finds a block/item as a material from a list of possible strings
|
||||
* Contains a fallback to the barrier icon just in case
|
||||
*
|
||||
* @param barrierFallback If the material should fall back to barrier
|
||||
* @param fallback If the material should fall back to barrier
|
||||
* @param input A list of material names
|
||||
* @return The first matching material
|
||||
*/
|
||||
public static Material closestMatchWithFallback(boolean barrierFallback, String... input) {
|
||||
public static Material closestMatchWithFallback(boolean fallback, String... input) {
|
||||
for (String name : input) {
|
||||
Material mat = closestMatch(name);
|
||||
if (mat != null)
|
||||
return mat;
|
||||
}
|
||||
|
||||
if (barrierFallback)
|
||||
return Material.BARRIER;
|
||||
if (fallback)
|
||||
return FALLBACK_MATERIAL;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -2,8 +2,8 @@ package dev.esophose.playerparticles.util.inputparser;
|
|||
|
||||
import dev.esophose.playerparticles.particles.PPlayer;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect.NoteColor;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect.OrdinaryColor;
|
||||
import dev.esophose.playerparticles.particles.data.NoteColor;
|
||||
import dev.esophose.playerparticles.particles.data.OrdinaryColor;
|
||||
import dev.esophose.playerparticles.styles.ParticleStyle;
|
||||
import dev.esophose.playerparticles.util.inputparser.parsable.ParsableInteger;
|
||||
import dev.esophose.playerparticles.util.inputparser.parsable.ParsableLocation;
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
package dev.esophose.playerparticles.util.inputparser.parsable;
|
||||
|
||||
import dev.esophose.playerparticles.particles.PPlayer;
|
||||
import dev.esophose.playerparticles.util.NMSUtil;
|
||||
import dev.esophose.playerparticles.util.inputparser.Parsable;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import org.bukkit.Bukkit;
|
||||
|
@ -9,10 +13,22 @@ import org.bukkit.Location;
|
|||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class ParsableLocation extends Parsable<Location> {
|
||||
|
||||
private static Method LivingEntity_getTargetBlock;
|
||||
static {
|
||||
if (NMSUtil.getVersionNumber() < 8) {
|
||||
try {
|
||||
LivingEntity_getTargetBlock = LivingEntity.class.getDeclaredMethod("getTargetBlock", HashSet.class, int.class);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ParsableLocation() {
|
||||
super(Location.class);
|
||||
}
|
||||
|
@ -23,7 +39,18 @@ public class ParsableLocation extends Parsable<Location> {
|
|||
|
||||
Player player = pplayer.getPlayer();
|
||||
if (player != null && input.equalsIgnoreCase("looking")) {
|
||||
Block targetBlock = player.getTargetBlock((Set<Material>) null, 8); // Need the Set<Material> cast for 1.9 support
|
||||
Block targetBlock;
|
||||
if (NMSUtil.getVersionNumber() > 7) {
|
||||
targetBlock = player.getTargetBlock((Set<Material>) null, 8); // Need the Set<Material> cast for 1.9 support
|
||||
} else {
|
||||
try {
|
||||
targetBlock = (Block) LivingEntity_getTargetBlock.invoke(player, null, 8);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
targetBlock = player.getLocation().getBlock();
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
int maxDistanceSqrd = 6 * 6;
|
||||
if (targetBlock.getLocation().distanceSquared(player.getLocation()) > maxDistanceSqrd)
|
||||
return null; // Looking at a block too far away
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package dev.esophose.playerparticles.util.inputparser.parsable;
|
||||
|
||||
import dev.esophose.playerparticles.particles.PPlayer;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect.NoteColor;
|
||||
import dev.esophose.playerparticles.particles.data.NoteColor;
|
||||
import dev.esophose.playerparticles.util.inputparser.Parsable;
|
||||
import java.util.List;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package dev.esophose.playerparticles.util.inputparser.parsable;
|
||||
|
||||
import dev.esophose.playerparticles.particles.PPlayer;
|
||||
import dev.esophose.playerparticles.particles.ParticleEffect.OrdinaryColor;
|
||||
import dev.esophose.playerparticles.particles.data.OrdinaryColor;
|
||||
import dev.esophose.playerparticles.util.inputparser.Parsable;
|
||||
import java.awt.Color;
|
||||
import java.util.Collections;
|
||||
|
|
|
@ -51,7 +51,7 @@ raincloud:
|
|||
style: 'overhead'
|
||||
data: ''
|
||||
2:
|
||||
effect: 'rain'
|
||||
effect: 'dripping_water'
|
||||
style: 'overhead'
|
||||
data: ''
|
||||
rainbows:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue