Merge branch 'development' into 'master'

Development

See merge request Songoda/songodaupdater!2
This commit is contained in:
Jacob Scott 2019-09-02 19:11:38 +00:00
commit dfb5ea1283
14 changed files with 476 additions and 24 deletions

View File

@ -86,12 +86,14 @@ public abstract class SongodaPlugin extends JavaPlugin {
locale = Locale.loadDefaultLocale(this, "en_US");
// plugin setup
onPluginEnable();
if(emergencyStop) {
console.sendMessage(ChatColor.RED + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
return;
}
// Start Metrics
Metrics.start(this);
} catch (Throwable t) {
getLogger().log(Level.SEVERE, "Unexpected error while loading " + getDescription().getName() + ": Disabling plugin!", t);
emergencyStop = true;
setEnabled(false);
console.sendMessage(ChatColor.RED + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
return;
}
@ -99,6 +101,11 @@ public abstract class SongodaPlugin extends JavaPlugin {
console.sendMessage(ChatColor.GREEN + "=============================");
}
protected void emergencyStop() {
emergencyStop = true;
Bukkit.getPluginManager().disablePlugin(this);
}
@Override
public final void onDisable() {
if (emergencyStop) {

View File

@ -900,7 +900,7 @@ public enum LegacyMaterials {
STONE_PRESSURE_PLATE("STONE_PLATE"),
STONE_SHOVEL("STONE_SPADE"),
STONE_SLAB("STEP", (byte) 0),
STONE_STAIRS(""),
STONE_STAIRS(),
STONE_SWORD,
STRAY_SPAWN_EGG("MONSTER_EGG", (byte) 6),
STRING,
@ -920,7 +920,7 @@ public enum LegacyMaterials {
STRUCTURE_VOID,
SUGAR,
SUGAR_CANE,
SUNFLOWER("LONG_GRASS", (byte) 0),
SUNFLOWER("DOUBLE_PLANT", (byte) 0),
SUSPICIOUS_STEW,
SWEET_BERRIES,
SWEET_BERRY_BUSH,

View File

@ -1,5 +1,6 @@
package com.songoda.core.compatibility;
import java.util.stream.Stream;
import org.bukkit.Color;
import org.bukkit.Effect;
import org.bukkit.Location;
@ -7,7 +8,165 @@ import org.bukkit.Particle;
import org.bukkit.block.BlockFace;
public class ParticleHandler {
public static enum ParticleType {
EXPLOSION_NORMAL(),
EXPLOSION_LARGE,
EXPLOSION_HUGE,
FIREWORKS_SPARK,
WATER_BUBBLE,
WATER_SPLASH,
WATER_WAKE,
SUSPENDED,
SUSPENDED_DEPTH,
CRIT,
CRIT_MAGIC,
SMOKE_NORMAL,
SMOKE_LARGE,
SPELL,
SPELL_INSTANT,
SPELL_MOB,
SPELL_MOB_AMBIENT,
SPELL_WITCH,
DRIP_WATER,
DRIP_LAVA,
VILLAGER_ANGRY,
VILLAGER_HAPPY,
TOWN_AURA,
NOTE,
PORTAL,
ENCHANTMENT_TABLE,
FLAME,
LAVA,
CLOUD,
REDSTONE(), //DustOptions
SNOWBALL,
SNOW_SHOVEL,
SLIME,
HEART,
BARRIER,
ITEM_CRACK(), // ItemStack
BLOCK_CRACK(), // BlockData
BLOCK_DUST(), // BlockData
WATER_DROP,
// 1.9-1.12 included ITEM_TAKE
MOB_APPEARANCE,
DRAGON_BREATH,
END_ROD,
DAMAGE_INDICATOR,
SWEEP_ATTACK,
/// End 1.9 particles ///
FALLING_DUST(ServerVersion.V1_10, "BLOCK_DUST"), // BlockData
/// End 1.10 ///
TOTEM(ServerVersion.V1_11, "VILLAGER_HAPPY"),
SPIT(ServerVersion.V1_11, "REDSTONE"),
/// End 1.11-1.12 ///
SQUID_INK(ServerVersion.V1_13, "CRIT"),
BUBBLE_POP(ServerVersion.V1_13, "CRIT"),
CURRENT_DOWN(ServerVersion.V1_13, "CRIT"),
BUBBLE_COLUMN_UP(ServerVersion.V1_13, "CRIT"),
NAUTILUS(ServerVersion.V1_13, "END_ROD"),
DOLPHIN(ServerVersion.V1_13, "TOWN_AURA"),
/// End 1.13 ///
SNEEZE(ServerVersion.V1_14, "REDSTONE"),
CAMPFIRE_COSY_SMOKE(ServerVersion.V1_14, "SMOKE_NORMAL"),
CAMPFIRE_SIGNAL_SMOKE(ServerVersion.V1_14, "SMOKE_LARGE"),
COMPOSTER(ServerVersion.V1_14, "CRIT"),
FLASH(ServerVersion.V1_14, "EXPLOSION_NORMAL"), // idk
FALLING_LAVA(ServerVersion.V1_14, "DRIP_LAVA"),
LANDING_LAVA(ServerVersion.V1_14, "LAVA"),
FALLING_WATER(ServerVersion.V1_14, "DRIP_WATER"),
/// End 1.14 ///
;
final boolean compatibilityMode;
final LegacyParticleEffects.Type compatibleEffect;
final Object particle;
private ParticleType() {
if (ServerVersion.isServerVersionAtOrBelow(ServerVersion.V1_8)) {
this.compatibilityMode = true;
this.particle = null;
this.compatibleEffect = LegacyParticleEffects.Type.valueOf(name());
} else {
this.compatibleEffect = null;
// does this particle exist in our version?
Particle check = Stream.of(Particle.values()).filter(p -> p.name().equals(name())).findFirst().orElse(null);
if (check != null) {
this.particle = check;
this.compatibilityMode = false;
} else {
// this shouldn't happen, really
this.particle = Particle.END_ROD;
this.compatibilityMode = true;
}
}
}
private ParticleType(ServerVersion minVersion, String compatible) {
// Particle class doesn't exist in 1.8
if (ServerVersion.isServerVersionAtOrBelow(ServerVersion.V1_8)) {
this.compatibilityMode = true;
this.compatibleEffect = LegacyParticleEffects.Type.valueOf(compatible);
this.particle = null;
} else if (ServerVersion.isServerVersionBelow(minVersion)) {
this.compatibilityMode = true;
this.compatibleEffect = null;
this.particle = Particle.valueOf(compatible);
} else {
this.compatibleEffect = null;
// does this particle exist in our version?
Particle check = Stream.of(Particle.values()).filter(p -> p.name().equals(name())).findFirst().orElse(null);
if (check != null) {
this.particle = check;
this.compatibilityMode = false;
} else {
// this shouldn't happen, really
this.particle = Particle.END_ROD;
this.compatibilityMode = true;
}
}
}
}
public static void spawnParticles(ParticleType type, Location location) {
if (ServerVersion.isServerVersionAtOrBelow(ServerVersion.V1_8)) {
LegacyParticleEffects.createParticle(location, type.compatibleEffect);
} else {
location.getWorld().spawnParticle((Particle) type.particle, location, 0);
}
}
public static void spawnParticles(ParticleType type, Location location, int count) {
if (ServerVersion.isServerVersionAtOrBelow(ServerVersion.V1_8)) {
LegacyParticleEffects.createParticle(location, type.compatibleEffect);
for (int i = 0; i < count; i++) {
float xx = (float) (1 * (Math.random() - Math.random()));
float yy = (float) (1 * (Math.random() - Math.random()));
float zz = (float) (1 * (Math.random() - Math.random()));
Location at = location.clone().add(xx, yy, zz);
LegacyParticleEffects.createParticle(at, LegacyParticleEffects.Type.REDSTONE);
}
} else {
location.getWorld().spawnParticle((Particle) type.particle, location, count);
}
}
public static void spawnParticles(ParticleType type, Location location, int count, double offsetX, double offsetY, double offsetZ) {
if (ServerVersion.isServerVersionAtOrBelow(ServerVersion.V1_8)) {
LegacyParticleEffects.createParticle(location, type.compatibleEffect);
for (int i = 0; i < count; i++) {
float xx = (float) (offsetX * (Math.random() - Math.random()));
float yy = (float) (offsetY * (Math.random() - Math.random()));
float zz = (float) (offsetZ * (Math.random() - Math.random()));
Location at = location.clone().add(xx, yy, zz);
LegacyParticleEffects.createParticle(at, LegacyParticleEffects.Type.REDSTONE);
}
} else {
location.getWorld().spawnParticle((Particle) type.particle, location, count, offsetX, offsetY, offsetZ);
}
}
public static void redstoneParticles(Location location, int red, int green, int blue) {
redstoneParticles(location, red, green, blue, 1F, 1, 0);
}

View File

@ -49,10 +49,18 @@ public enum ServerVersion {
return ArrayUtils.contains(versions, serverVersion);
}
public static boolean isServerVersionAbove(ServerVersion version) {
return serverVersion.ordinal() > version.ordinal();
}
public static boolean isServerVersionAtLeast(ServerVersion version) {
return serverVersion.ordinal() >= version.ordinal();
}
public static boolean isServerVersionAtOrBelow(ServerVersion version) {
return serverVersion.ordinal() <= version.ordinal();
}
public static boolean isServerVersionBelow(ServerVersion version) {
return serverVersion.ordinal() < version.ordinal();
}

View File

@ -1,5 +1,8 @@
package com.songoda.core.configuration;
import com.songoda.core.compatibility.LegacyMaterials;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
@ -7,6 +10,8 @@ import org.bukkit.configuration.Configuration;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.FileConfiguration;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class ConfigFileConfigurationAdapter extends FileConfiguration {
@ -116,4 +121,153 @@ public class ConfigFileConfigurationAdapter extends FileConfiguration {
return config.createSection(path, map);
}
// Other non-FileConfiguration methods
@NotNull
public ConfigSection createDefaultSection(@NotNull String path) {
return config.createDefaultSection(path);
}
@NotNull
public ConfigSection createDefaultSection(@NotNull String path, String... comment) {
return config.createDefaultSection(path, comment);
}
@NotNull
public ConfigSection createDefaultSection(@NotNull String path, ConfigFormattingRules.CommentStyle commentStyle, String... comment) {
return config.createDefaultSection(path, commentStyle, comment);
}
@NotNull
public ConfigSection setComment(@NotNull String path, @Nullable ConfigFormattingRules.CommentStyle commentStyle, String... lines) {
return config.setComment(path, commentStyle, lines);
}
@NotNull
public ConfigSection setComment(@NotNull String path, @Nullable ConfigFormattingRules.CommentStyle commentStyle, @Nullable List<String> lines) {
return config.setComment(path, commentStyle, lines);
}
@NotNull
public ConfigSection setDefaultComment(@NotNull String path, String... lines) {
return config.setDefaultComment(path, lines);
}
@NotNull
public ConfigSection setDefaultComment(@NotNull String path, @Nullable List<String> lines) {
return config.setDefaultComment(path, lines);
}
@NotNull
public ConfigSection setDefaultComment(@NotNull String path, ConfigFormattingRules.CommentStyle commentStyle, String... lines) {
return config.setDefaultComment(path, commentStyle, lines);
}
@NotNull
public ConfigSection setDefaultComment(@NotNull String path, ConfigFormattingRules.CommentStyle commentStyle, @Nullable List<String> lines) {
return config.setDefaultComment(path, commentStyle, lines);
}
@Nullable
public Comment getComment(@NotNull String path) {
return config.getComment(path);
}
@Nullable
public String getCommentString(@NotNull String path) {
return config.getCommentString(path);
}
@NotNull
public List<ConfigSection> getSections(String path) {
return config.getSections(path);
}
@NotNull
public ConfigSection set(@NotNull String path, @Nullable Object value, String... comment) {
return config.set(path, value, comment);
}
@NotNull
public ConfigSection set(@NotNull String path, @Nullable Object value, List<String> comment) {
return config.set(path, value, comment);
}
@NotNull
public ConfigSection set(@NotNull String path, @Nullable Object value, @Nullable ConfigFormattingRules.CommentStyle commentStyle, String... comment) {
return config.set(path, value, commentStyle, comment);
}
@NotNull
public ConfigSection set(@NotNull String path, @Nullable Object value, @Nullable ConfigFormattingRules.CommentStyle commentStyle, List<String> comment) {
return config.set(path, value, commentStyle, comment);
}
@NotNull
public ConfigSection setDefault(@NotNull String path, @Nullable Object value) {
return config.setDefault(path, value);
}
@NotNull
public ConfigSection setDefault(@NotNull String path, @Nullable Object value, String... comment) {
return config.setDefault(path, value, comment);
}
@NotNull
public ConfigSection setDefault(@NotNull String path, @Nullable Object value, List<String> comment) {
return config.setDefault(path, value, comment);
}
@NotNull
public ConfigSection setDefault(@NotNull String path, @Nullable Object value, ConfigFormattingRules.CommentStyle commentStyle, String... comment) {
return config.setDefault(path, value, commentStyle, comment);
}
@NotNull
public ConfigSection setDefault(@NotNull String path, @Nullable Object value, ConfigFormattingRules.CommentStyle commentStyle, List<String> comment) {
return config.setDefault(path, value, commentStyle, comment);
}
@NotNull
public ConfigSection createSection(@NotNull String path, String... comment) {
return config.createSection(path, comment);
}
@NotNull
public ConfigSection createSection(@NotNull String path, @Nullable List<String> comment) {
return config.createSection(path, comment);
}
@NotNull
public ConfigSection createSection(@NotNull String path, @Nullable ConfigFormattingRules.CommentStyle commentStyle, String... comment) {
return config.createSection(path, commentStyle, comment);
}
@NotNull
public ConfigSection createSection(@NotNull String path, @Nullable ConfigFormattingRules.CommentStyle commentStyle, @Nullable List<String> comment) {
return config.createSection(path, commentStyle, comment);
}
public char getChar(@NotNull String path) {
return config.getChar(path);
}
public char getChar(@NotNull String path, char def) {
return config.getChar(path, def);
}
@Nullable
public LegacyMaterials getMaterial(@NotNull String path) {
return config.getMaterial(path);
}
@Nullable
public LegacyMaterials getMaterial(@NotNull String path, @Nullable LegacyMaterials def) {
return config.getMaterial(path, def);
}
@NotNull
public ConfigSection getOrCreateConfigurationSection(@NotNull String path) {
return config.getOrCreateConfigurationSection(path);
}
}

View File

@ -629,6 +629,7 @@ public class ConfigSection extends MemoryConfiguration {
return result instanceof ConfigSection ? (ConfigSection) result : null;
}
@NotNull
public ConfigSection getOrCreateConfigurationSection(@NotNull String path) {
Object result = get(path);
return result instanceof ConfigSection ? (ConfigSection) result : createSection(path);

View File

@ -60,7 +60,7 @@ public class PluginConfigGui extends SimplePagedGui {
try {
// can we also grab extra config from this mysterious plugin?
Object more = plugin.getClass().getDeclaredMethod("getExtraConfig").invoke(plugin);
if (more instanceof List && !((List) more).isEmpty()) {
if (more != null && more instanceof List && !((List) more).isEmpty()) {
try {
// if we have the getExtraConfig function, we should also be able to get the file
Method method_Config_getFile = ((List) more).get(0).getClass().getDeclaredMethod("getFile");

View File

@ -5,6 +5,7 @@ import com.songoda.core.gui.events.GuiClickEvent;
import com.songoda.core.gui.events.GuiCloseEvent;
import com.songoda.core.gui.events.GuiDropItemEvent;
import com.songoda.core.gui.events.GuiOpenEvent;
import com.songoda.core.gui.events.GuiPageEvent;
import com.songoda.core.gui.methods.Pagable;
import com.songoda.core.gui.methods.Clickable;
import com.songoda.core.gui.methods.Droppable;
@ -51,6 +52,7 @@ public class Gui {
protected static ItemStack AIR = new ItemStack(Material.AIR);
protected boolean open = false;
protected Clickable defaultClicker = null;
protected Openable opener = null;
protected Closable closer = null;
protected Droppable dropper = null;
@ -210,6 +212,11 @@ public class Gui {
return this;
}
public Gui setDefaultAction(Clickable action) {
defaultClicker = action;
return this;
}
public Gui setDefaultItem(ItemStack item) {
blankItem = item;
return this;
@ -219,6 +226,21 @@ public class Gui {
return blankItem;
}
public ItemStack getItem(int cell) {
if (inventory != null && unlockedCells.getOrDefault(cell, false)) {
return inventory.getItem(cell);
}
return cellItems.get(cell);
}
public ItemStack getItem(int row, int col) {
final int cell = col + row * 9;
if (inventory != null && unlockedCells.getOrDefault(cell, false)) {
return inventory.getItem(cell);
}
return cellItems.get(cell);
}
public Gui setItem(int cell, ItemStack item) {
cellItems.put(cell, item);
if (open && cell >= 0 && cell < inventory.getSize()) {
@ -277,7 +299,7 @@ public class Gui {
public Gui updateItem(int cell, String name, String... lore) {
ItemStack item = cellItems.get(cell);
if (item != null && item.getType() != Material.AIR) {
setItem(cell, GuiUtils.updateItem(item, title, lore));
setItem(cell, GuiUtils.updateItem(item, name, lore));
}
return this;
}
@ -462,7 +484,7 @@ public class Gui {
public Gui setNextPage(int row, int col, ItemStack item) {
nextPageIndex = col + row * 9;
if (page < pages) {
setButton(nextPageIndex, item, ClickType.LEFT, (event) -> this.nextPage());
setButton(nextPageIndex, item, ClickType.LEFT, (event) -> this.nextPage(event.manager));
}
return this;
}
@ -470,18 +492,18 @@ public class Gui {
public Gui setPrevPage(int row, int col, ItemStack item) {
prevPageIndex = col + row * 9;
if (page > 1) {
setButton(prevPageIndex, item, ClickType.LEFT, (event) -> this.prevPage());
setButton(prevPageIndex, item, ClickType.LEFT, (event) -> this.prevPage(event.manager));
}
return this;
}
public void nextPage() {
public void nextPage(GuiManager manager) {
if (page < pages) {
int lastPage = page;
++page;
// page switch events
if (pager != null) {
pager.onPageChange(this, lastPage, page);
pager.onPageChange(new GuiPageEvent(this, manager, lastPage, page));
// page markers
updatePageNavigation();
@ -493,12 +515,12 @@ public class Gui {
}
}
public void prevPage() {
public void prevPage(GuiManager manager) {
if (page > 1) {
int lastPage = page;
--page;
if (pager != null) {
pager.onPageChange(this, lastPage, page);
pager.onPageChange(new GuiPageEvent(this, manager, lastPage, page));
// page markers
updatePageNavigation();
@ -512,13 +534,13 @@ public class Gui {
protected void updatePageNavigation() {
if (page > 1) {
this.setButton(prevPageIndex, prevPage, ClickType.LEFT, (event) -> this.prevPage());
this.setButton(prevPageIndex, prevPage, ClickType.LEFT, (event) -> this.prevPage(event.manager));
} else {
this.setItem(prevPageIndex, null);
this.clearActions(prevPageIndex);
}
if (pages > 1 && page != pages) {
this.setButton(nextPageIndex, nextPage, ClickType.LEFT, (event) -> this.nextPage());
this.setButton(nextPageIndex, nextPage, ClickType.LEFT, (event) -> this.nextPage(event.manager));
} else {
this.setItem(nextPageIndex, null);
this.clearActions(nextPageIndex);
@ -586,6 +608,10 @@ public class Gui {
button.onClick(new GuiClickEvent(manager, this, player, event, cell, true));
} else {
// no event for this button
if(defaultClicker != null) {
// this is a default action, not a triggered action
defaultClicker.onClick(new GuiClickEvent(manager, this, player, event, cell, true));
}
return false;
}
return true;

View File

@ -78,7 +78,7 @@ public class GuiManager {
if(openInv != null) {
openInv.open = false;
}
Inventory inv = gui.generateInventory(this);
Inventory inv = gui.getOrCreateInventory(this);
player.openInventory(inv);
gui.onOpen(this, player);
openInventories.put(player, gui);

View File

@ -89,7 +89,7 @@ public class SimplePagedGui extends Gui {
}
@Override
public void nextPage() {
public void nextPage(GuiManager manager) {
if (page < pages) {
++page;
showPage();
@ -97,7 +97,7 @@ public class SimplePagedGui extends Gui {
}
@Override
public void prevPage() {
public void prevPage(GuiManager manager) {
if (page > 1) {
--page;
showPage();
@ -120,7 +120,7 @@ public class SimplePagedGui extends Gui {
protected void updatePageNavigation() {
if (page > 1) {
inventory.setItem((rows * 9) - 6, prevPage);
this.setButton(prevPageIndex, prevPage, ClickType.LEFT, (event) -> this.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);
@ -128,7 +128,7 @@ public class SimplePagedGui extends Gui {
}
if (pages > 1 && page != pages) {
inventory.setItem((rows * 9) - 4, nextPage);
this.setButton(nextPageIndex, nextPage, ClickType.LEFT, (event) -> this.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);

View File

@ -0,0 +1,20 @@
package com.songoda.core.gui.events;
import com.songoda.core.gui.Gui;
import com.songoda.core.gui.GuiManager;
public class GuiPageEvent {
final Gui gui;
final GuiManager manager;
final int lastPage;
final int page;
public GuiPageEvent(Gui gui, GuiManager manager, int lastPage, int page) {
this.gui = gui;
this.manager = manager;
this.lastPage = lastPage;
this.page = page;
}
}

View File

@ -1,8 +1,8 @@
package com.songoda.core.gui.methods;
import com.songoda.core.gui.Gui;
import com.songoda.core.gui.events.GuiPageEvent;
public interface Pagable {
void onPageChange(Gui gui, int lastPage, int newPage);
void onPageChange(GuiPageEvent event);
}

View File

@ -1,5 +1,6 @@
package com.songoda.core.locale;
import com.songoda.core.compatibility.ServerVersion;
import java.util.regex.Matcher;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
@ -58,8 +59,12 @@ public class Message {
* @param sender command sender to send the message to
*/
public void sendTitle(CommandSender sender) {
if(sender instanceof Player) {
((Player) sender).sendTitle("", this.getMessage(), 10, 20, 10);
if (sender instanceof Player) {
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_11)) {
((Player) sender).sendTitle("", getMessage(), 10, 30, 10);
} else {
((Player) sender).sendTitle("", getMessage());
}
} else {
sender.sendMessage(this.getMessage());
}

View File

@ -0,0 +1,72 @@
package com.songoda.core.utils;
import org.bukkit.inventory.ItemStack;
import org.bukkit.util.io.BukkitObjectInputStream;
import org.bukkit.util.io.BukkitObjectOutputStream;
import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.List;
/**
* Class based off of https://gist.github.com/graywolf336/8153678
*/
public class ItemSerializer {
/**
* A method to serialize an {@link ItemStack} list to Base64 String.
*
* @param items to turn into a Base64 String.
* @return Base64 string of the items.
*/
public static String toBase64(List<ItemStack> items) {
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
BukkitObjectOutputStream dataOutput = new BukkitObjectOutputStream(outputStream);
// Write the size of the inventory
dataOutput.writeInt(items.size());
// Save every element in the list
for (ItemStack item : items)
dataOutput.writeObject(item);
// Serialize that array
dataOutput.close();
return Base64Coder.encodeLines(outputStream.toByteArray());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* Gets a list of ItemStacks from Base64 string.
*
* @param data Base64 string to convert to ItemStack list.
* @return ItemStack array created from the Base64 string.
*/
public static List<ItemStack> fromBase64(String data) {
try {
ByteArrayInputStream inputStream = new ByteArrayInputStream(Base64Coder.decodeLines(data));
BukkitObjectInputStream dataInput = new BukkitObjectInputStream(inputStream);
int length = dataInput.readInt();
List<ItemStack> items = new ArrayList<>();
// Read the serialized itemstack list
for (int i = 0; i < length; i++)
items.add((ItemStack) dataInput.readObject());
dataInput.close();
return items;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}