mirror of
https://github.com/TotalFreedomMC/PlayerParticles.git
synced 2025-07-22 21:43:42 +00:00
Group GUI sections finished, sort command list outputs, GUI configuration added
This commit is contained in:
parent
f7eb08e48d
commit
98a570a236
20 changed files with 619 additions and 232 deletions
|
@ -116,6 +116,8 @@ public class PlayerParticles extends JavaPlugin {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reloads the settings of the plugin
|
* Reloads the settings of the plugin
|
||||||
|
*
|
||||||
|
* @param updatePluginSettings True if the settings should be updated to the latest version of the plugin
|
||||||
*/
|
*/
|
||||||
public void reload(boolean updatePluginSettings) {
|
public void reload(boolean updatePluginSettings) {
|
||||||
this.reloadConfig();
|
this.reloadConfig();
|
||||||
|
|
|
@ -82,18 +82,5 @@ public interface CommandModule {
|
||||||
LangManager.sendCustomMessage(pplayer, new MessageFormat(ChatColor.YELLOW + "/pp {0} {1} - {2}").format(args));
|
LangManager.sendCustomMessage(pplayer, new MessageFormat(ChatColor.YELLOW + "/pp {0} {1} - {2}").format(args));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays a command's sub-command usage to the player
|
|
||||||
*
|
|
||||||
* @param pplayer The PPlayer to display the command usage to
|
|
||||||
* @param command The command to display usage for
|
|
||||||
* @param subCommandName The name of the command's sub-command to display usage for
|
|
||||||
* @param subCommandArgs The sub-command's arguments
|
|
||||||
*/
|
|
||||||
public static void printSubcommandUsage(PPlayer pplayer, CommandModule command, String subCommandName, String subCommandArgs) {
|
|
||||||
Object[] args = new Object[] { command.getName(), subCommandName, subCommandArgs };
|
|
||||||
LangManager.sendCustomMessage(pplayer, new MessageFormat(ChatColor.YELLOW + "/pp {0} {1} {2}").format(args));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package com.esophose.playerparticles.command;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
@ -215,8 +216,11 @@ public class GroupCommandModule implements CommandModule {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<ParticlePair> particles = group.getParticles();
|
||||||
|
particles.sort(Comparator.comparingInt(ParticlePair::getId));
|
||||||
|
|
||||||
LangManager.sendMessage(pplayer, Lang.GROUP_INFO_HEADER, groupName);
|
LangManager.sendMessage(pplayer, Lang.GROUP_INFO_HEADER, groupName);
|
||||||
for (ParticlePair particle : group.getParticles())
|
for (ParticlePair particle : particles)
|
||||||
LangManager.sendMessage(pplayer, Lang.LIST_OUTPUT, particle.getId(), particle.getEffect().getName(), particle.getStyle().getName(), particle.getDataString());
|
LangManager.sendMessage(pplayer, Lang.LIST_OUTPUT, particle.getId(), particle.getEffect().getName(), particle.getStyle().getName(), particle.getDataString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,6 +231,7 @@ public class GroupCommandModule implements CommandModule {
|
||||||
*/
|
*/
|
||||||
private void onList(PPlayer pplayer) {
|
private void onList(PPlayer pplayer) {
|
||||||
List<ParticleGroup> groups = pplayer.getParticleGroups();
|
List<ParticleGroup> groups = pplayer.getParticleGroups();
|
||||||
|
groups.sort(Comparator.comparing(ParticleGroup::getName));
|
||||||
|
|
||||||
String groupsList = "";
|
String groupsList = "";
|
||||||
for (ParticleGroup group : groups)
|
for (ParticleGroup group : groups)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package com.esophose.playerparticles.command;
|
package com.esophose.playerparticles.command;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.esophose.playerparticles.manager.LangManager;
|
import com.esophose.playerparticles.manager.LangManager;
|
||||||
|
@ -12,6 +13,7 @@ public class ListCommandModule implements CommandModule {
|
||||||
|
|
||||||
public void onCommandExecute(PPlayer pplayer, String[] args) {
|
public void onCommandExecute(PPlayer pplayer, String[] args) {
|
||||||
List<ParticlePair> particles = pplayer.getActiveParticles();
|
List<ParticlePair> particles = pplayer.getActiveParticles();
|
||||||
|
particles.sort(Comparator.comparingInt(ParticlePair::getId));
|
||||||
|
|
||||||
if (particles.isEmpty()) {
|
if (particles.isEmpty()) {
|
||||||
LangManager.sendMessage(pplayer, Lang.LIST_NONE);
|
LangManager.sendMessage(pplayer, Lang.LIST_NONE);
|
||||||
|
|
|
@ -90,7 +90,11 @@ public class ParticleCommandHandler implements CommandExecutor, TabCompleter {
|
||||||
* @return true
|
* @return true
|
||||||
*/
|
*/
|
||||||
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
|
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
|
||||||
if (!(sender instanceof Player)) return true;
|
if (!(sender instanceof Player)) {
|
||||||
|
sender.sendMessage("Error: PlayerParticles only supports players executing commands.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
Player p = (Player) sender;
|
Player p = (Player) sender;
|
||||||
|
|
||||||
DataManager.getPPlayer(p.getUniqueId(), (pplayer) -> {
|
DataManager.getPPlayer(p.getUniqueId(), (pplayer) -> {
|
||||||
|
|
|
@ -13,8 +13,8 @@ import com.esophose.playerparticles.particles.PPlayer;
|
||||||
public class VersionCommandModule implements CommandModule {
|
public class VersionCommandModule implements CommandModule {
|
||||||
|
|
||||||
public void onCommandExecute(PPlayer pplayer, String[] args) {
|
public void onCommandExecute(PPlayer pplayer, String[] args) {
|
||||||
LangManager.sendCustomMessage(pplayer, ChatColor.GOLD + "Running PlayerParticles v" + PlayerParticles.getPlugin().getDescription().getVersion());
|
LangManager.sendCustomMessage(pplayer, ChatColor.YELLOW + "Running PlayerParticles " + ChatColor.AQUA + "v" + PlayerParticles.getPlugin().getDescription().getVersion());
|
||||||
LangManager.sendCustomMessage(pplayer, ChatColor.GOLD + "Plugin created by: Esophose");
|
LangManager.sendCustomMessage(pplayer, ChatColor.YELLOW + "Plugin created by: " + ChatColor.AQUA + "Esophose");
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> onTabComplete(PPlayer pplayer, String[] args) {
|
public List<String> onTabComplete(PPlayer pplayer, String[] args) {
|
||||||
|
|
|
@ -3,7 +3,6 @@ package com.esophose.playerparticles.gui;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.enchantments.Enchantment;
|
|
||||||
import org.bukkit.inventory.ItemFlag;
|
import org.bukkit.inventory.ItemFlag;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.inventory.meta.ItemMeta;
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
|
@ -14,24 +13,22 @@ public class GuiActionButton {
|
||||||
private Material[] icons;
|
private Material[] icons;
|
||||||
private String[] names;
|
private String[] names;
|
||||||
private String[] lore;
|
private String[] lore;
|
||||||
private boolean glowing;
|
|
||||||
private GuiActionButtonClickCallback onClick;
|
private GuiActionButtonClickCallback onClick;
|
||||||
private int iconIndex;
|
private int iconIndex;
|
||||||
|
|
||||||
public GuiActionButton(int slot, Material[] icons, String[] names, String[] lore, boolean glowing, GuiActionButtonClickCallback onClick) {
|
public GuiActionButton(int slot, Material[] icons, String[] names, String[] lore, GuiActionButtonClickCallback onClick) {
|
||||||
this.slot = slot;
|
this.slot = slot;
|
||||||
this.icons = icons;
|
this.icons = icons;
|
||||||
this.names = names;
|
this.names = names;
|
||||||
this.lore = lore;
|
this.lore = lore;
|
||||||
this.glowing = glowing;
|
|
||||||
this.onClick = onClick;
|
this.onClick = onClick;
|
||||||
|
|
||||||
if (icons.length != names.length)
|
if (icons.length != names.length)
|
||||||
throw new IllegalArgumentException("icons and names must have the same length!");
|
throw new IllegalArgumentException("icons and names must have the same length!");
|
||||||
}
|
}
|
||||||
|
|
||||||
public GuiActionButton(int slot, Material icon, String name, String[] lore, boolean glowing, GuiActionButtonClickCallback onClick) {
|
public GuiActionButton(int slot, Material icon, String name, String[] lore, GuiActionButtonClickCallback onClick) {
|
||||||
this(slot, new Material[] { icon }, new String[] { name }, lore, glowing, onClick);
|
this(slot, new Material[] { icon }, new String[] { name }, lore, onClick);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -54,10 +51,7 @@ public class GuiActionButton {
|
||||||
|
|
||||||
itemMeta.setDisplayName(this.names[this.iconIndex]);
|
itemMeta.setDisplayName(this.names[this.iconIndex]);
|
||||||
itemMeta.setLore(Arrays.asList(this.lore));
|
itemMeta.setLore(Arrays.asList(this.lore));
|
||||||
itemMeta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES, ItemFlag.HIDE_POTION_EFFECTS, ItemFlag.HIDE_ENCHANTS);
|
itemMeta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES, ItemFlag.HIDE_POTION_EFFECTS);
|
||||||
|
|
||||||
if (this.glowing)
|
|
||||||
itemMeta.addEnchant(Enchantment.ARROW_INFINITE, 1, false);
|
|
||||||
|
|
||||||
itemStack.setItemMeta(itemMeta);
|
itemStack.setItemMeta(itemMeta);
|
||||||
|
|
||||||
|
@ -69,9 +63,9 @@ public class GuiActionButton {
|
||||||
*
|
*
|
||||||
* @param isShiftClick If the player was holding shift when they clicked
|
* @param isShiftClick If the player was holding shift when they clicked
|
||||||
*/
|
*/
|
||||||
public void handleClick(boolean isShiftClick) {
|
public void handleClick(GuiActionButton button, boolean isShiftClick) {
|
||||||
if (this.onClick != null)
|
if (this.onClick != null)
|
||||||
this.onClick.execute(isShiftClick);
|
this.onClick.execute(this, isShiftClick);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -93,8 +87,9 @@ public class GuiActionButton {
|
||||||
/**
|
/**
|
||||||
* Allows button click callbacks as parameters
|
* Allows button click callbacks as parameters
|
||||||
*/
|
*/
|
||||||
|
@FunctionalInterface
|
||||||
public static interface GuiActionButtonClickCallback {
|
public static interface GuiActionButtonClickCallback {
|
||||||
public void execute(boolean isShiftClick);
|
public void execute(GuiActionButton button, boolean isShiftClick);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||||
import org.bukkit.scheduler.BukkitRunnable;
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
import org.bukkit.scheduler.BukkitTask;
|
||||||
|
|
||||||
import com.esophose.playerparticles.PlayerParticles;
|
import com.esophose.playerparticles.PlayerParticles;
|
||||||
import com.esophose.playerparticles.manager.DataManager;
|
import com.esophose.playerparticles.manager.DataManager;
|
||||||
|
@ -22,12 +23,15 @@ import com.esophose.playerparticles.particles.PPlayer;
|
||||||
public class GuiHandler extends BukkitRunnable implements Listener {
|
public class GuiHandler extends BukkitRunnable implements Listener {
|
||||||
|
|
||||||
private static List<GuiInventory> guiInventories = new ArrayList<GuiInventory>();
|
private static List<GuiInventory> guiInventories = new ArrayList<GuiInventory>();
|
||||||
|
private static BukkitTask guiTask = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes all the static values for this class
|
* Initializes all the static values for this class
|
||||||
*/
|
*/
|
||||||
public static void setup() {
|
public static void setup() {
|
||||||
new GuiHandler().runTaskTimer(PlayerParticles.getPlugin(), 0, 10);
|
if (guiTask != null)
|
||||||
|
guiTask.cancel();
|
||||||
|
guiTask = new GuiHandler().runTaskTimer(PlayerParticles.getPlugin(), 0, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -115,12 +119,13 @@ public class GuiHandler extends BukkitRunnable implements Listener {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Changes the player's inventory to another one
|
* Changes the player's inventory to another one
|
||||||
|
*
|
||||||
|
* @param nextInventory The GuiInventory to transition to
|
||||||
*/
|
*/
|
||||||
protected static void transition(GuiInventory nextInventory) {
|
protected static void transition(GuiInventory nextInventory) {
|
||||||
removeGuiInventory(nextInventory.getPPlayer());
|
removeGuiInventory(nextInventory.getPPlayer());
|
||||||
guiInventories.add(nextInventory);
|
guiInventories.add(nextInventory);
|
||||||
nextInventory.getPPlayer().getPlayer().openInventory(nextInventory.getInventory());
|
nextInventory.getPPlayer().getPlayer().openInventory(nextInventory.getInventory());
|
||||||
System.out.println("Transitioned inventories");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -127,6 +127,8 @@ public abstract class GuiInventory {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles clicks of GuiActionButtons
|
* Handles clicks of GuiActionButtons
|
||||||
|
*
|
||||||
|
* @param event The InventoryClickEvent triggered when the player clicks a GuiActionButton
|
||||||
*/
|
*/
|
||||||
public void onClick(InventoryClickEvent event) {
|
public void onClick(InventoryClickEvent event) {
|
||||||
int slot = event.getSlot();
|
int slot = event.getSlot();
|
||||||
|
@ -134,7 +136,7 @@ public abstract class GuiInventory {
|
||||||
|
|
||||||
for (GuiActionButton button : this.actionButtons) {
|
for (GuiActionButton button : this.actionButtons) {
|
||||||
if (button.getSlot() == slot) {
|
if (button.getSlot() == slot) {
|
||||||
button.handleClick(isShiftClick);
|
button.handleClick(button, isShiftClick);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,12 +3,14 @@ package com.esophose.playerparticles.gui;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.ChatColor;
|
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.SkullType;
|
import org.bukkit.SkullType;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.inventory.meta.SkullMeta;
|
import org.bukkit.inventory.meta.SkullMeta;
|
||||||
|
|
||||||
|
import com.esophose.playerparticles.manager.LangManager;
|
||||||
|
import com.esophose.playerparticles.manager.LangManager.Lang;
|
||||||
|
import com.esophose.playerparticles.manager.SettingManager.GUIIcon;
|
||||||
import com.esophose.playerparticles.particles.PPlayer;
|
import com.esophose.playerparticles.particles.PPlayer;
|
||||||
import com.esophose.playerparticles.util.ParticleUtils;
|
import com.esophose.playerparticles.util.ParticleUtils;
|
||||||
|
|
||||||
|
@ -16,7 +18,7 @@ import com.esophose.playerparticles.util.ParticleUtils;
|
||||||
public class GuiInventoryDefault extends GuiInventory {
|
public class GuiInventoryDefault extends GuiInventory {
|
||||||
|
|
||||||
public GuiInventoryDefault(PPlayer pplayer) {
|
public GuiInventoryDefault(PPlayer pplayer) {
|
||||||
super(pplayer, Bukkit.createInventory(pplayer.getPlayer(), INVENTORY_SIZE, "PlayerParticles"));
|
super(pplayer, Bukkit.createInventory(pplayer.getPlayer(), INVENTORY_SIZE, LangManager.getText(Lang.GUI_PLAYERPARTICLES)));
|
||||||
|
|
||||||
this.fillBorder(BorderColor.WHITE);
|
this.fillBorder(BorderColor.WHITE);
|
||||||
|
|
||||||
|
@ -28,13 +30,13 @@ public class GuiInventoryDefault extends GuiInventory {
|
||||||
} else {
|
} else {
|
||||||
headIcon = new ItemStack(ParticleUtils.closestMatch("SKULL_ITEM"), 1, (short) SkullType.PLAYER.ordinal());
|
headIcon = new ItemStack(ParticleUtils.closestMatch("SKULL_ITEM"), 1, (short) SkullType.PLAYER.ordinal());
|
||||||
}
|
}
|
||||||
|
|
||||||
SkullMeta currentIconMeta = (SkullMeta) headIcon.getItemMeta();
|
SkullMeta currentIconMeta = (SkullMeta) headIcon.getItemMeta();
|
||||||
currentIconMeta.setDisplayName(ChatColor.GREEN + pplayer.getPlayer().getName());
|
currentIconMeta.setDisplayName(LangManager.getText(Lang.GUI_COLOR_ICON_NAME) + pplayer.getPlayer().getName());
|
||||||
String[] currentIconLore = new String[] {
|
String[] currentIconLore = new String[] {
|
||||||
ChatColor.YELLOW + "Active Particles: " + ChatColor.AQUA + pplayer.getActiveParticles().size(),
|
LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_ACTIVE_PARTICLES, pplayer.getActiveParticles().size()),
|
||||||
ChatColor.YELLOW + "Saved Groups: " + ChatColor.AQUA + pplayer.getParticleGroups().size(),
|
LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_SAVED_GROUPS, pplayer.getParticleGroups().size()),
|
||||||
ChatColor.YELLOW + "Fixed Effects: " + ChatColor.AQUA + pplayer.getFixedEffectIds().size()
|
LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_FIXED_EFFECTS, pplayer.getFixedEffectIds().size())
|
||||||
};
|
};
|
||||||
currentIconMeta.setLore(Arrays.asList(currentIconLore));
|
currentIconMeta.setLore(Arrays.asList(currentIconLore));
|
||||||
currentIconMeta.setOwner(pplayer.getPlayer().getName());
|
currentIconMeta.setOwner(pplayer.getPlayer().getName());
|
||||||
|
@ -43,20 +45,32 @@ public class GuiInventoryDefault extends GuiInventory {
|
||||||
this.inventory.setItem(13, headIcon);
|
this.inventory.setItem(13, headIcon);
|
||||||
|
|
||||||
// Manage Your Particles button
|
// Manage Your Particles button
|
||||||
GuiActionButton manageYourParticlesButton = new GuiActionButton(38, Material.BLAZE_POWDER, ChatColor.GREEN + "Manage Your Particles", new String[] { ChatColor.YELLOW + "Create, edit, and delete your particles" }, false, (isShiftClick) -> {
|
GuiActionButton manageYourParticlesButton = new GuiActionButton(38,
|
||||||
|
GUIIcon.PARTICLES.get(),
|
||||||
|
LangManager.getText(Lang.GUI_COLOR_ICON_NAME) + LangManager.getText(Lang.GUI_MANAGE_YOUR_PARTICLES),
|
||||||
|
new String[] { LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_MANAGE_YOUR_PARTICLES_DESCRIPTION) },
|
||||||
|
(button, isShiftClick) -> {
|
||||||
GuiHandler.transition(new GuiInventoryManageParticles(pplayer));
|
GuiHandler.transition(new GuiInventoryManageParticles(pplayer));
|
||||||
});
|
});
|
||||||
this.actionButtons.add(manageYourParticlesButton);
|
this.actionButtons.add(manageYourParticlesButton);
|
||||||
|
|
||||||
// Manage Your Groups button
|
// Manage Your Groups button
|
||||||
GuiActionButton manageYourGroupsButton = new GuiActionButton(40, Material.CHEST, ChatColor.GREEN + "Manage Your Groups", new String[] { ChatColor.YELLOW + "Create, delete, and load particle groups" }, false, (isShiftClick) -> {
|
GuiActionButton manageYourGroupsButton = new GuiActionButton(40,
|
||||||
// transition to GuiInventoryManageGroups
|
GUIIcon.GROUPS.get(),
|
||||||
|
LangManager.getText(Lang.GUI_COLOR_ICON_NAME) + LangManager.getText(Lang.GUI_MANAGE_YOUR_GROUPS),
|
||||||
|
new String[] { LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_MANAGE_YOUR_GROUPS_DESCRIPTION) },
|
||||||
|
(button, isShiftClick) -> {
|
||||||
|
GuiHandler.transition(new GuiInventoryManageGroups(pplayer));
|
||||||
});
|
});
|
||||||
this.actionButtons.add(manageYourGroupsButton);
|
this.actionButtons.add(manageYourGroupsButton);
|
||||||
|
|
||||||
// Load Preset Groups
|
// Load Preset Groups
|
||||||
GuiActionButton loadPresetGroups = new GuiActionButton(42, Material.ENDER_CHEST, ChatColor.GREEN + "Load Preset Groups", new String[] { ChatColor.YELLOW + "Load pre-existing particle groups" }, false, (isShiftClick) -> {
|
GuiActionButton loadPresetGroups = new GuiActionButton(42,
|
||||||
// transition to GuiInventoryPresetGroups
|
GUIIcon.PRESET_GROUPS.get(),
|
||||||
|
LangManager.getText(Lang.GUI_COLOR_ICON_NAME) + LangManager.getText(Lang.GUI_LOAD_A_PRESET_GROUP),
|
||||||
|
new String[] { LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_LOAD_A_PRESET_GROUP_DESCRIPTION) },
|
||||||
|
(button, isShiftClick) -> {
|
||||||
|
GuiHandler.transition(new GuiInventoryLoadPresetGroups(pplayer));
|
||||||
});
|
});
|
||||||
this.actionButtons.add(loadPresetGroups);
|
this.actionButtons.add(loadPresetGroups);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
package com.esophose.playerparticles.gui;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
|
||||||
|
import com.esophose.playerparticles.manager.DataManager;
|
||||||
|
import com.esophose.playerparticles.manager.LangManager;
|
||||||
|
import com.esophose.playerparticles.manager.LangManager.Lang;
|
||||||
|
import com.esophose.playerparticles.manager.SettingManager.GUIIcon;
|
||||||
|
import com.esophose.playerparticles.particles.PPlayer;
|
||||||
|
import com.esophose.playerparticles.particles.ParticleGroup;
|
||||||
|
import com.esophose.playerparticles.particles.ParticlePair;
|
||||||
|
|
||||||
|
public class GuiInventoryLoadPresetGroups extends GuiInventory {
|
||||||
|
|
||||||
|
public GuiInventoryLoadPresetGroups(PPlayer pplayer) {
|
||||||
|
super(pplayer, Bukkit.createInventory(pplayer.getPlayer(), INVENTORY_SIZE, LangManager.getText(Lang.GUI_LOAD_A_PRESET_GROUP)));
|
||||||
|
|
||||||
|
this.fillBorder(BorderColor.GREEN);
|
||||||
|
|
||||||
|
int index = 10;
|
||||||
|
int nextWrap = 17;
|
||||||
|
int maxIndex = 43;
|
||||||
|
List<Entry<ParticleGroup, Material>> groups = ParticleGroup.getPresetGroupsForGUIForPlayer(pplayer.getPlayer());
|
||||||
|
for (Entry<ParticleGroup, Material> groupEntry : groups) {
|
||||||
|
ParticleGroup group = groupEntry.getKey();
|
||||||
|
Material iconMaterial = groupEntry.getValue();
|
||||||
|
List<ParticlePair> particles = group.getParticles();
|
||||||
|
particles.sort(Comparator.comparingInt(ParticlePair::getId));
|
||||||
|
|
||||||
|
String[] lore = new String[particles.size() + 1];
|
||||||
|
lore[0] = LangManager.getText(Lang.GUI_COLOR_SUBTEXT) + LangManager.getText(Lang.GUI_CLICK_TO_LOAD, particles.size());
|
||||||
|
int i = 1;
|
||||||
|
for (ParticlePair particle : particles) {
|
||||||
|
lore[i] = LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_PARTICLE_INFO, particle.getId(), particle.getEffect().getName(), particle.getStyle().getName(), particle.getDataString());
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load Group Buttons
|
||||||
|
GuiActionButton groupButton = new GuiActionButton(index, iconMaterial, LangManager.getText(Lang.GUI_COLOR_ICON_NAME) + group.getName(), lore, (button, isShiftClick) -> {
|
||||||
|
ParticleGroup activeGroup = pplayer.getActiveParticleGroup();
|
||||||
|
activeGroup.getParticles().clear();
|
||||||
|
for (ParticlePair particle : particles)
|
||||||
|
activeGroup.getParticles().add(particle.clone());
|
||||||
|
DataManager.saveParticleGroup(pplayer.getUniqueId(), activeGroup);
|
||||||
|
|
||||||
|
pplayer.getPlayer().closeInventory();
|
||||||
|
});
|
||||||
|
this.actionButtons.add(groupButton);
|
||||||
|
|
||||||
|
index++;
|
||||||
|
if (index == nextWrap) { // Loop around border
|
||||||
|
nextWrap += 9;
|
||||||
|
index += 2;
|
||||||
|
}
|
||||||
|
if (index > maxIndex) break; // Overflowed the available space
|
||||||
|
}
|
||||||
|
|
||||||
|
// Back Button
|
||||||
|
GuiActionButton backButton = new GuiActionButton(INVENTORY_SIZE - 1, GUIIcon.BACK.get(), LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_BACK_BUTTON), new String[] {}, (button, isShiftClick) -> {
|
||||||
|
GuiHandler.transition(new GuiInventoryDefault(pplayer));
|
||||||
|
});
|
||||||
|
this.actionButtons.add(backButton);
|
||||||
|
|
||||||
|
this.populate();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
package com.esophose.playerparticles.gui;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
|
||||||
|
import com.esophose.playerparticles.manager.DataManager;
|
||||||
|
import com.esophose.playerparticles.manager.LangManager;
|
||||||
|
import com.esophose.playerparticles.manager.LangManager.Lang;
|
||||||
|
import com.esophose.playerparticles.manager.SettingManager.GUIIcon;
|
||||||
|
import com.esophose.playerparticles.particles.PPlayer;
|
||||||
|
import com.esophose.playerparticles.particles.ParticleGroup;
|
||||||
|
import com.esophose.playerparticles.particles.ParticlePair;
|
||||||
|
|
||||||
|
public class GuiInventoryManageGroups extends GuiInventory {
|
||||||
|
|
||||||
|
public GuiInventoryManageGroups(PPlayer pplayer) {
|
||||||
|
super(pplayer, Bukkit.createInventory(pplayer.getPlayer(), INVENTORY_SIZE, LangManager.getText(Lang.GUI_MANAGE_YOUR_GROUPS)));
|
||||||
|
|
||||||
|
this.fillBorder(BorderColor.BROWN);
|
||||||
|
|
||||||
|
int index = 10;
|
||||||
|
int nextWrap = 17;
|
||||||
|
int maxIndex = 35;
|
||||||
|
List<ParticleGroup> groups = pplayer.getParticleGroups();
|
||||||
|
groups.sort(Comparator.comparing(ParticleGroup::getName));
|
||||||
|
|
||||||
|
for (ParticleGroup group : groups) {
|
||||||
|
if (group.getName().equals(ParticleGroup.DEFAULT_NAME)) continue;
|
||||||
|
|
||||||
|
List<ParticlePair> particles = group.getParticles();
|
||||||
|
particles.sort(Comparator.comparingInt(ParticlePair::getId));
|
||||||
|
|
||||||
|
String[] lore = new String[particles.size() + 2];
|
||||||
|
lore[0] = LangManager.getText(Lang.GUI_COLOR_SUBTEXT) + LangManager.getText(Lang.GUI_CLICK_TO_LOAD, particles.size());
|
||||||
|
int i = 1;
|
||||||
|
for (ParticlePair particle : particles) {
|
||||||
|
lore[i] = LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_PARTICLE_INFO, particle.getId(), particle.getEffect().getName(), particle.getStyle().getName(), particle.getDataString());
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
lore[i] = LangManager.getText(Lang.GUI_COLOR_UNAVAILABLE) + LangManager.getText(Lang.GUI_SHIFT_CLICK_TO_DELETE);
|
||||||
|
|
||||||
|
// Load Group Buttons
|
||||||
|
GuiActionButton groupButton = new GuiActionButton(index, GUIIcon.GROUPS.get(), LangManager.getText(Lang.GUI_COLOR_ICON_NAME) + group.getName(), lore, (button, isShiftClick) -> {
|
||||||
|
if (isShiftClick) {
|
||||||
|
DataManager.removeParticleGroup(pplayer.getUniqueId(), group);
|
||||||
|
|
||||||
|
this.actionButtons.remove(button);
|
||||||
|
this.inventory.setItem(button.getSlot(), null);
|
||||||
|
} else {
|
||||||
|
ParticleGroup activeGroup = pplayer.getActiveParticleGroup();
|
||||||
|
activeGroup.getParticles().clear();
|
||||||
|
for (ParticlePair particle : particles)
|
||||||
|
activeGroup.getParticles().add(particle.clone());
|
||||||
|
DataManager.saveParticleGroup(pplayer.getUniqueId(), activeGroup);
|
||||||
|
|
||||||
|
pplayer.getPlayer().closeInventory();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.actionButtons.add(groupButton);
|
||||||
|
|
||||||
|
index++;
|
||||||
|
if (index == nextWrap) { // Loop around border
|
||||||
|
nextWrap += 9;
|
||||||
|
index += 2;
|
||||||
|
}
|
||||||
|
if (index > maxIndex) break; // Overflowed the available space
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save Group Button
|
||||||
|
GuiActionButton saveGroupButton = new GuiActionButton(40,
|
||||||
|
GUIIcon.CREATE.get(),
|
||||||
|
LangManager.getText(Lang.GUI_COLOR_ICON_NAME) + LangManager.getText(Lang.GUI_SAVE_GROUP),
|
||||||
|
new String[] {
|
||||||
|
LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_SAVE_GROUP_DESCRIPTION),
|
||||||
|
LangManager.getText(Lang.GUI_COLOR_SUBTEXT) + LangManager.getText(Lang.GUI_SAVE_GROUP_DESCRIPTION_2),
|
||||||
|
},
|
||||||
|
(button, isShiftClick) -> {}); // Does nothing on click
|
||||||
|
this.actionButtons.add(saveGroupButton);
|
||||||
|
|
||||||
|
// Back Button
|
||||||
|
GuiActionButton backButton = new GuiActionButton(INVENTORY_SIZE - 1, GUIIcon.BACK.get(), LangManager.getText(Lang.GUI_COLOR_INFO) + LangManager.getText(Lang.GUI_BACK_BUTTON), new String[] {}, (button, isShiftClick) -> {
|
||||||
|
GuiHandler.transition(new GuiInventoryDefault(pplayer));
|
||||||
|
});
|
||||||
|
this.actionButtons.add(backButton);
|
||||||
|
|
||||||
|
this.populate();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -3,19 +3,21 @@ package com.esophose.playerparticles.gui;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
|
|
||||||
|
import com.esophose.playerparticles.manager.LangManager;
|
||||||
|
import com.esophose.playerparticles.manager.LangManager.Lang;
|
||||||
import com.esophose.playerparticles.particles.PPlayer;
|
import com.esophose.playerparticles.particles.PPlayer;
|
||||||
|
|
||||||
public class GuiInventoryManageParticles extends GuiInventory {
|
public class GuiInventoryManageParticles extends GuiInventory {
|
||||||
|
|
||||||
public GuiInventoryManageParticles(PPlayer pplayer) {
|
public GuiInventoryManageParticles(PPlayer pplayer) {
|
||||||
super(pplayer, Bukkit.createInventory(pplayer.getPlayer(), INVENTORY_SIZE));
|
super(pplayer, Bukkit.createInventory(pplayer.getPlayer(), INVENTORY_SIZE, LangManager.getText(Lang.GUI_MANAGE_YOUR_PARTICLES)));
|
||||||
|
|
||||||
this.fillBorder(BorderColor.ORANGE);
|
this.fillBorder(BorderColor.ORANGE);
|
||||||
|
|
||||||
GuiActionButton button = new GuiActionButton(0, new Material[] { Material.BLAZE_POWDER, Material.BLAZE_ROD }, new String[] { "Test 2!", "Look at that!" } , new String[] { "To be continued..." }, true, (isShiftClick) -> {
|
GuiActionButton testButton = new GuiActionButton(0, new Material[] { Material.BLAZE_POWDER, Material.BLAZE_ROD }, new String[] { "Test 2!", "Look at that!" } , new String[] { "To be continued..." }, (button, isShiftClick) -> {
|
||||||
GuiHandler.transition(new GuiInventoryDefault(pplayer));
|
GuiHandler.transition(new GuiInventoryDefault(pplayer));
|
||||||
});
|
});
|
||||||
this.actionButtons.add(button);
|
this.actionButtons.add(testButton);
|
||||||
|
|
||||||
this.populate();
|
this.populate();
|
||||||
}
|
}
|
||||||
|
|
|
@ -420,6 +420,7 @@ public class DataManager {
|
||||||
/**
|
/**
|
||||||
* Provides an easy way to run a section of code either synchronously or asynchronously using a callback
|
* Provides an easy way to run a section of code either synchronously or asynchronously using a callback
|
||||||
*/
|
*/
|
||||||
|
@FunctionalInterface
|
||||||
private static interface SyncInterface {
|
private static interface SyncInterface {
|
||||||
public void execute();
|
public void execute();
|
||||||
}
|
}
|
||||||
|
@ -427,6 +428,7 @@ public class DataManager {
|
||||||
/**
|
/**
|
||||||
* Allows callbacks to be passed between configuration methods and executed for returning objects after database queries
|
* Allows callbacks to be passed between configuration methods and executed for returning objects after database queries
|
||||||
*/
|
*/
|
||||||
|
@FunctionalInterface
|
||||||
public static interface ConfigurationCallback<T> {
|
public static interface ConfigurationCallback<T> {
|
||||||
public void execute(T obj);
|
public void execute(T obj);
|
||||||
}
|
}
|
||||||
|
|
|
@ -177,16 +177,36 @@ public class LangManager {
|
||||||
// GUI
|
// GUI
|
||||||
GUI_DISABLED,
|
GUI_DISABLED,
|
||||||
GUI_BY_DEFAULT,
|
GUI_BY_DEFAULT,
|
||||||
|
GUI_COLOR_ICON_NAME,
|
||||||
|
GUI_COLOR_INFO,
|
||||||
|
GUI_COLOR_SUBTEXT,
|
||||||
|
GUI_COLOR_UNAVAILABLE,
|
||||||
GUI_BACK_BUTTON,
|
GUI_BACK_BUTTON,
|
||||||
GUI_ICON_NAME_COLOR,
|
GUI_CLICK_TO_LOAD,
|
||||||
GUI_ICON_CURRENT_ACTIVE,
|
GUI_SHIFT_CLICK_TO_DELETE,
|
||||||
GUI_ICON_SETS_TO,
|
GUI_PARTICLE_INFO,
|
||||||
GUI_ICON_SET_YOUR,
|
GUI_PLAYERPARTICLES,
|
||||||
GUI_NO_ACCESS_TO,
|
GUI_ACTIVE_PARTICLES,
|
||||||
GUI_NO_DATA; // @formatter:on
|
GUI_SAVED_GROUPS,
|
||||||
|
GUI_FIXED_EFFECTS,
|
||||||
|
GUI_MANAGE_YOUR_PARTICLES,
|
||||||
|
GUI_MANAGE_YOUR_PARTICLES_DESCRIPTION,
|
||||||
|
GUI_MANAGE_YOUR_GROUPS,
|
||||||
|
GUI_MANAGE_YOUR_GROUPS_DESCRIPTION,
|
||||||
|
GUI_LOAD_A_PRESET_GROUP,
|
||||||
|
GUI_LOAD_A_PRESET_GROUP_DESCRIPTION,
|
||||||
|
GUI_SAVE_GROUP,
|
||||||
|
GUI_SAVE_GROUP_DESCRIPTION,
|
||||||
|
GUI_SAVE_GROUP_DESCRIPTION_2;
|
||||||
|
// @formatter:on
|
||||||
|
|
||||||
private String message;
|
private String message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the name of the message in the config
|
||||||
|
*
|
||||||
|
* @return The location in the config that this message is located
|
||||||
|
*/
|
||||||
private String getConfigName() {
|
private String getConfigName() {
|
||||||
return this.name().toLowerCase().replaceAll("_", "-");
|
return this.name().toLowerCase().replaceAll("_", "-");
|
||||||
}
|
}
|
||||||
|
@ -230,6 +250,8 @@ public class LangManager {
|
||||||
* Used to set up the LangManager
|
* Used to set up the LangManager
|
||||||
* This should only get called once by the PlayerParticles class, however
|
* This should only get called once by the PlayerParticles class, however
|
||||||
* calling it multiple times wont affect anything negatively
|
* calling it multiple times wont affect anything negatively
|
||||||
|
*
|
||||||
|
* @param resetLangFile If the default.lang file should be updated to the latest version
|
||||||
*/
|
*/
|
||||||
public static void reload(boolean resetLangFile) {
|
public static void reload(boolean resetLangFile) {
|
||||||
YamlConfiguration lang = configureLangFile(resetLangFile);
|
YamlConfiguration lang = configureLangFile(resetLangFile);
|
||||||
|
@ -242,6 +264,7 @@ public class LangManager {
|
||||||
* If it doesn't exist, default to default.lang
|
* If it doesn't exist, default to default.lang
|
||||||
* If default.lang doesn't exist, copy the file from this .jar to the target directory
|
* If default.lang doesn't exist, copy the file from this .jar to the target directory
|
||||||
*
|
*
|
||||||
|
* @param resetLangFile If the default.lang file should be updated to the latest version
|
||||||
* @return The YamlConfiguration of the target .lang file
|
* @return The YamlConfiguration of the target .lang file
|
||||||
*/
|
*/
|
||||||
private static YamlConfiguration configureLangFile(boolean resetLangFile) {
|
private static YamlConfiguration configureLangFile(boolean resetLangFile) {
|
||||||
|
|
|
@ -1,20 +1,33 @@
|
||||||
package com.esophose.playerparticles.manager;
|
package com.esophose.playerparticles.manager;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.bukkit.Material;
|
||||||
|
|
||||||
import com.esophose.playerparticles.PlayerParticles;
|
import com.esophose.playerparticles.PlayerParticles;
|
||||||
|
import com.esophose.playerparticles.particles.ParticleEffect;
|
||||||
|
import com.esophose.playerparticles.util.ParticleUtils;
|
||||||
|
|
||||||
public class SettingManager {
|
public class SettingManager {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The types of settings that can be loaded
|
||||||
|
*/
|
||||||
private enum PSettingType {
|
private enum PSettingType {
|
||||||
BOOLEAN,
|
BOOLEAN,
|
||||||
INTEGER,
|
INTEGER,
|
||||||
LONG,
|
LONG,
|
||||||
DOUBLE,
|
DOUBLE,
|
||||||
STRING,
|
STRING,
|
||||||
STRING_LIST
|
STRING_LIST,
|
||||||
|
MATERIAL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An enum containing all settings in the config.yml for the plugin
|
||||||
|
*/
|
||||||
public enum PSetting {
|
public enum PSetting {
|
||||||
VERSION(PSettingType.DOUBLE),
|
VERSION(PSettingType.DOUBLE),
|
||||||
TICKS_PER_PARTICLE(PSettingType.LONG),
|
TICKS_PER_PARTICLE(PSettingType.LONG),
|
||||||
|
@ -87,6 +100,15 @@ public class SettingManager {
|
||||||
case STRING_LIST:
|
case STRING_LIST:
|
||||||
this.value = PlayerParticles.getPlugin().getConfig().getStringList(configPath);
|
this.value = PlayerParticles.getPlugin().getConfig().getStringList(configPath);
|
||||||
break;
|
break;
|
||||||
|
case MATERIAL:
|
||||||
|
String materialName = PlayerParticles.getPlugin().getConfig().getString(configPath);
|
||||||
|
Material material = ParticleUtils.closestMatch(materialName);
|
||||||
|
if (material == null) {
|
||||||
|
material = Material.BARRIER;
|
||||||
|
PlayerParticles.getPlugin().getLogger().severe("Invalid block/item name for '" + this.name().toLowerCase().replace('_', '-') + "' in config.yml: '" + materialName + "'");
|
||||||
|
}
|
||||||
|
this.value = material;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this.value;
|
return this.value;
|
||||||
|
@ -146,6 +168,92 @@ public class SettingManager {
|
||||||
public List<String> getStringList() {
|
public List<String> getStringList() {
|
||||||
return (List<String>) this.getValue();
|
return (List<String>) this.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the setting's value as a Material
|
||||||
|
*
|
||||||
|
* @return The setting's value as a Material
|
||||||
|
*/
|
||||||
|
public Material getMaterial() {
|
||||||
|
return (Material) this.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum GUIIcon {
|
||||||
|
PARTICLES,
|
||||||
|
GROUPS,
|
||||||
|
PRESET_GROUPS,
|
||||||
|
BACK,
|
||||||
|
CREATE,
|
||||||
|
EDIT_EFFECT,
|
||||||
|
EDIT_STYLE,
|
||||||
|
EDIT_DATA,
|
||||||
|
RANDOMIZE,
|
||||||
|
|
||||||
|
EFFECT,
|
||||||
|
STYLE;
|
||||||
|
|
||||||
|
private Map<String, Material> materials;
|
||||||
|
|
||||||
|
private GUIIcon() {
|
||||||
|
this.materials = new HashMap<String, Material>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the Material for this icon from the 'gui-icon.misc' section in the config.yml
|
||||||
|
* Tries to get from cache first, otherwise loads it
|
||||||
|
*
|
||||||
|
* @return The Material for this Icon
|
||||||
|
*/
|
||||||
|
public Material get() {
|
||||||
|
return this.getInternal("gui-icon.misc." + this.name().toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the Material for a subsection of this icon in the config.yml
|
||||||
|
* Tries to get from cache first, otherwise loads it
|
||||||
|
*
|
||||||
|
* @param subsection The name of the icon in the section
|
||||||
|
* @return The Material for this Icon
|
||||||
|
*/
|
||||||
|
public Material get(String subsection) {
|
||||||
|
return this.getInternal("gui-icon." + this.name().toLowerCase() + "." + subsection);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the Material for this icon
|
||||||
|
* Tries to get from cache first, otherwise loads it
|
||||||
|
*
|
||||||
|
* @return The path in the config.yml to lookup
|
||||||
|
*/
|
||||||
|
private Material getInternal(String configPath) {
|
||||||
|
Material material = this.materials.get(configPath);
|
||||||
|
if (material != null)
|
||||||
|
return material;
|
||||||
|
|
||||||
|
List<String> materials = PlayerParticles.getPlugin().getConfig().getStringList(configPath);
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (materials.size() == 1) {
|
||||||
|
material = ParticleUtils.closestMatch(materials.get(0));
|
||||||
|
} else {
|
||||||
|
if (ParticleEffect.VERSION_13) {
|
||||||
|
material = ParticleUtils.closestMatch(materials.get(0));
|
||||||
|
} else {
|
||||||
|
material = ParticleUtils.closestMatch(materials.get(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
PlayerParticles.getPlugin().getLogger().severe("Missing GUI icon for '" + this.name().toLowerCase() + "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (material == null)
|
||||||
|
material = Material.BARRIER;
|
||||||
|
|
||||||
|
this.materials.put(configPath, material);
|
||||||
|
|
||||||
|
return material;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private SettingManager() {
|
private SettingManager() {
|
||||||
|
|
|
@ -77,8 +77,8 @@ public enum ParticleEffect {
|
||||||
UNDERWATER("SUSPENDED_DEPTH", "SUSPENDED_DEPTH"),
|
UNDERWATER("SUSPENDED_DEPTH", "SUSPENDED_DEPTH"),
|
||||||
WITCH("SPELL_WITCH", "SPELL_WTICH");
|
WITCH("SPELL_WITCH", "SPELL_WTICH");
|
||||||
|
|
||||||
|
public static boolean VERSION_13; // This is a particle unique to Minecraft 1.13, this is a reliable way of telling what server version is running
|
||||||
private static final Map<String, ParticleEffect> NAME_MAP = new HashMap<String, ParticleEffect>();
|
private static final Map<String, ParticleEffect> NAME_MAP = new HashMap<String, ParticleEffect>();
|
||||||
private static boolean VERSION_13; // This is a particle unique to Minecraft 1.13, this is a reliable way of telling what server version is running
|
|
||||||
private static Constructor<?> DustOptions_CONSTRUCTOR;
|
private static Constructor<?> DustOptions_CONSTRUCTOR;
|
||||||
private static Method createBlockData_METHOD;
|
private static Method createBlockData_METHOD;
|
||||||
private final Particle internalEnum;
|
private final Particle internalEnum;
|
||||||
|
@ -307,6 +307,7 @@ public enum ParticleEffect {
|
||||||
* Gets a List of Players within the particle display range
|
* Gets a List of Players within the particle display range
|
||||||
*
|
*
|
||||||
* @param center The center of the radius to check around
|
* @param center The center of the radius to check around
|
||||||
|
* @param isFixedEffect If the particle is spawned from a fixed effect
|
||||||
* @return A List of Players within the particle display range
|
* @return A List of Players within the particle display range
|
||||||
*/
|
*/
|
||||||
private List<Player> getPlayersInRange(Location center, boolean isFixedEffect) {
|
private List<Player> getPlayersInRange(Location center, boolean isFixedEffect) {
|
||||||
|
|
|
@ -5,9 +5,10 @@ import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
import java.util.AbstractMap;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -84,8 +85,6 @@ public class ParticleGroup {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads the preset groups from the groups.yml file
|
* Loads the preset groups from the groups.yml file
|
||||||
*
|
|
||||||
* @param pluginDataFolder
|
|
||||||
*/
|
*/
|
||||||
public static void reload() {
|
public static void reload() {
|
||||||
presetGroups = new HashMap<ParticleGroup, Material>();
|
presetGroups = new HashMap<ParticleGroup, Material>();
|
||||||
|
@ -213,7 +212,8 @@ public class ParticleGroup {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iconMaterial == null) {
|
if (iconMaterial == null) {
|
||||||
|
PlayerParticles.getPlugin().getLogger().severe("Missing icon for group '" + groupName + "'! Defaulting to ENDER_CHEST");
|
||||||
|
iconMaterial = Material.ENDER_CHEST;
|
||||||
}
|
}
|
||||||
|
|
||||||
presetGroups.put(new ParticleGroup(groupName, particles), iconMaterial);
|
presetGroups.put(new ParticleGroup(groupName, particles), iconMaterial);
|
||||||
|
@ -223,11 +223,21 @@ public class ParticleGroup {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Set<Entry<ParticleGroup, Material>> getPresetGroupsForGUIForPlayer(Player player) {
|
/**
|
||||||
Set<Entry<ParticleGroup, Material>> groups = new HashSet<Entry<ParticleGroup, Material>>();
|
* Gets all the preset ParticleGroups ordered for display in the GUI
|
||||||
for (Entry<ParticleGroup, Material> entry : presetGroups.entrySet())
|
*
|
||||||
if (entry.getKey().canPlayerUse(player))
|
* @param player The player
|
||||||
groups.add(entry);
|
* @return a List of preset ParticleGroups the player can use
|
||||||
|
*/
|
||||||
|
public static List<Entry<ParticleGroup, Material>> getPresetGroupsForGUIForPlayer(Player player) {
|
||||||
|
List<Entry<ParticleGroup, Material>> groups = new ArrayList<Entry<ParticleGroup, Material>>();
|
||||||
|
List<ParticleGroup> orderedGroups = new ArrayList<ParticleGroup>();
|
||||||
|
orderedGroups.addAll(presetGroups.keySet());
|
||||||
|
orderedGroups.sort(Comparator.comparing(ParticleGroup::getName));
|
||||||
|
|
||||||
|
for (ParticleGroup group : orderedGroups)
|
||||||
|
if (group.canPlayerUse(player))
|
||||||
|
groups.add(new AbstractMap.SimpleEntry<ParticleGroup, Material>(group, presetGroups.get(group)));
|
||||||
return groups;
|
return groups;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
368
src/config.yml
368
src/config.yml
|
@ -31,7 +31,7 @@ messages-enabled: true
|
||||||
# Default: true
|
# Default: true
|
||||||
use-message-prefix: true
|
use-message-prefix: true
|
||||||
|
|
||||||
# The prefix to use for all PlayerParticle messages
|
# The prefix to use for all PlayerParticles messages
|
||||||
# This is useless if use-message-prefix is set to false
|
# This is useless if use-message-prefix is set to false
|
||||||
# Default: '&7[&3PlayerParticles&7]'
|
# Default: '&7[&3PlayerParticles&7]'
|
||||||
message-prefix: '&7[&3PlayerParticles&7]'
|
message-prefix: '&7[&3PlayerParticles&7]'
|
||||||
|
@ -49,12 +49,12 @@ disabled-worlds: []
|
||||||
# - add_more_under_these
|
# - add_more_under_these
|
||||||
|
|
||||||
# The maximum number of particles a player can apply at once
|
# The maximum number of particles a player can apply at once
|
||||||
# The GUI will only display up to 14, don't set this any higher than that
|
# The GUI will only display up to 21, don't set this any higher than that
|
||||||
# Default: 3
|
# Default: 3
|
||||||
max-particles: 3
|
max-particles: 3
|
||||||
|
|
||||||
# The maximum number of groups a player can have saved
|
# The maximum number of groups a player can have saved
|
||||||
# The GUI will only display up to 14, don't set this any higher than that
|
# The GUI will only display up to 21, don't set this any higher than that
|
||||||
# Default: 10
|
# Default: 10
|
||||||
max-groups: 10
|
max-groups: 10
|
||||||
|
|
||||||
|
@ -133,165 +133,213 @@ database-user-password: ''
|
||||||
# * You MUST use the Spigot-given name for it to work. You can see #
|
# * You MUST use the Spigot-given name for it to work. You can see #
|
||||||
# all the Spigot-given names at the link below: #
|
# all the Spigot-given names at the link below: #
|
||||||
# https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Material.html #
|
# https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Material.html #
|
||||||
|
# * If two icons are listed, the second one is used for below MC 1.13 #
|
||||||
# =================================================================== #
|
# =================================================================== #
|
||||||
|
|
||||||
gui-icon:
|
gui-icon:
|
||||||
main-menu:
|
misc:
|
||||||
EFFECT: BLAZE_POWDER
|
particles:
|
||||||
STYLE: NETHER_STAR
|
- BLAZE_POWDER
|
||||||
DATA: BOOK
|
groups:
|
||||||
effect: # 1.13 and up
|
- CHEST
|
||||||
AMBIENT_ENTITY_EFFECT: BEACON
|
preset_groups:
|
||||||
ANGRY_VILLAGER: IRON_DOOR
|
- ENDER_CHEST
|
||||||
BARRIER: BARRIER
|
back:
|
||||||
BLOCK: STONE
|
- ARROW
|
||||||
BUBBLE: BUBBLE_CORAL
|
create:
|
||||||
BUBBLE_COLUMN_UP: MAGMA_BLOCK
|
- WRITABLE_BOOK
|
||||||
BUBBLE_POP: BUBBLE_CORAL_FAN
|
- BOOK_AND_QUILL
|
||||||
CLOUD: WHITE_WOOL
|
edit_effect:
|
||||||
CRIT: IRON_SWORD
|
- FIREWORK_ROCKET
|
||||||
CURRENT_DOWN: SOUL_SAND
|
- FIREWORK
|
||||||
DAMAGE_INDICATOR: BOW
|
edit_style:
|
||||||
DOLPHIN: DOLPHIN_SPAWN_EGG
|
- NETHER_STAR
|
||||||
DRAGON_BREATH: DRAGON_BREATH
|
edit_data:
|
||||||
DRIPPING_LAVA: LAVA_BUCKET
|
- BOOK
|
||||||
DRIPPING_WATER: WATER_BUCKET
|
randomize:
|
||||||
DUST: REDSTONE
|
- HOPPER
|
||||||
ENCHANT: ENCHANTING_TABLE
|
effect:
|
||||||
ENCHANTED_HIT: DIAMOND_SWORD
|
ambient_entity_effect:
|
||||||
END_ROD: END_ROD
|
- BEACON
|
||||||
ENTITY_EFFECT: GLOWSTONE_DUST
|
angry_villager:
|
||||||
EXPLOSION: FIRE_CHARGE
|
- IRON_DOOR
|
||||||
EXPLOSION_EMITTER: TNT
|
barrier:
|
||||||
FALLING_DUST: SAND
|
- BARRIER
|
||||||
FIREWORK: FIREWORK_ROCKET
|
block:
|
||||||
FISHING: FISHING_ROD
|
- STONE
|
||||||
FLAME: BLAZE_POWDER
|
bubble:
|
||||||
HAPPY_VILLAGER: DARK_OAK_DOOR
|
- BUBBLE_CORAL
|
||||||
HEART: POPPY
|
- GLASS
|
||||||
INSTANT_EFFECT: SPLASH_POTION
|
bubble_column_up:
|
||||||
ITEM: ITEM_FRAME
|
- MAGMA_BLOCK
|
||||||
ITEM_SLIME: SLIME_BALL
|
bubble_pop:
|
||||||
ITEM_SNOWBALL: SNOWBALL
|
- BUBBLE_CORAL_FAN
|
||||||
LARGE_SMOKE: COBWEB
|
cloud:
|
||||||
LAVA: MAGMA_CREAM
|
- WHITE_WOOL
|
||||||
MYCELIUM: MYCELIUM
|
- WOOL
|
||||||
NAUTILUS: HEART_OF_THE_SEA
|
crit:
|
||||||
NOTE: NOTE_BLOCK
|
- IRON_SWORD
|
||||||
POOF: FIREWORK_STAR
|
current_down:
|
||||||
PORTAL: OBSIDIAN
|
- SOUL_SAND
|
||||||
RAIN: PUFFERFISH_BUCKET
|
damage_indicator:
|
||||||
SMOKE: TORCH
|
- BOW
|
||||||
SPELL: POTION
|
dolphin:
|
||||||
SPIT: LLAMA_SPAWN_EGG
|
- DOLPHIN_SPAWN_EGG
|
||||||
SPLASH: SALMON
|
dragon_breath:
|
||||||
SQUID_INK: INK_SAC
|
- DRAGON_BREATH
|
||||||
SWEEP_ATTACK: GOLDEN_SWORD
|
- DRAGONS_BREATH
|
||||||
TOTEM_OF_UNDYING: TOTEM
|
dripping_lava:
|
||||||
UNDERWATER: TURTLE_HELMET
|
- LAVA_BUCKET
|
||||||
WITCH: CAULDRON
|
dripping_water:
|
||||||
effect-legacy: # 1.9 to 1.12
|
- WATER_BUCKET
|
||||||
AMBIENT_ENTITY_EFFECT: BEACON
|
dust:
|
||||||
ANGRY_VILLAGER: IRON_DOOR
|
- REDSTONE
|
||||||
BARRIER: BARRIER
|
enchant:
|
||||||
BLOCK: STONE
|
- ENCHANTING_TABLE
|
||||||
BUBBLE: GLASS
|
- ENCHANTMENT_TABLE
|
||||||
CLOUD: WOOL
|
enchanted_hit:
|
||||||
CRIT: IRON_SWORD
|
- DIAMOND_SWORD
|
||||||
DAMAGE_INDICATOR: BOW
|
end_rod:
|
||||||
DRAGON_BREATH: DRAGONS_BREATH
|
- END_ROD
|
||||||
DRIPPING_LAVA: LAVA_BUCKET
|
entity_effect:
|
||||||
DRIPPING_WATER: WATER_BUCKET
|
- GLOWSTONE_DUST
|
||||||
DUST: REDSTONE
|
explosion:
|
||||||
ENCHANT: ENCHANTMENT_TABLE
|
- FIRE_CHARGE
|
||||||
ENCHANTED_HIT: DIAMOND_SWORD
|
- FIREBALL
|
||||||
END_ROD: END_ROD
|
explosion_emitter:
|
||||||
ENTITY_EFFECT: GLOWSTONE_DUST
|
- TNT
|
||||||
EXPLOSION: FIREBALL
|
falling_dust:
|
||||||
EXPLOSION_EMITTER: TNT
|
- SAND
|
||||||
FALLING_DUST: SAND
|
firework:
|
||||||
FIREWORK: FIREWORK
|
- FIREWORK_ROCKET
|
||||||
FISHING: FISHING_ROD
|
- FIREWORK
|
||||||
FLAME: BLAZE_POWDER
|
fishing:
|
||||||
FOOTSTEP: GRASS
|
- FISHING_ROD
|
||||||
HAPPY_VILLAGER: WOOD_DOOR
|
flame:
|
||||||
HEART: RED_ROSE
|
- BLAZE_POWDER
|
||||||
INSTANT_EFFECT: POTION
|
footstep:
|
||||||
ITEM: ITEM_FRAME
|
- GRASS
|
||||||
ITEM_SLIME: SLIME_BALL
|
happy_villager:
|
||||||
ITEM_SNOWBALL: SNOWBALL
|
- DARK_OAK_DOOR
|
||||||
LARGE_SMOKE: WEB
|
- WOOD_DOOR
|
||||||
LAVA: MAGMA_CREAM
|
heart:
|
||||||
MYCELIUM: MYCEL
|
- POPPY
|
||||||
NOTE: NOTE_BLOCK
|
- RED_ROSE
|
||||||
POOF: FIREWORK_CHARGE
|
instant_effect:
|
||||||
PORTAL: OBSIDIAN
|
- SPLASH_POTION
|
||||||
RAIN: LAPIS_BLOCK
|
- POTION
|
||||||
SMOKE: TORCH
|
item:
|
||||||
SPELL: GLASS_BOTTLE
|
- ITEM_FRAME
|
||||||
SPIT: PUMPKIN_SEEDS
|
item_slime:
|
||||||
SPLASH: FISH
|
- SLIME_BALL
|
||||||
SWEEP_ATTACK: GOLD_SWORD
|
item_snowball:
|
||||||
TOTEM_OF_UNDYING: TOTEM
|
- SNOWBALL
|
||||||
UNDERWATER: BOAT
|
large_smoke:
|
||||||
WITCH: CAULDRON
|
- COBWEB
|
||||||
style: # 1.13 and up
|
- WEB
|
||||||
ARROWS: BOW
|
lava:
|
||||||
BATMAN: COAL
|
- MAGMA_CREAM
|
||||||
BEAM: POWERED_RAIL
|
mycelium:
|
||||||
BLOCKBREAK: IRON_PICKAXE
|
- MYCELIUM
|
||||||
BLOCKEDIT: DISPENSER
|
- MYCEL
|
||||||
BLOCKPLACE: OAK_PLANKS
|
nautilus:
|
||||||
CHAINS: TRIPWIRE_HOOK
|
- HEART_OF_THE_SEA
|
||||||
COMPANION: NAME_TAG
|
note:
|
||||||
CUBE: STONE
|
- NOTE_BLOCK
|
||||||
FEET: GRASS
|
poof:
|
||||||
HALO: END_PORTAL_FRAME
|
- FIREWORK_STAR
|
||||||
HURT: CACTUS
|
- FIREWORK_CHARGE
|
||||||
INVOCATION: ENDER_EYE
|
portal:
|
||||||
MOVE: PISTON
|
- OBSIDIAN
|
||||||
NONE: GLASS_PANE
|
rain:
|
||||||
ORBIT: ENCHANTING_TABLE
|
- PUFFERFISH_BUCKET
|
||||||
OVERHEAD: GLOWSTONE
|
- LAPIS_BLOCK
|
||||||
POINT: STONE_BUTTON
|
smoke:
|
||||||
QUADHELIX: NAUTILUS_SHELL
|
- TORCH
|
||||||
NORMAL: DIRT
|
spell:
|
||||||
RINGS: STRING
|
- POTION
|
||||||
SPHERE: HEART_OF_THE_SEA
|
- GLASS_BOTTLE
|
||||||
SPIN: BEACON
|
spit:
|
||||||
SPIRAL: HOPPER
|
- LLAMA_SPAWN_EGG
|
||||||
SWORDS: IRON_SWORD
|
- PUMPKIN_SEEDS
|
||||||
THICK: COBWEB
|
splash:
|
||||||
VORTEX: GLOWSTONE_DUST
|
- SALMON
|
||||||
WINGS: ELYTRA
|
- FISH
|
||||||
style-legacy: # 1.9 to 1.12
|
squid_ink:
|
||||||
ARROWS: BOW
|
- INK_SAC
|
||||||
BATMAN: COAL
|
sweep_attack:
|
||||||
BEAM: POWERED_RAIL
|
- GOLDEN_SWORD
|
||||||
BLOCKBREAK: IRON_PICKAXE
|
- GOLD_SWORD
|
||||||
BLOCKEDIT: DISPENSER
|
totem_of_undying:
|
||||||
BLOCKPLACE: WOOD
|
- TOTEM
|
||||||
CHAINS: TRIPWIRE_HOOK
|
underwater:
|
||||||
COMPANION: NAME_TAG
|
- TURTLE_HELMET
|
||||||
CUBE: STONE
|
witch:
|
||||||
FEET: GRASS
|
- CAULDRON
|
||||||
HALO: ENDER_PORTAL_FRAME
|
style:
|
||||||
HURT: CACTUS
|
arrows:
|
||||||
INVOCATION: EYE_OF_ENDER
|
- BOW
|
||||||
MOVE: PISTON_BASE
|
batman:
|
||||||
NORMAL: DIRT
|
- BAT_SPAWN_EGG
|
||||||
ORBIT: ENCHANTMENT_TABLE
|
- COAL
|
||||||
OVERHEAD: GLOWSTONE
|
beam:
|
||||||
POINT: STONE_BUTTON
|
- POWERED_RAIL
|
||||||
QUADHELIX: ACTIVATOR_RAIL
|
blockbreak:
|
||||||
RINGS: STRING
|
- IRON_PICKAXE
|
||||||
SPHERE: SNOW_BALL
|
blockedit:
|
||||||
SPIN: BEACON
|
- DISPENSER
|
||||||
SPIRAL: HOPPER
|
blockplace:
|
||||||
SWORDS: IRON_SWORD
|
- OAK_PLANKS
|
||||||
THICK: VINE
|
- WOOD
|
||||||
VORTEX: GLOWSTONE_DUST
|
chains:
|
||||||
WINGS: ELYTRA
|
- TRIPWIRE_HOOK
|
||||||
|
companion:
|
||||||
|
- NAME_TAG
|
||||||
|
cube:
|
||||||
|
- STONE
|
||||||
|
feet:
|
||||||
|
- GRASS
|
||||||
|
halo:
|
||||||
|
- END_PORTAL_FRAME
|
||||||
|
- ENDER_PORTAL_FRAME
|
||||||
|
hurt:
|
||||||
|
- CACTUS
|
||||||
|
invocation:
|
||||||
|
- ENDER_EYE
|
||||||
|
- EYE_OF_ENDER
|
||||||
|
move:
|
||||||
|
- PISTON
|
||||||
|
- PISTON_BASE
|
||||||
|
normal:
|
||||||
|
- DIRT
|
||||||
|
orbit:
|
||||||
|
- ENCHANTING_TABLE
|
||||||
|
- ENCHANTMENT_TABLE
|
||||||
|
overhead:
|
||||||
|
- GLOWSTONE
|
||||||
|
point:
|
||||||
|
- STONE_BUTTON
|
||||||
|
quadhelix:
|
||||||
|
- NAUTILUS_SHELL
|
||||||
|
- ACTIVATOR_RAIL
|
||||||
|
rings:
|
||||||
|
- STRING
|
||||||
|
sphere:
|
||||||
|
- HEART_OF_THE_SEA
|
||||||
|
- SNOWBALL
|
||||||
|
spin:
|
||||||
|
- BEACON
|
||||||
|
spiral:
|
||||||
|
- HOPPER
|
||||||
|
swords:
|
||||||
|
- IRON_SWORD
|
||||||
|
thick:
|
||||||
|
- COBWEB
|
||||||
|
- WEB
|
||||||
|
vortex:
|
||||||
|
- GLOWSTONE_DUST
|
||||||
|
wings:
|
||||||
|
- ELYTRA
|
||||||
|
|
||||||
# That's everything! You reached the end of the configuration.
|
# That's everything! You reached the end of the configuration.
|
||||||
# Enjoy the plugin!
|
# Enjoy the plugin!
|
||||||
|
|
|
@ -163,10 +163,24 @@ fixed-invalid-command: '&cInvalid sub-command for &b/pp fixed&c!'
|
||||||
# GUI
|
# GUI
|
||||||
gui-disabled: '&cThe server administrator has disabled the GUI!'
|
gui-disabled: '&cThe server administrator has disabled the GUI!'
|
||||||
gui-by-default: '&eWe opened the GUI for you because you did not specify a command. View other commands with &b/pp help&e or use &b/pp gui&e to avoid this message.'
|
gui-by-default: '&eWe opened the GUI for you because you did not specify a command. View other commands with &b/pp help&e or use &b/pp gui&e to avoid this message.'
|
||||||
gui-back-button: '&eGo Back'
|
gui-color-icon-name: '&a'
|
||||||
gui-icon-name-color: '&a'
|
gui-color-info: '&e'
|
||||||
gui-icon-current-active: '&d- Your current {0} -'
|
gui-color-subtext: '&b'
|
||||||
gui-icon-sets-to: '&eSets your {0} to &b'
|
gui-color-unavailable: '&c'
|
||||||
gui-icon-set-your: '&eSelect your {0}'
|
gui-back-button: 'Go Back'
|
||||||
gui-no-access-to: '&cYou have no access to any {0}!'
|
gui-click-to-load: 'Click to load the following {0} particle(s):'
|
||||||
gui-no-data: '&cYour effect does not use any data!'
|
gui-shift-click-to-delete: 'Shift click to delete'
|
||||||
|
gui-particle-info: ' - ID: &b{0} &eEffect: &b{1} &eStyle: &b{2} &eData: &b{3}'
|
||||||
|
gui-playerparticles: 'PlayerParticles'
|
||||||
|
gui-active-particles: 'Active Particles: &b{0}'
|
||||||
|
gui-saved-groups: 'Saved Groups: &b{0}'
|
||||||
|
gui-fixed-effects: 'Fixed Effects: &b{0}'
|
||||||
|
gui-manage-your-particles: 'Manage Your Particles'
|
||||||
|
gui-manage-your-particles-description: 'Create, edit, and delete your particles'
|
||||||
|
gui-manage-your-groups: 'Manage Your Groups'
|
||||||
|
gui-manage-your-groups-description: 'Create, delete, and load your particle groups'
|
||||||
|
gui-load-a-preset-group: 'Load A Preset Group'
|
||||||
|
gui-load-a-preset-group-description: 'Load a premade particle group'
|
||||||
|
gui-save-group: 'Save New Group'
|
||||||
|
gui-save-group-description: 'You can save a new group using the following command:'
|
||||||
|
gui-save-group-description-2: '/pp group save <groupName>'
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue