Merge branch 'development' into 'master'

2.0.7

See merge request Songoda/songodaupdater!10
This commit is contained in:
Jacob Scott 2019-09-07 14:36:36 +00:00
commit 07b40f604c
13 changed files with 957 additions and 124 deletions

View File

@ -4,7 +4,7 @@ stages:
variables:
name: "SongodaCore"
path: "/builds/$CI_PROJECT_PATH"
version: "2.0.6"
version: "2.0.7"
build:
stage: build

View File

@ -46,7 +46,7 @@ public class SongodaCore {
* Whenever we make a major change to the core GUI, updater,
* or other function used by the core, increment this number
*/
private final static int coreRevision = 2;
private final static int coreRevision = 3;
private final static int updaterVersion = 1;
private final static Set<PluginInfo> registeredPlugins = new HashSet<>();

View File

@ -293,7 +293,7 @@ public enum CompatibleSounds {
ENTITY_DROWNED_SHOOT,
ENTITY_DROWNED_STEP,
ENTITY_DROWNED_SWIM,
ENTITY_EGG_THROW,
ENTITY_EGG_THROW(ServerVersion.V1_9, v("SHOOT_ARROW", true)),
ENTITY_ELDER_GUARDIAN_AMBIENT,
ENTITY_ELDER_GUARDIAN_AMBIENT_LAND,
ENTITY_ELDER_GUARDIAN_CURSE,
@ -767,7 +767,7 @@ public enum CompatibleSounds {
ITEM_CROSSBOW_QUICK_CHARGE_3,
ITEM_CROSSBOW_SHOOT,
ITEM_ELYTRA_FLYING,
ITEM_FIRECHARGE_USE,
ITEM_FIRECHARGE_USE(ServerVersion.V1_9, v("GHAST_FIREBALL", true)),
ITEM_FLINTANDSTEEL_USE("FIRE_IGNITE"),
ITEM_HOE_TILL,
ITEM_NETHER_WART_PLANT,

View File

@ -6,6 +6,7 @@ import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import org.bukkit.Material;
import org.bukkit.entity.EntityType;
import org.bukkit.inventory.ItemStack;
/**
@ -932,7 +933,7 @@ public enum LegacyMaterials {
TNT_MINECART("EXPLOSIVE_MINECART"),
TORCH,
TOTEM_OF_UNDYING("TOTEM"),
TRADER_LLAMA_SPAWN_EGG(ServerVersion.V1_14, "LLAMA_SPAWN_EGG"),
TRADER_LLAMA_SPAWN_EGG(),
TRAPPED_CHEST,
TRIDENT,
TRIPWIRE,
@ -1952,8 +1953,8 @@ public enum LegacyMaterials {
case PURPLE_WALL_BANNER:
case REDSTONE_WALL_TORCH:
case REDSTONE_WIRE:
case RED_TULIP:
case SKELETON_SPAWN_EGG:
case RED_WALL_BANNER:
case SKELETON_WALL_SKULL:
case SPRUCE_WALL_SIGN:
case SWEET_BERRY_BUSH:
case TALL_SEAGRASS:
@ -1970,6 +1971,8 @@ public enum LegacyMaterials {
switch (this) {
case ACACIA_WOOD:
case BIRCH_WOOD:
case BREWING_STAND:
case CAULDRON:
case DARK_OAK_WOOD:
case JUNGLE_WOOD:
case OAK_WOOD:
@ -2024,6 +2027,13 @@ public enum LegacyMaterials {
return false;
}
public static LegacyMaterials getSpawnEgg(EntityType type) {
if(type == EntityType.MUSHROOM_COW) {
return MOOSHROOM_SPAWN_EGG;
}
return lookupMap.get(type.name() + "_SPAWN_EGG");
}
public static LegacyMaterials getGlassPaneColor(int color) {
switch (color) {
case 0:

View File

@ -126,16 +126,18 @@ public class Config extends ConfigSection {
fileName = file;
}
public Config(@NotNull Plugin plugin, @NotNull String directory, @NotNull String file) {
public Config(@NotNull Plugin plugin, @Nullable String directory, @NotNull String file) {
this.plugin = plugin;
dirName = directory;
fileName = file;
}
@NotNull
public ConfigFileConfigurationAdapter getFileConfig() {
return config;
}
@NotNull
public File getFile() {
if (file == null) {
if (dirName != null) {
@ -175,6 +177,7 @@ public class Config extends ConfigSection {
* @param autosaveInterval time in seconds
* @return this class
*/
@NotNull
public Config setAutosaveInterval(int autosaveInterval) {
this.autosaveInterval = autosaveInterval;
return this;
@ -202,6 +205,7 @@ public class Config extends ConfigSection {
/**
* Default comment applied to config nodes
*/
@Nullable
public ConfigFormattingRules.CommentStyle getDefaultNodeCommentFormat() {
return defaultNodeCommentFormat;
}
@ -211,7 +215,8 @@ public class Config extends ConfigSection {
*
* @return this config
*/
public Config setDefaultNodeCommentFormat(ConfigFormattingRules.CommentStyle defaultNodeCommentFormat) {
@NotNull
public Config setDefaultNodeCommentFormat(@Nullable ConfigFormattingRules.CommentStyle defaultNodeCommentFormat) {
this.defaultNodeCommentFormat = defaultNodeCommentFormat;
return this;
}
@ -219,6 +224,7 @@ public class Config extends ConfigSection {
/**
* Default comment applied to section nodes
*/
@Nullable
public ConfigFormattingRules.CommentStyle getDefaultSectionCommentFormat() {
return defaultSectionCommentFormat;
}
@ -228,7 +234,8 @@ public class Config extends ConfigSection {
*
* @return this config
*/
public Config setDefaultSectionCommentFormat(ConfigFormattingRules.CommentStyle defaultSectionCommentFormat) {
@NotNull
public Config setDefaultSectionCommentFormat(@Nullable ConfigFormattingRules.CommentStyle defaultSectionCommentFormat) {
this.defaultSectionCommentFormat = defaultSectionCommentFormat;
return this;
}
@ -245,6 +252,7 @@ public class Config extends ConfigSection {
*
* @return this config
*/
@NotNull
public Config setRootNodeSpacing(int rootNodeSpacing) {
this.rootNodeSpacing = rootNodeSpacing;
return this;
@ -264,6 +272,7 @@ public class Config extends ConfigSection {
*
* @return this config
*/
@NotNull
public Config setCommentSpacing(int commentSpacing) {
this.commentSpacing = commentSpacing;
return this;

View File

@ -0,0 +1,35 @@
package com.songoda.core.configuration;
import org.bukkit.configuration.ConfigurationSection;
public interface DataStoreObject<T> {
/**
* @return a unique hashable instance of T to store this value under
*/
public abstract T getKey();
/**
* @return a unique identifier for saving this value with
*/
public abstract String getConfigKey();
/**
* Save this data to a ConfigurationSection
*
* @param sec
*/
public abstract void saveToSection(ConfigurationSection sec);
/**
* @return true if this data has changed from the state saved to file
*/
public boolean hasChanged();
/**
* Mark this data as needing a save or not
*
* @param isChanged
*/
public void setChanged(boolean isChanged);
}

View File

@ -0,0 +1,264 @@
package com.songoda.core.configuration;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.function.Function;
import java.util.logging.Level;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Used to easily store a set of one data value
*
* @param <T> DataObject class that is used to store the data
* @since 2019-09-06
* @author jascotty2
*/
public class SimpleDataStore<T extends DataStoreObject> {
protected final Plugin plugin;
protected final String filename, dirName;
private final Function<ConfigurationSection, T> getFromSection;
protected final HashMap<Object, T> data = new HashMap();
private File file;
private final Object lock = new Object();
SaveTask saveTask;
Timer autosaveTimer;
/**
* time in seconds to start a save after a change is made
*/
int autosaveInterval = 60;
public SimpleDataStore(@NotNull Plugin plugin, @NotNull String filename, @NotNull Function<ConfigurationSection, T> loadFunction) {
this.plugin = plugin;
this.filename = filename;
dirName = null;
this.getFromSection = loadFunction;
}
public SimpleDataStore(@NotNull Plugin plugin, @Nullable String directory, @NotNull String filename, @NotNull Function<ConfigurationSection, T> loadFunction) {
this.plugin = plugin;
this.filename = filename;
this.dirName = directory;
this.getFromSection = loadFunction;
}
@NotNull
public File getFile() {
if (file == null) {
if (dirName != null) {
this.file = new File(plugin.getDataFolder() + dirName, filename != null ? filename : "data.yml");
} else {
this.file = new File(plugin.getDataFolder(), filename != null ? filename : "data.yml");
}
}
return file;
}
/**
* @return a directly-modifiable instance of the data mapping for this
* storage
*/
public Map<Object, T> getData() {
return data;
}
/**
* Returns the value to which the specified key is mapped, or {@code null}
* if this map contains no mapping for the key.
*
* @param key key whose mapping is to be retrieved from this storage
* @return the value associated with <tt>key</tt>, or
* <tt>null</tt> if there was no mapping for <tt>key</tt>.
*/
@Nullable
public T get(Object key) {
return data.get(key);
}
/**
* Removes the mapping for the specified key from this storage if present.
*
* @param key key whose mapping is to be removed from this storage
* @return the previous value associated with <tt>key</tt>, or
* <tt>null</tt> if there was no mapping for <tt>key</tt>.
*/
@Nullable
public T remove(@NotNull Object key) {
T temp;
synchronized (lock) {
temp = data.remove(key);
}
save();
return temp;
}
/**
* Removes the mapping for the specified key from this storage if present.
*
* @param value value whose mapping is to be removed from this storage
* @return the previous value associated with <tt>key</tt>, or
* <tt>null</tt> if there was no mapping for <tt>key</tt>.
*/
@Nullable
public T remove(@NotNull T value) {
if (value == null) {
return null;
}
T temp;
synchronized (lock) {
temp = data.remove(value.getKey());
}
save();
return temp;
}
/**
* Adds the specified value in this storage. If the map previously contained
* a mapping for the key, the old value is replaced.
*
* @param value value to be added
* @return the previous value associated with <tt>value.getKey()</tt>, or
* <tt>null</tt> if there was no mapping for <tt>value.getKey()</tt>.
*/
@Nullable
public T add(@NotNull T value) {
if (value == null) {
return null;
}
T temp;
synchronized (lock) {
temp = data.put(value.getKey(), value);
}
save();
return temp;
}
/**
* Adds the specified value in this storage. If the map previously contained
* a mapping for the key, the old value is replaced.
*
* @param value values to be added
*/
@Nullable
public void addAll(@NotNull T[] value) {
if (value == null) {
return;
}
synchronized (lock) {
for (int i = 0; i < value.length; ++i) {
if (value[i] != null) {
data.put(value[i].getKey(), value[i]);
}
}
}
save();
}
/**
* Adds the specified value in this storage. If the map previously contained
* a mapping for the key, the old value is replaced.
*
* @param value values to be added
*/
@Nullable
public void addAll(@NotNull Collection<T> value) {
if (value == null) {
return;
}
synchronized (lock) {
for (T v : value) {
if (v != null) {
data.put(v.getKey(), v);
}
}
}
save();
}
/**
* Load data from the associated file
*/
public void load() {
if (!getFile().exists()) {
return;
}
try {
YamlConfiguration f = new YamlConfiguration();
f.options().pathSeparator('\0');
f.load(file);
synchronized (lock) {
data.clear();
f.getValues(false).entrySet().stream()
.filter(d -> d.getValue() instanceof ConfigurationSection)
.map(Map.Entry::getValue)
.map(v -> getFromSection.apply((ConfigurationSection) v))
.forEach(v -> data.put(v.getKey(), v));
}
} catch (IOException | InvalidConfigurationException ex) {
plugin.getLogger().log(Level.SEVERE, "Failed to load data from " + file.getName(), ex);
}
}
/**
* Optionally save this storage's data to file if there have been changes
* made
*/
public void saveChanges() {
if (saveTask != null || data.values().stream().anyMatch(v -> v.hasChanged())) {
flushSave();
}
}
/**
* Save this file data. This saves later asynchronously.
*/
public void save() {
// save async even if no plugin or if plugin disabled
if (saveTask == null) {
autosaveTimer = new Timer((plugin != null ? plugin.getName() + "-DataStoreSave-" : "DataStoreSave-") + getFile().getName());
autosaveTimer.schedule(saveTask = new SaveTask(), autosaveInterval * 1000L);
}
}
/**
* Force a new save of this storage's data
*/
public void flushSave() {
if (saveTask != null) {
//Close Threads
saveTask.cancel();
autosaveTimer.cancel();
saveTask = null;
autosaveTimer = null;
}
YamlConfiguration f = new YamlConfiguration();
synchronized (lock) {
data.values().stream().forEach(e -> e.saveToSection(f.createSection(e.getConfigKey())));
}
try {
f.save(getFile());
data.values().stream().forEach(e -> e.setChanged(false));
} catch (IOException ex) {
plugin.getLogger().log(Level.SEVERE, "Failed to save data to " + file.getName(), ex);
}
}
class SaveTask extends TimerTask {
@Override
public void run() {
flushSave();
}
}
}

View File

@ -0,0 +1,335 @@
package com.songoda.core.gui;
import com.songoda.core.compatibility.LegacyMaterials;
import com.songoda.core.configuration.DataStoreObject;
import com.songoda.core.configuration.SimpleDataStore;
import com.songoda.core.gui.methods.Clickable;
import java.util.List;
import java.util.Map;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Represents a GUI screen that can be user-configured
*
* @since 2019-09-06
* @author jascotty2
*/
public class CustomizableGui extends Gui {
final Map<String, CustomButton> buttons;
public CustomizableGui(SimpleDataStore<CustomButton> buttons) {
this((Map<String, CustomButton>) (Map) buttons.getData());
}
public CustomizableGui(SimpleDataStore<CustomButton> buttons, Gui parent) {
this((Map<String, CustomButton>) (Map) buttons.getData(), parent);
}
public CustomizableGui(@NotNull Map<String, CustomButton> buttons) {
this(buttons, null);
}
public CustomizableGui(@NotNull Map<String, CustomButton> buttons, @Nullable Gui parent) {
super(parent);
this.buttons = buttons;
if (buttons.containsKey("__DEFAULT__")) {
blankItem = GuiUtils.getBorderItem(buttons.get("__DEFAULT__").icon);
}
}
@NotNull
public CustomButton[] getButtons() {
return buttons.values().toArray(new CustomButton[buttons.size()]);
}
@NotNull
@Override
public CustomizableGui setDefaultItem(ItemStack item) {
if ((blankItem = item) != null) {
buttons.put("__DEFAULT__", (new CustomButton("__DEFAULT__")).setIcon(LegacyMaterials.getMaterial(item)));
}
return this;
}
@Nullable
public CustomButton getButton(@NotNull String key) {
return key == null ? null : buttons.get(key.toLowerCase());
}
@NotNull
public CustomizableGui setItem(int defaultRow, int defaultCol, @NotNull String key, @NotNull ItemStack item) {
final int cell = defaultCol + defaultRow * 9;
return setItem(cell, key, item);
}
@NotNull
public CustomizableGui setItem(int defaultCell, @NotNull String key, @NotNull ItemStack item) {
CustomButton btn = key == null ? null : buttons.get(key = key.toLowerCase());
if (btn == null) {
buttons.put(key, btn = (new CustomButton(key, defaultCell)).setIcon(LegacyMaterials.getMaterial(item)));
} else {
ItemStack btnItem = btn.icon.getItem();
ItemMeta itemMeta = item.getItemMeta();
ItemMeta btnItemMeta = btnItem.getItemMeta();
if (itemMeta != null && btnItemMeta != null) {
btnItemMeta.setDisplayName(itemMeta.getDisplayName());
btnItemMeta.setLore(itemMeta.getLore());
btnItem.setItemMeta(itemMeta);
}
item = btnItem;
}
cellItems.put(btn.position, item);
if (inventory != null && btn.position >= 0 && btn.position < inventory.getSize()) {
inventory.setItem(btn.position, item);
}
return this;
}
@NotNull
public CustomizableGui setItem(int defaultRow, int defaultCol, @NotNull String key, @NotNull LegacyMaterials defaultItem, @NotNull String title, @NotNull String... lore) {
final int cell = defaultCol + defaultRow * 9;
return setItem(cell, key, defaultItem, title, lore);
}
@NotNull
public CustomizableGui setItem(int defaultCell, @NotNull String key, @NotNull LegacyMaterials defaultItem, @NotNull String title, @NotNull String... lore) {
CustomButton btn = key == null ? null : buttons.get(key = key.toLowerCase());
if (btn == null) {
buttons.put(key, btn = (new CustomButton(key, defaultCell)).setIcon(defaultItem));
}
ItemStack item = GuiUtils.createButtonItem(btn.icon, title, lore);
cellItems.put(btn.position, item);
if (inventory != null && btn.position >= 0 && btn.position < inventory.getSize()) {
inventory.setItem(btn.position, item);
}
return this;
}
@NotNull
public CustomizableGui highlightItem(@NotNull String key) {
CustomButton btn = key == null ? null : buttons.get(key.toLowerCase());
if (btn != null) {
this.highlightItem(btn.position);
}
return this;
}
@NotNull
public CustomizableGui removeHighlight(@NotNull String key) {
CustomButton btn = key == null ? null : buttons.get(key.toLowerCase());
if (btn != null) {
this.removeHighlight(btn.position);
}
return this;
}
@NotNull
public CustomizableGui updateItem(@NotNull String key, @Nullable String title, @NotNull String... lore) {
CustomButton btn = key == null ? null : buttons.get(key.toLowerCase());
if (btn != null) {
this.updateItem(btn.position, title, lore);
}
return this;
}
@NotNull
public CustomizableGui updateItem(@NotNull String key, @Nullable String title, @Nullable List<String> lore) {
CustomButton btn = key == null ? null : buttons.get(key.toLowerCase());
if (btn != null) {
this.updateItem(btn.position, title, lore);
}
return this;
}
@NotNull
public CustomizableGui updateItem(@NotNull String key, @NotNull LegacyMaterials itemTo, @NotNull String title, @NotNull String... lore) {
CustomButton btn = key == null ? null : buttons.get(key.toLowerCase());
if (btn != null) {
this.updateItem(btn.position, itemTo, title, lore);
}
return this;
}
@NotNull
public CustomizableGui updateItem(@NotNull String key, @NotNull LegacyMaterials itemTo, @NotNull String title, @Nullable List<String> lore) {
CustomButton btn = key == null ? null : buttons.get(key.toLowerCase());
if (btn != null) {
this.updateItem(btn.position, itemTo, title, lore);
}
return this;
}
@NotNull
public CustomizableGui setAction(@NotNull String key, Clickable action) {
CustomButton btn = key == null ? null : buttons.get(key = key.toLowerCase());
if (btn != null) {
setConditional(btn.position, null, action);
}
return this;
}
@NotNull
public CustomizableGui setAction(@NotNull String key, @Nullable ClickType type, @Nullable Clickable action) {
CustomButton btn = key == null ? null : buttons.get(key = key.toLowerCase());
if (btn != null) {
setConditional(btn.position, type, action);
}
return this;
}
@NotNull
public CustomizableGui setButton(int defaultCell, @NotNull String key, ItemStack item, @Nullable Clickable action) {
setItem(defaultCell, key, item);
setAction(key, null, action);
return this;
}
@NotNull
public CustomizableGui setButton(int defaultCell, @NotNull String key, ItemStack item, @Nullable ClickType type, @Nullable Clickable action) {
setItem(defaultCell, key, item);
setAction(key, type, action);
return this;
}
@NotNull
public CustomizableGui setButton(int defaultRow, int defaultCol, @NotNull String key, ItemStack item, @Nullable Clickable action) {
final int defaultCell = defaultCol + defaultRow * 9;
setItem(defaultCell, key, item);
setAction(key, null, action);
return this;
}
@NotNull
public CustomizableGui setButton(int defaultRow, int defaultCol, @NotNull String key, ItemStack item, @Nullable ClickType type, @Nullable Clickable action) {
final int defaultCell = defaultCol + defaultRow * 9;
setItem(defaultCell, key, item);
setAction(key, type, action);
return this;
}
@NotNull
@Override
public CustomizableGui setNextPage(int row, int col, @NotNull ItemStack item) {
return this.setNextPage(col + row * 9, item);
}
@NotNull
@Override
public CustomizableGui setNextPage(int cell, @NotNull ItemStack item) {
CustomButton btn = buttons.get("__NEXT__");
if (btn == null) {
buttons.put("__NEXT__", btn = (new CustomButton("__NEXT__", cell)).setIcon(LegacyMaterials.getMaterial(item)));
} else {
ItemStack btnItem = btn.icon.getItem();
ItemMeta itemMeta = item.getItemMeta();
ItemMeta btnItemMeta = btnItem.getItemMeta();
if (itemMeta != null && btnItemMeta != null) {
btnItemMeta.setDisplayName(itemMeta.getDisplayName());
btnItemMeta.setLore(itemMeta.getLore());
btnItem.setItemMeta(itemMeta);
}
item = btnItem;
}
return (CustomizableGui) super.setNextPage(btn.position, item);
}
@NotNull
@Override
public CustomizableGui setPrevPage(int row, int col, @NotNull ItemStack item) {
return this.setPrevPage(col + row * 9, item);
}
@NotNull
@Override
public CustomizableGui setPrevPage(int cell, @NotNull ItemStack item) {
CustomButton btn = buttons.get("__PREV__");
if (btn == null) {
buttons.put("__PREV__", btn = (new CustomButton("__PREV__", cell)).setIcon(LegacyMaterials.getMaterial(item)));
} else {
ItemStack btnItem = btn.icon.getItem();
ItemMeta itemMeta = item.getItemMeta();
ItemMeta btnItemMeta = btnItem.getItemMeta();
if (itemMeta != null && btnItemMeta != null) {
btnItemMeta.setDisplayName(itemMeta.getDisplayName());
btnItemMeta.setLore(itemMeta.getLore());
btnItem.setItemMeta(itemMeta);
}
item = btnItem;
}
return (CustomizableGui) super.setPrevPage(btn.position, item);
}
public CustomizableGui clearActions(@NotNull String key) {
CustomButton btn = key == null ? null : buttons.get(key = key.toLowerCase());
if (btn != null) {
this.clearActions(btn.position);
}
return this;
}
public static class CustomButton implements DataStoreObject<String> {
boolean _changed = false;
final String key;
int position = -1;
LegacyMaterials icon = LegacyMaterials.STONE;
public CustomButton(String key) {
this.key = key;
}
public CustomButton(String key, int position) {
this.key = key;
this.position = position;
}
public static CustomButton loadFromSection(ConfigurationSection sec) {
CustomButton dat = new CustomButton(sec.getName());
dat.icon = sec.contains("icon") ? LegacyMaterials.getMaterial(sec.getString("icon"), LegacyMaterials.STONE) : LegacyMaterials.STONE;
dat.position = sec.getInt("position");
return dat;
}
@Override
public void saveToSection(ConfigurationSection sec) {
sec.set("icon", icon.name());
sec.set("position", position);
}
@Override
public String getKey() {
return key;
}
@Override
public String getConfigKey() {
return key;
}
@Override
public boolean hasChanged() {
return _changed;
}
@Override
public void setChanged(boolean isChanged) {
_changed = isChanged;
}
public LegacyMaterials getIcon() {
return icon;
}
public CustomButton setIcon(LegacyMaterials icon) {
this.icon = icon != null ? icon : LegacyMaterials.STONE;
_changed = true;
return this;
}
}
}

View File

@ -26,6 +26,8 @@ import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* TODO: animated buttons
@ -62,8 +64,8 @@ public class Gui {
this.rows = 3;
}
public Gui(GuiType type) {
this.inventoryType = type;
public Gui(@NotNull GuiType type) {
this.inventoryType = type != null ? type : GuiType.STANDARD;
switch (type) {
case HOPPER:
case DISPENSER:
@ -74,7 +76,7 @@ public class Gui {
}
}
public Gui(Gui parent) {
public Gui(@Nullable Gui parent) {
this.parent = parent;
}
@ -82,17 +84,18 @@ public class Gui {
this.rows = Math.max(1, Math.min(6, rows));
}
public Gui(int rows, Gui parent) {
public Gui(int rows, @Nullable Gui parent) {
this.parent = parent;
this.rows = Math.max(1, Math.min(6, rows));
}
@NotNull
public List<Player> getPlayers() {
return inventory == null ? Collections.EMPTY_LIST
: inventory.getViewers().stream()
.filter(e -> e instanceof Player)
.map(e -> (Player) e)
.collect(Collectors.toList());
.filter(e -> e instanceof Player)
.map(e -> (Player) e)
.collect(Collectors.toList());
}
public boolean isOpen() {
@ -139,7 +142,8 @@ public class Gui {
}
/**
* Close the GUI without calling onClose() and without opening any parent GUIs
* Close the GUI without calling onClose() and without opening any parent
* GUIs
*/
public void exit() {
allowClose = true;
@ -151,21 +155,25 @@ public class Gui {
.forEach(Player::closeInventory);
}
@NotNull
public GuiType getType() {
return inventoryType;
}
@NotNull
public Gui setUnlocked(int cell) {
unlockedCells.put(cell, true);
return this;
}
@NotNull
public Gui setUnlocked(int row, int col) {
final int cell = col + row * 9;
unlockedCells.put(cell, true);
return this;
}
@NotNull
public Gui setUnlockedRange(int cellFirst, int cellLast) {
for (int cell = cellFirst; cell <= cellLast; ++cell) {
unlockedCells.put(cell, true);
@ -173,6 +181,7 @@ public class Gui {
return this;
}
@NotNull
public Gui setUnlockedRange(int cellRowFirst, int cellColFirst, int cellRowLast, int cellColLast) {
final int last = cellColLast + cellRowLast * 9;
for (int cell = cellColFirst + cellRowFirst * 9; cell <= last; ++cell) {
@ -181,17 +190,20 @@ public class Gui {
return this;
}
@NotNull
public Gui setUnlocked(int cell, boolean open) {
unlockedCells.put(cell, open);
return this;
}
@NotNull
public Gui setUnlocked(int row, int col, boolean open) {
final int cell = col + row * 9;
unlockedCells.put(cell, open);
return this;
}
@NotNull
public Gui setTitle(String title) {
this.title = title;
return this;
@ -201,6 +213,7 @@ public class Gui {
return rows;
}
@NotNull
public Gui setRows(int rows) {
switch (inventoryType) {
case HOPPER:
@ -212,20 +225,24 @@ public class Gui {
return this;
}
public Gui setDefaultAction(Clickable action) {
@NotNull
public Gui setDefaultAction(@Nullable Clickable action) {
defaultClicker = action;
return this;
}
@NotNull
public Gui setDefaultItem(ItemStack item) {
blankItem = item;
return this;
}
@Nullable
public ItemStack getDefaultItem() {
return blankItem;
}
@Nullable
public ItemStack getItem(int cell) {
if (inventory != null && unlockedCells.getOrDefault(cell, false)) {
return inventory.getItem(cell);
@ -233,6 +250,7 @@ public class Gui {
return cellItems.get(cell);
}
@Nullable
public ItemStack getItem(int row, int col) {
final int cell = col + row * 9;
if (inventory != null && unlockedCells.getOrDefault(cell, false)) {
@ -241,7 +259,8 @@ public class Gui {
return cellItems.get(cell);
}
public Gui setItem(int cell, ItemStack item) {
@NotNull
public Gui setItem(int cell, @Nullable ItemStack item) {
cellItems.put(cell, item);
if (inventory != null && cell >= 0 && cell < inventory.getSize()) {
inventory.setItem(cell, item);
@ -249,7 +268,8 @@ public class Gui {
return this;
}
public Gui setItem(int row, int col, ItemStack item) {
@NotNull
public Gui setItem(int row, int col, @Nullable ItemStack item) {
final int cell = col + row * 9;
cellItems.put(cell, item);
if (inventory != null && cell >= 0 && cell < inventory.getSize()) {
@ -258,6 +278,7 @@ public class Gui {
return this;
}
@NotNull
public Gui highlightItem(int cell) {
ItemStack item = cellItems.get(cell);
if (item != null && item.getType() != Material.AIR) {
@ -266,6 +287,7 @@ public class Gui {
return this;
}
@NotNull
public Gui highlightItem(int row, int col) {
final int cell = col + row * 9;
ItemStack item = cellItems.get(cell);
@ -275,6 +297,7 @@ public class Gui {
return this;
}
@NotNull
public Gui removeHighlight(int cell) {
ItemStack item = cellItems.get(cell);
if (item != null && item.getType() != Material.AIR) {
@ -283,6 +306,7 @@ public class Gui {
return this;
}
@NotNull
public Gui removeHighlight(int row, int col) {
final int cell = col + row * 9;
ItemStack item = cellItems.get(cell);
@ -292,11 +316,13 @@ public class Gui {
return this;
}
public Gui updateItem(int row, int col, String name, String... lore) {
@NotNull
public Gui updateItem(int row, int col, @Nullable String name, @NotNull String... lore) {
return updateItem(col + row * 9, name, lore);
}
public Gui updateItem(int cell, String name, String... lore) {
@NotNull
public Gui updateItem(int cell, @Nullable String name, @NotNull String... lore) {
ItemStack item = cellItems.get(cell);
if (item != null && item.getType() != Material.AIR) {
setItem(cell, GuiUtils.updateItem(item, name, lore));
@ -304,11 +330,13 @@ public class Gui {
return this;
}
public Gui updateItem(int row, int col, String name, List<String> lore) {
@NotNull
public Gui updateItem(int row, int col, @Nullable String name, @Nullable List<String> lore) {
return updateItem(col + row * 9, name, lore);
}
public Gui updateItem(int cell, String name, List<String> lore) {
@NotNull
public Gui updateItem(int cell, @NotNull String name, @Nullable List<String> lore) {
ItemStack item = cellItems.get(cell);
if (item != null && item.getType() != Material.AIR) {
setItem(cell, GuiUtils.updateItem(item, title, lore));
@ -316,11 +344,13 @@ public class Gui {
return this;
}
public Gui updateItem(int row, int col, ItemStack itemTo, String title, String... lore) {
@NotNull
public Gui updateItem(int row, int col, @NotNull ItemStack itemTo, @Nullable String title, @NotNull String... lore) {
return updateItem(col + row * 9, itemTo, title, lore);
}
public Gui updateItem(int cell, ItemStack itemTo, String title, String... lore) {
@NotNull
public Gui updateItem(int cell, @NotNull ItemStack itemTo, @Nullable String title, @NotNull String... lore) {
ItemStack item = cellItems.get(cell);
if (item != null && item.getType() != Material.AIR) {
setItem(cell, GuiUtils.updateItem(item, itemTo, title, lore));
@ -328,11 +358,13 @@ public class Gui {
return this;
}
public Gui updateItem(int row, int col, LegacyMaterials itemTo, String title, String... lore) {
@NotNull
public Gui updateItem(int row, int col, @NotNull LegacyMaterials itemTo, @Nullable String title, @NotNull String... lore) {
return updateItem(col + row * 9, itemTo, title, lore);
}
public Gui updateItem(int cell, LegacyMaterials itemTo, String title, String... lore) {
@NotNull
public Gui updateItem(int cell, @NotNull LegacyMaterials itemTo, @Nullable String title, @Nullable String... lore) {
ItemStack item = cellItems.get(cell);
if (item != null && item.getType() != Material.AIR) {
setItem(cell, GuiUtils.updateItem(item, itemTo, title, lore));
@ -340,11 +372,13 @@ public class Gui {
return this;
}
public Gui updateItem(int row, int col, ItemStack itemTo, String title, List<String> lore) {
@NotNull
public Gui updateItem(int row, int col, @NotNull ItemStack itemTo, @Nullable String title, @Nullable List<String> lore) {
return updateItem(col + row * 9, itemTo, title, lore);
}
public Gui updateItem(int cell, ItemStack itemTo, String title, List<String> lore) {
@NotNull
public Gui updateItem(int cell, @NotNull ItemStack itemTo, @Nullable String title, @Nullable List<String> lore) {
ItemStack item = cellItems.get(cell);
if (item != null && item.getType() != Material.AIR) {
setItem(cell, GuiUtils.updateItem(item, itemTo, title, lore));
@ -352,11 +386,13 @@ public class Gui {
return this;
}
public Gui updateItem(int row, int col, LegacyMaterials itemTo, String title, List<String> lore) {
@NotNull
public Gui updateItem(int row, int col, @NotNull LegacyMaterials itemTo, @Nullable String title, @Nullable List<String> lore) {
return updateItem(col + row * 9, itemTo, title, lore);
}
public Gui updateItem(int cell, LegacyMaterials itemTo, String title, List<String> lore) {
@NotNull
public Gui updateItem(int cell, @NotNull LegacyMaterials itemTo, @Nullable String title, @Nullable List<String> lore) {
ItemStack item = cellItems.get(cell);
if (item != null && item.getType() != Material.AIR) {
setItem(cell, GuiUtils.updateItem(item, itemTo, title, lore));
@ -364,34 +400,40 @@ public class Gui {
return this;
}
public Gui setAction(int cell, Clickable action) {
@NotNull
public Gui setAction(int cell, @Nullable Clickable action) {
setConditional(cell, null, action);
return this;
}
public Gui setAction(int row, int col, Clickable action) {
@NotNull
public Gui setAction(int row, int col, @Nullable Clickable action) {
setConditional(col + row * 9, null, action);
return this;
}
public Gui setAction(int cell, ClickType type, Clickable action) {
@NotNull
public Gui setAction(int cell, @Nullable ClickType type, @Nullable Clickable action) {
setConditional(cell, type, action);
return this;
}
public Gui setAction(int row, int col, ClickType type, Clickable action) {
@NotNull
public Gui setAction(int row, int col, @Nullable ClickType type, @Nullable Clickable action) {
setConditional(col + row * 9, type, action);
return this;
}
public Gui setActionForRange(int cellFirst, int cellLast, Clickable action) {
@NotNull
public Gui setActionForRange(int cellFirst, int cellLast, @Nullable Clickable action) {
for (int cell = cellFirst; cell <= cellLast; ++cell) {
setConditional(cell, null, action);
}
return this;
}
public Gui setActionForRange(int cellRowFirst, int cellColFirst, int cellRowLast, int cellColLast, Clickable action) {
@NotNull
public Gui setActionForRange(int cellRowFirst, int cellColFirst, int cellRowLast, int cellColLast, @Nullable Clickable action) {
final int last = cellColLast + cellRowLast * 9;
for (int cell = cellColFirst + cellRowFirst * 9; cell <= last; ++cell) {
setConditional(cell, null, action);
@ -399,14 +441,16 @@ public class Gui {
return this;
}
public Gui setActionForRange(int cellFirst, int cellLast, ClickType type, Clickable action) {
@NotNull
public Gui setActionForRange(int cellFirst, int cellLast, @Nullable ClickType type, @Nullable Clickable action) {
for (int cell = cellFirst; cell <= cellLast; ++cell) {
setConditional(cell, type, action);
}
return this;
}
public Gui setActionForRange(int cellRowFirst, int cellColFirst, int cellRowLast, int cellColLast, ClickType type, Clickable action) {
@NotNull
public Gui setActionForRange(int cellRowFirst, int cellColFirst, int cellRowLast, int cellColLast, @Nullable ClickType type, @Nullable Clickable action) {
final int last = cellColLast + cellRowLast * 9;
for (int cell = cellColFirst + cellRowFirst * 9; cell <= last; ++cell) {
setConditional(cell, type, action);
@ -414,90 +458,128 @@ public class Gui {
return this;
}
@NotNull
public Gui clearActions(int cell) {
conditionalButtons.remove(cell);
return this;
}
@NotNull
public Gui clearActions(int row, int col) {
final int cell = col + row * 9;
conditionalButtons.remove(cell);
return this;
}
public Gui setButton(int cell, ItemStack item, Clickable action) {
@NotNull
public Gui setButton(int cell, ItemStack item, @Nullable Clickable action) {
setItem(cell, item);
setConditional(cell, null, action);
return this;
}
public Gui setButton(int row, int col, ItemStack item, Clickable action) {
@NotNull
public Gui setButton(int row, int col, @Nullable ItemStack item, @Nullable Clickable action) {
final int cell = col + row * 9;
setItem(cell, item);
setConditional(cell, null, action);
return this;
}
public Gui setButton(int cell, ItemStack item, ClickType type, Clickable action) {
@NotNull
public Gui setButton(int cell, @Nullable ItemStack item, @Nullable ClickType type, @Nullable Clickable action) {
setItem(cell, item);
setConditional(cell, type, action);
return this;
}
public Gui setButton(int row, int col, ItemStack item, ClickType type, Clickable action) {
@NotNull
public Gui setButton(int row, int col, @Nullable ItemStack item, @Nullable ClickType type, @Nullable Clickable action) {
final int cell = col + row * 9;
setItem(cell, item);
setConditional(cell, type, action);
return this;
}
protected void setConditional(int cell, ClickType type, Clickable action) {
protected void setConditional(int cell, @Nullable ClickType type, @Nullable Clickable action) {
Map<ClickType, Clickable> conditionals = conditionalButtons.get(cell);
if (action != null) {
if (conditionals == null) {
conditionalButtons.put(cell, conditionals = new HashMap());
}
conditionals.put(type, action);
if (conditionals == null) {
conditionalButtons.put(cell, conditionals = new HashMap());
}
conditionals.put(type, action);
}
public Gui setOnOpen(Openable action) {
@NotNull
public Gui setOnOpen(@Nullable Openable action) {
opener = action;
return this;
}
public Gui setOnClose(Closable action) {
@NotNull
public Gui setOnClose(@Nullable Closable action) {
closer = action;
return this;
}
public Gui setOnDrop(Droppable action) {
@NotNull
public Gui setOnDrop(@Nullable Droppable action) {
dropper = action;
return this;
}
public Gui setOnPage(Pagable action) {
@NotNull
public Gui setOnPage(@Nullable Pagable action) {
pager = action;
return this;
}
public Gui setNextPage(int row, int col, ItemStack item) {
public Gui setNextPage(ItemStack item) {
nextPage = item;
return this;
}
public Gui setPrevPage(ItemStack item) {
prevPage = item;
return this;
}
@NotNull
public Gui setNextPage(int cell, @NotNull ItemStack item) {
nextPageIndex = cell;
if (page < pages) {
setButton(nextPageIndex, nextPage = item, ClickType.LEFT, (event) -> this.nextPage(event.manager));
}
return this;
}
@NotNull
public Gui setNextPage(int row, int col, @NotNull ItemStack item) {
nextPageIndex = col + row * 9;
if (page < pages) {
setButton(nextPageIndex, item, ClickType.LEFT, (event) -> this.nextPage(event.manager));
setButton(nextPageIndex, nextPage = item, ClickType.LEFT, (event) -> this.nextPage(event.manager));
}
return this;
}
public Gui setPrevPage(int row, int col, ItemStack item) {
@NotNull
public Gui setPrevPage(int cell, @NotNull ItemStack item) {
prevPageIndex = cell;
if (page > 1) {
setButton(prevPageIndex, prevPage = item, ClickType.LEFT, (event) -> this.prevPage(event.manager));
}
return this;
}
@NotNull
public Gui setPrevPage(int row, int col, @NotNull ItemStack item) {
prevPageIndex = col + row * 9;
if (page > 1) {
setButton(prevPageIndex, item, ClickType.LEFT, (event) -> this.prevPage(event.manager));
setButton(prevPageIndex, prevPage = item, ClickType.LEFT, (event) -> this.prevPage(event.manager));
}
return this;
}
public void nextPage(GuiManager manager) {
public void nextPage(@NotNull GuiManager manager) {
if (page < pages) {
int lastPage = page;
++page;
@ -515,7 +597,7 @@ public class Gui {
}
}
public void prevPage(GuiManager manager) {
public void prevPage(@NotNull GuiManager manager) {
if (page > 1) {
int lastPage = page;
--page;
@ -547,11 +629,13 @@ public class Gui {
}
}
protected Inventory getOrCreateInventory(GuiManager manager) {
@NotNull
protected Inventory getOrCreateInventory(@NotNull GuiManager manager) {
return inventory != null ? inventory : generateInventory(manager);
}
protected Inventory generateInventory(GuiManager manager) {
@NotNull
protected Inventory generateInventory(@NotNull GuiManager manager) {
final int cells = rows * 9;
InventoryType t = inventoryType == null ? InventoryType.CHEST : inventoryType.type;
switch (t) {
@ -573,6 +657,7 @@ public class Gui {
return inventory;
}
@Nullable
public Gui getParent() {
return parent;
}
@ -595,11 +680,11 @@ public class Gui {
return title;
}
protected boolean onClickOutside(GuiManager manager, Player player, InventoryClickEvent event) {
protected boolean onClickOutside(@NotNull GuiManager manager, @NotNull Player player, @NotNull InventoryClickEvent event) {
return dropper != null ? dropper.onDrop(new GuiDropItemEvent(manager, this, player, event)) : true;
}
protected boolean onClick(GuiManager manager, Player player, Inventory inventory, InventoryClickEvent event) {
protected boolean onClick(@NotNull GuiManager manager, @NotNull Player player, @NotNull Inventory inventory, @NotNull InventoryClickEvent event) {
final int cell = event.getSlot();
Map<ClickType, Clickable> conditionals = conditionalButtons.get(cell);
Clickable button;
@ -608,7 +693,7 @@ public class Gui {
button.onClick(new GuiClickEvent(manager, this, player, event, cell, true));
} else {
// no event for this button
if(defaultClicker != null) {
if (defaultClicker != null) {
// this is a default action, not a triggered action
defaultClicker.onClick(new GuiClickEvent(manager, this, player, event, cell, true));
}
@ -617,19 +702,19 @@ public class Gui {
return true;
}
protected boolean onClickPlayerInventory(GuiManager manager, Player player, Inventory openInv, InventoryClickEvent event) {
protected boolean onClickPlayerInventory(@NotNull GuiManager manager, @NotNull Player player, @NotNull Inventory openInv, @NotNull InventoryClickEvent event) {
// no events for this yet
return false;
}
public void onOpen(GuiManager manager, Player player) {
public void onOpen(@NotNull GuiManager manager, @NotNull Player player) {
open = true;
if (opener != null) {
opener.onOpen(new GuiOpenEvent(manager, this, player));
}
}
public void onClose(GuiManager manager, Player player) {
public void onClose(@NotNull GuiManager manager, @NotNull Player player) {
if (!allowClose) {
manager.showGUI(player, this);
return;

View File

@ -26,7 +26,7 @@ public class SimplePagedGui extends Gui {
private int rowsPerPage, maxCellSlot;
protected ItemStack headerBackItem;
protected ItemStack footerBackItem;
final int nextPageIndex = -4, prevPageIndex = -6;
final int nextPageIndex = 4, prevPageIndex = 6;
public SimplePagedGui() {
this(null);
@ -62,16 +62,6 @@ public class SimplePagedGui extends Gui {
return this;
}
public SimplePagedGui setNextPage(ItemStack item) {
nextPage = item;
return this;
}
public SimplePagedGui setPrevPage(ItemStack item) {
prevPage = item;
return this;
}
@Override
public SimplePagedGui setItem(int row, int col, ItemStack item) {
return setItem(col + row * 9, item);
@ -80,7 +70,7 @@ public class SimplePagedGui extends Gui {
@Override
public SimplePagedGui setItem(int cell, ItemStack item) {
// set the cell relative to the current page
int cellIndex = page == 1 || (useHeader && cell < 9) ? cell : (cell + (page - 1) * (rowsPerPage * 9));
int cellIndex = cell < 0 ? cell : (page == 1 || (useHeader && cell < 9) ? cell : (cell + (page - 1) * (rowsPerPage * 9)));
cellItems.put(cellIndex, item);
if (open && cell >= 0 && cell < inventory.getSize()) {
@ -120,20 +110,20 @@ public class SimplePagedGui extends Gui {
@Override
protected void updatePageNavigation() {
if (page > 1) {
inventory.setItem((rows * 9) - 6, prevPage);
this.setButton(prevPageIndex, prevPage, ClickType.LEFT, (event) -> this.prevPage(event.manager));
inventory.setItem(inventory.getSize() - prevPageIndex, prevPage);
this.setButton(-prevPageIndex, prevPage, ClickType.LEFT, (event) -> this.prevPage(event.manager));
} else {
inventory.setItem((rows * 9) - 6, footerBackItem != null ? footerBackItem : blankItem);
this.setItem(prevPageIndex, null);
this.clearActions(prevPageIndex);
inventory.setItem(inventory.getSize() - prevPageIndex, footerBackItem != null ? footerBackItem : blankItem);
this.setItem(-prevPageIndex, null);
this.clearActions(-prevPageIndex);
}
if (pages > 1 && page != pages) {
inventory.setItem((rows * 9) - 4, nextPage);
this.setButton(nextPageIndex, nextPage, ClickType.LEFT, (event) -> this.nextPage(event.manager));
inventory.setItem(inventory.getSize() - nextPageIndex, nextPage);
this.setButton(-nextPageIndex, nextPage, ClickType.LEFT, (event) -> this.nextPage(event.manager));
} else {
inventory.setItem((rows * 9) - 4, footerBackItem != null ? footerBackItem : blankItem);
this.setItem(nextPageIndex, null);
this.clearActions(nextPageIndex);
inventory.setItem(inventory.getSize() - nextPageIndex, footerBackItem != null ? footerBackItem : blankItem);
this.setItem(-nextPageIndex, null);
this.clearActions(-nextPageIndex);
}
}

View File

@ -22,6 +22,16 @@ public class EntityStackerManager {
return manager;
}
/**
* Check to see if there is a default stacker hook loaded. <br />
* NOTE: using a default stacker assumes that this library is shaded
*
* @return returns false if there are no supported plugins
*/
public static boolean isEnabled() {
return manager.isEnabled();
}
/**
* Grab the default hologram plugin. <br />
* NOTE: using a default hologram assumes that this library is shaded

View File

@ -16,9 +16,11 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Stream;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
@ -28,11 +30,9 @@ import org.bukkit.inventory.meta.SkullMeta;
public class ItemUtils {
static boolean check_compatibility = false;
static boolean can_getI18NDisplayName = true;
static void init() {
check_compatibility = true;
static {
try {
ItemStack.class.getMethod("getI18NDisplayName");
} catch (NoSuchMethodException | SecurityException ex) {
@ -40,6 +40,34 @@ public class ItemUtils {
}
}
public static String getItemName(ItemStack it) {
if (it == null) {
return null;
} else if (can_getI18NDisplayName) {
return it.getI18NDisplayName();
} else {
return itemName(it.getType());
}
}
static String itemName(Material mat) {
String matName = mat.name().replace("_", " ");
StringBuilder titleCase = new StringBuilder(matName.length());
Stream.of(matName.split(" ")).forEach(s -> {
s = s.toLowerCase();
if (s.equals("of")) {
titleCase.append(s).append(" ");
} else {
char[] str = s.toCharArray();
str[0] = Character.toUpperCase(str[0]);
titleCase.append(new String(str)).append(" ");
}
});
return titleCase.toString().trim();
}
/**
* Clone of org.bukkit.inventory.ItemStack.asQuantity, since it is a paper-only function
*
@ -187,38 +215,34 @@ public class ItemUtils {
return item;
}
public static String getItemName(ItemStack it) {
if (!check_compatibility) {
init();
}
if (it == null) {
return null;
} else if (can_getI18NDisplayName) {
return it.getI18NDisplayName();
} else {
return itemName(it.getType());
}
}
private static Class mc_Item = NMSUtils.getNMSClass("Item");
private static Method mc_Item_getItem;
private static Field mc_Item_maxStackSize;
static String itemName(Material mat) {
String matName = mat.name().replace("_", " ");
StringBuilder titleCase = new StringBuilder(matName.length());
static {
if(mc_ItemStack != null) {
try {
mc_Item_getItem = mc_ItemStack.getDeclaredMethod("getItem");
mc_Item_maxStackSize = mc_Item.getDeclaredField("maxStackSize");
mc_Item_maxStackSize.setAccessible(true);
} catch (Exception ex) {
}
}
}
Stream.of(matName.split(" ")).forEach(s -> {
s = s.toLowerCase();
if (s.equals("of")) {
titleCase.append(s).append(" ");
} else {
char[] str = s.toCharArray();
str[0] = Character.toUpperCase(str[0]);
titleCase.append(new String(str)).append(" ");
}
});
public static ItemStack setMaxStack(ItemStack item, int max) {
if (item != null && mc_Item_maxStackSize != null) {
try {
Object objItemStack = mc_Item_getItem.invoke(cb_CraftItemStack_asNMSCopy.invoke(null, item));
mc_Item_maxStackSize.set(objItemStack, max);
} catch (ReflectiveOperationException e) {
Bukkit.getLogger().log(Level.SEVERE, "Failed to set max stack size on item " + item, e);
}
}
return item;
}
return titleCase.toString().trim();
}
public static ItemStack getPlayerSkull(OfflinePlayer player) {
public static ItemStack getPlayerSkull(OfflinePlayer player) {
ItemStack head = LegacyMaterials.PLAYER_HEAD.getItem();
if (ServerVersion.isServerVersionBelow(ServerVersion.V1_8)) {
return head;
@ -273,6 +297,40 @@ public class ItemUtils {
}
}
/**
* Use up whatever item the player is holding in their main hand
*
* @param player player to grab item from
*/
public static void takeActiveItem(Player player) {
takeActiveItem(player, 1);
}
/**
* Use up whatever item the player is holding in their main hand
*
* @param player player to grab item from
* @param amount number of items to use up
*/
public static void takeActiveItem(Player player, int amount) {
if (player.getGameMode() == GameMode.CREATIVE) return;
ItemStack item = player.getInventory().getItemInHand();
int result = item.getAmount() - amount;
item.setAmount(result);
player.setItemInHand(result > 0 ? item : null);
}
/**
* Quickly check to see if the two items use the same material. <br />
* NOTE: Does not check meta data; only checks the item material.
*
* @param is1 first item to compare
* @param is2 item to compare against
* @return true if both items are of the same material
*/
public static boolean isSimilarMaterial(ItemStack is1, ItemStack is2) {
LegacyMaterials mat1 = LegacyMaterials.getMaterial(is1);
return mat1 != null && mat1 == LegacyMaterials.getMaterial(is2);

View File

@ -26,14 +26,51 @@ public class TextUtils {
return ChatColor.translateAlternateColorCodes('&', text);
}
/**
* Convert a string to an invisible colored string that's lore-safe <br />
* (Safe to use as lore) <br />
* Note: Do not use semi-colons in this string, or they will be lost when decoding!
*
* @param s string to convert
* @return encoded string
*/
public static String convertToInvisibleLoreString(String s) {
if (s == null || s.equals(""))
return "";
StringBuilder hidden = new StringBuilder();
for (char c : s.toCharArray()) hidden.append(ChatColor.COLOR_CHAR).append(';').append(ChatColor.COLOR_CHAR).append(c);
return hidden.toString();
}
/**
* Convert a string to an invisible colored string <br />
* (Not safe to use as lore) <br />
* Note: Do not use semi-colons in this string, or they will be lost when decoding!
*
* @param s string to convert
* @return encoded string
*/
public static String convertToInvisibleString(String s) {
if (s == null || s.equals(""))
return "";
StringBuilder hidden = new StringBuilder();
for (char c : s.toCharArray()) hidden.append(ChatColor.COLOR_CHAR + "").append(c);
for (char c : s.toCharArray()) hidden.append(ChatColor.COLOR_CHAR).append(c);
return hidden.toString();
}
/**
* Removes color markers used to encode strings as invisible text
*
* @param s encoded string
* @return string with color markers removed
*/
public static String convertFromInvisibleString(String s) {
if (s == null || s.equals("")) {
return "";
}
return s.replaceAll(ChatColor.COLOR_CHAR + ";" + ChatColor.COLOR_CHAR + "|" + ChatColor.COLOR_CHAR, "");
}
protected static final List<Charset> supportedCharsets = new ArrayList();
static {