Updated to 2.0.2 (some manual changes).

This commit is contained in:
CoderMarido 2018-08-22 17:12:55 +02:00
parent 002a5e9b68
commit 1caf138d56
11 changed files with 724 additions and 697 deletions

View File

@ -1,15 +1,14 @@
package net.sothatsit.heads;
import com.mojang.authlib.GameProfile;
import net.sothatsit.blockstore.BlockStoreApi;
import net.sothatsit.heads.cache.CacheHead;
import net.sothatsit.heads.volatilecode.ItemNBT;
import net.sothatsit.heads.volatilecode.Items;
import net.sothatsit.heads.volatilecode.TextureGetter;
import net.sothatsit.heads.volatilecode.reflection.nms.BlockPosition;
import net.sothatsit.heads.volatilecode.reflection.nms.TileEntitySkull;
import net.sothatsit.heads.volatilecode.reflection.nms.World;
import org.bukkit.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.Skull;
@ -25,178 +24,185 @@ import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.SkullMeta;
import org.bukkit.plugin.RegisteredListener;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import com.mojang.authlib.GameProfile;
import net.sothatsit.blockstore.BlockStoreApi;
import net.sothatsit.heads.cache.CacheHead;
import net.sothatsit.heads.volatilecode.ItemNBT;
import net.sothatsit.heads.volatilecode.Items;
import net.sothatsit.heads.volatilecode.TextureGetter;
import net.sothatsit.heads.volatilecode.reflection.nms.BlockPosition;
import net.sothatsit.heads.volatilecode.reflection.nms.TileEntitySkull;
import net.sothatsit.heads.volatilecode.reflection.nms.World;
public class HeadNamer implements Listener {
public void registerEvents() {
Bukkit.getPluginManager().registerEvents(this, Heads.getInstance());
}
public void registerEvents() {
Bukkit.getPluginManager().registerEvents(this, Heads.getInstance());
}
private boolean shouldUseBlockStore() {
return Heads.getMainConfig().shouldUseBlockStore() && Heads.isBlockStoreAvailable();
}
private boolean shouldUseBlockStore() {
return Heads.getMainConfig().shouldUseBlockStore() && Heads.isBlockStoreAvailable();
}
private boolean isHeadsHead(ItemStack item) {
if(!Items.isSkull(item))
return false;
private boolean isHeadsHead(ItemStack item) {
if (!Items.isSkull(item))
return false;
SkullMeta meta = (SkullMeta) item.getItemMeta();
SkullMeta meta = (SkullMeta) item.getItemMeta();
return meta.hasOwner() && meta.getOwner().equals("SpigotHeadPlugin");
}
return meta.hasOwner() && meta.getOwner().equals("SpigotHeadPlugin");
}
private boolean isHeadsHead(Block block) {
BlockState state = block.getState();
if(!(state instanceof Skull))
return false;
private boolean isHeadsHead(Block block) {
BlockState state = block.getState();
if (!(state instanceof Skull))
return false;
Skull skull = (Skull) state;
Skull skull = (Skull) state;
return skull.getOwner() != null && skull.getOwner().equals("SpigotHeadPlugin");
}
return skull.getOwner() != null && skull.getOwner().equals("SpigotHeadPlugin");
}
private GameProfile getGameProfile(Block block) {
World world = new World(block.getWorld());
BlockPosition pos = new BlockPosition(block.getX(), block.getY(), block.getZ());
TileEntitySkull tile = world.getTileEntity(pos).asSkullEntity();
private GameProfile getGameProfile(Block block) {
World world = new World(block.getWorld());
BlockPosition pos = new BlockPosition(block.getX(), block.getY(), block.getZ());
TileEntitySkull tile = world.getTileEntity(pos).asSkullEntity();
return tile.getGameProfile();
}
return tile.getGameProfile();
}
private String findHeadName(Block block) {
if(Heads.getMainConfig().shouldUseCacheNames()) {
GameProfile profile = getGameProfile(block);
String texture = TextureGetter.findTexture(profile);
CacheHead head = Heads.getCache().findHeadByTexture(texture);
private String findHeadName(Block block) {
if (Heads.getMainConfig().shouldUseCacheNames()) {
GameProfile profile = getGameProfile(block);
String texture = TextureGetter.findTexture(profile);
CacheHead head = Heads.getCache().findHeadByTexture(texture);
if(head != null)
return ChatColor.GRAY + head.getName();
}
if (head != null)
return ChatColor.GRAY + head.getName();
}
return ChatColor.GRAY + Heads.getMainConfig().getDefaultHeadName();
}
return ChatColor.GRAY + Heads.getMainConfig().getDefaultHeadName();
}
@EventHandler(priority = EventPriority.MONITOR)
public void onBlockPlace(BlockPlaceEvent e) {
if(!Heads.getMainConfig().isHeadNamesEnabled() || !shouldUseBlockStore() || !isHeadsHead(e.getItemInHand()))
return;
@EventHandler(priority = EventPriority.MONITOR)
public void onBlockPlace(BlockPlaceEvent e) {
if (!Heads.getMainConfig().isHeadNamesEnabled() || !shouldUseBlockStore() || !isHeadsHead(e.getItemInHand()))
return;
ItemMeta meta = e.getItemInHand().getItemMeta();
ItemMeta meta = e.getItemInHand().getItemMeta();
if(!meta.hasDisplayName())
return;
if (!meta.hasDisplayName())
return;
BlockStoreApi.setBlockMeta(e.getBlock(), Heads.getInstance(), "name", meta.getDisplayName());
}
BlockStoreApi.setBlockMeta(e.getBlock(), Heads.getInstance(), "name", meta.getDisplayName());
}
@EventHandler(priority = EventPriority.LOWEST)
public void onBlockBreak(BlockBreakEvent e) {
if(!Heads.getMainConfig().isHeadNamesEnabled())
return;
@EventHandler(priority = EventPriority.LOWEST)
public void onBlockBreak(BlockBreakEvent e) {
if (!Heads.getMainConfig().isHeadNamesEnabled())
return;
Block block = e.getBlock();
Block block = e.getBlock();
if(e.getPlayer().getGameMode() == GameMode.CREATIVE || !isHeadsHead(block))
return;
if (e.getPlayer().getGameMode() == GameMode.CREATIVE || !isHeadsHead(block))
return;
// Stop the head item being dropped by the server
e.setCancelled(true);
// Stop the head item being dropped by the server
e.setCancelled(true);
if(shouldUseBlockStore()) {
BlockStoreApi.retrieveBlockMeta(Heads.getInstance(), block, Heads.getInstance(), "name", metaValue -> {
String newName;
if (shouldUseBlockStore()) {
BlockStoreApi.retrieveBlockMeta(Heads.getInstance(), block, Heads.getInstance(), "name", metaValue -> {
String newName;
if(metaValue instanceof String) {
newName = (String) metaValue;
} else {
newName = findHeadName(block);
}
if (metaValue instanceof String) {
newName = (String) metaValue;
} else {
newName = findHeadName(block);
}
redropRenamedSkull(block, e.getPlayer(), newName);
});
} else {
redropRenamedSkull(block, e.getPlayer(), findHeadName(block));
}
}
redropRenamedSkull(block, e.getPlayer(), newName);
});
} else {
redropRenamedSkull(block, e.getPlayer(), findHeadName(block));
}
}
private void redropRenamedSkull(Block block, Player player, String newName) {
BlockBreakEvent event = new BlockBreakEvent(block, player);
private void redropRenamedSkull(Block block, Player player, String newName) {
BlockBreakEvent event = new BlockBreakEvent(block, player);
List<RegisteredListener> listenersToCall = new ArrayList<>();
List<RegisteredListener> listenersToCall = new ArrayList<>();
for (RegisteredListener listener : BlockBreakEvent.getHandlerList().getRegisteredListeners()) {
if(!listener.getPlugin().isEnabled() || listener.getListener() instanceof HeadNamer)
continue;
for (RegisteredListener listener : BlockBreakEvent.getHandlerList().getRegisteredListeners()) {
if (!listener.getPlugin().isEnabled() || listener.getListener() instanceof HeadNamer)
continue;
listenersToCall.add(listener);
}
listenersToCall.add(listener);
}
CountdownRunnable eventResultHandler = new CountdownRunnable(listenersToCall.size(), () -> {
if(event.isCancelled())
return;
CountdownRunnable eventResultHandler = new CountdownRunnable(listenersToCall.size(), () -> {
if (event.isCancelled())
return;
GameProfile profile = getGameProfile(block);
ItemStack drop = ItemNBT.createHead(profile, newName);
GameProfile profile = getGameProfile(block);
ItemStack drop = ItemNBT.createHead(profile, newName);
Location dropLocation = block.getLocation().add(0.5, 0.5, 0.5);
Location dropLocation = block.getLocation().add(0.5, 0.5, 0.5);
block.setType(Material.AIR);
block.getWorld().dropItemNaturally(dropLocation, drop);
});
block.setType(Material.AIR);
block.getWorld().dropItemNaturally(dropLocation, drop);
});
for (RegisteredListener listener : listenersToCall) {
new BlockBreakEventCaller(listener, event, eventResultHandler).scheduleTask();
}
}
for (RegisteredListener listener : listenersToCall) {
new BlockBreakEventCaller(listener, event, eventResultHandler).scheduleTask();
}
}
private static class BlockBreakEventCaller implements Runnable {
private static class BlockBreakEventCaller implements Runnable {
private final RegisteredListener listener;
private final BlockBreakEvent event;
private final CountdownRunnable countdown;
private final RegisteredListener listener;
private final BlockBreakEvent event;
private final CountdownRunnable countdown;
public BlockBreakEventCaller(RegisteredListener listener, BlockBreakEvent event, CountdownRunnable countdown) {
this.listener = listener;
this.event = event;
this.countdown = countdown;
}
public BlockBreakEventCaller(RegisteredListener listener, BlockBreakEvent event, CountdownRunnable countdown) {
this.listener = listener;
this.event = event;
this.countdown = countdown;
}
public void scheduleTask() {
Bukkit.getScheduler().scheduleSyncDelayedTask(listener.getPlugin(), this);
}
public void scheduleTask() {
Bukkit.getScheduler().scheduleSyncDelayedTask(listener.getPlugin(), this);
}
@Override
public void run() {
try {
listener.callEvent(event);
} catch (EventException exception) {
Heads.severe("There was an exception calling BlockBreakEvent for " + listener.getPlugin().getName());
exception.printStackTrace();
} finally {
countdown.countdown();
}
}
}
@Override
public void run() {
try {
listener.callEvent(event);
} catch (EventException exception) {
Heads.severe("There was an exception calling BlockBreakEvent for " + listener.getPlugin().getName());
exception.printStackTrace();
} finally {
countdown.countdown();
}
}
}
private static class CountdownRunnable {
private static class CountdownRunnable {
private final AtomicInteger countdown;
private final Runnable runnable;
private final AtomicInteger countdown;
private final Runnable runnable;
public CountdownRunnable(int count, Runnable runnable) {
this.countdown = new AtomicInteger(count);
this.runnable = runnable;
}
public CountdownRunnable(int count, Runnable runnable) {
this.countdown = new AtomicInteger(count);
this.runnable = runnable;
}
public void countdown() {
if(countdown.decrementAndGet() != 0)
return;
public void countdown() {
if (countdown.decrementAndGet() != 0)
return;
Heads.sync(runnable);
}
}
Heads.sync(runnable);
}
}
}

View File

@ -1,74 +1,78 @@
package net.sothatsit.heads;
import net.sothatsit.heads.util.Checks;
import org.bukkit.Material;
import java.io.*;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.bukkit.Material;
import net.sothatsit.heads.util.Checks;
public class LegacyIDs {
public static final LegacyIDs EMPTY = new LegacyIDs(Collections.emptyMap());
public static final LegacyIDs EMPTY = new LegacyIDs(Collections.emptyMap());
private final Map<Integer, String> idToType;
private final Map<Integer, String> idToType;
public LegacyIDs(Map<Integer, String> idToType) {
Checks.ensureNonNull(idToType, "idToType");
public LegacyIDs(Map<Integer, String> idToType) {
Checks.ensureNonNull(idToType, "idToType");
this.idToType = idToType;
}
this.idToType = idToType;
}
public String fromId(int id) {
return idToType.get(id);
}
public String fromId(int id) {
return idToType.get(id);
}
public void write(File file) throws IOException {
try (FileOutputStream fos = new FileOutputStream(file);
OutputStreamWriter osr = new OutputStreamWriter(fos);
BufferedWriter writer = new BufferedWriter(osr)) {
public void write(File file) throws IOException {
try (FileOutputStream fos = new FileOutputStream(file); OutputStreamWriter osr = new OutputStreamWriter(fos); BufferedWriter writer = new BufferedWriter(osr)) {
write(writer);
}
}
write(writer);
}
}
public void write(BufferedWriter writer) throws IOException {
for(Map.Entry<Integer, String> entry : idToType.entrySet()) {
writer.write(entry.getKey() + ":" + entry.getValue() + "\n");
}
}
public void write(BufferedWriter writer) throws IOException {
for (Map.Entry<Integer, String> entry : idToType.entrySet()) {
writer.write(entry.getKey() + ":" + entry.getValue() + "\n");
}
}
public static LegacyIDs create() {
Map<Integer, String> idToType = new HashMap<>();
public static LegacyIDs create() {
Map<Integer, String> idToType = new HashMap<>();
for(Material type : Material.values()) {
idToType.put(type.getId(), type.name());
}
for (Material type : Material.values()) {
idToType.put(type.getId(), type.name());
}
return new LegacyIDs(idToType);
}
return new LegacyIDs(idToType);
}
public static LegacyIDs readResource(String resource) throws IOException {
try (InputStream is = Heads.getInstance().getResource(resource);
InputStreamReader isr = new InputStreamReader(is);
BufferedReader reader = new BufferedReader(isr)) {
public static LegacyIDs readResource(String resource) throws IOException {
try (InputStream is = Heads.getInstance().getResource(resource); InputStreamReader isr = new InputStreamReader(is); BufferedReader reader = new BufferedReader(isr)) {
return read(reader);
}
}
return read(reader);
}
}
public static LegacyIDs read(BufferedReader reader) throws IOException {
Map<Integer, String> idToType = new HashMap<>();
public static LegacyIDs read(BufferedReader reader) throws IOException {
Map<Integer, String> idToType = new HashMap<>();
String line;
while((line = reader.readLine()) != null) {
int splitIndex = line.indexOf(':');
int id = Integer.valueOf(line.substring(0, splitIndex));
String type = line.substring(splitIndex + 1);
idToType.put(id, type);
}
String line;
while ((line = reader.readLine()) != null) {
int splitIndex = line.indexOf(':');
int id = Integer.valueOf(line.substring(0, splitIndex));
String type = line.substring(splitIndex + 1);
idToType.put(id, type);
}
return new LegacyIDs(idToType);
}
return new LegacyIDs(idToType);
}
}

View File

@ -0,0 +1,7 @@
package net.sothatsit.heads;
public class LiveHead {
// TODO: Add animation heads with live (cached) texures in the next updates.
}

View File

@ -0,0 +1,7 @@
package net.sothatsit.heads.animation;
public class Animations {
// TODO: Add animation heads with live (cached) texures in the next updates.
}

View File

@ -0,0 +1,7 @@
package net.sothatsit.heads.animation;
public class LiveData {
// TODO: Add animation heads with live (cached) texures in the next updates.
}

View File

@ -0,0 +1,7 @@
package net.sothatsit.heads.animation;
public class Monitor {
// TODO: Add animation heads with live (cached) texures in the next updates.
}

View File

@ -1,21 +1,5 @@
package net.sothatsit.heads.menu.ui.item;
import net.sothatsit.heads.Heads;
import net.sothatsit.heads.config.lang.Placeholder;
import net.sothatsit.heads.menu.ui.MenuResponse;
import net.sothatsit.heads.util.Checks;
import net.sothatsit.heads.util.Stringify;
import net.sothatsit.heads.volatilecode.ItemNBT;
import net.sothatsit.heads.volatilecode.reflection.Version;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.Damageable;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.material.MaterialData;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
@ -23,359 +7,361 @@ import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.material.MaterialData;
import net.sothatsit.heads.Heads;
import net.sothatsit.heads.config.lang.Placeholder;
import net.sothatsit.heads.menu.ui.MenuResponse;
import net.sothatsit.heads.util.Checks;
import net.sothatsit.heads.util.Stringify;
import net.sothatsit.heads.volatilecode.ItemNBT;
import net.sothatsit.heads.volatilecode.reflection.Version;
public final class Item {
private final Material type;
private final int amount;
private final short damage;
private final Material type;
private final int amount;
private final short damage;
private final String name;
private final String[] lore;
private final String name;
private final String[] lore;
private final boolean enchanted;
private final boolean enchanted;
private Item(Material type) {
this(type, 1, (short) 0, null, null, false);
}
private Item(Material type) {
this(type, 1, (short) 0, null, null, false);
}
private Item(Material type, int amount, short damage, String name, String[] lore, boolean enchanted) {
Checks.ensureNonNull(type, "type");
Checks.ensureTrue(amount > 0, "amount must be greater than 0");
Checks.ensureTrue(damage >= 0, "damage must be greater than or equal to 0");
private Item(Material type, int amount, short damage, String name, String[] lore, boolean enchanted) {
Checks.ensureNonNull(type, "type");
Checks.ensureTrue(amount > 0, "amount must be greater than 0");
Checks.ensureTrue(damage >= 0, "damage must be greater than or equal to 0");
if(lore != null) {
Checks.ensureArrayNonNull(lore, "lore");
}
if (lore != null) {
Checks.ensureArrayNonNull(lore, "lore");
}
this.type = type;
this.amount = amount;
this.damage = damage;
this.name = name;
this.lore = (lore == null || lore.length == 0 ? null : lore);
this.enchanted = enchanted;
}
this.type = type;
this.amount = amount;
this.damage = damage;
this.name = name;
this.lore = (lore == null || lore.length == 0 ? null : lore);
this.enchanted = enchanted;
}
public Item amount(int amount) {
return new Item(type, amount, damage, name, lore, enchanted);
}
public Item amount(int amount) {
return new Item(type, amount, damage, name, lore, enchanted);
}
public Item damage(short damage) {
return new Item(type, amount, damage, name, lore, enchanted);
}
public Item damage(short damage) {
return new Item(type, amount, damage, name, lore, enchanted);
}
public Item name(String name) {
return new Item(type, amount, damage, name, lore, enchanted);
}
public Item name(String name) {
return new Item(type, amount, damage, name, lore, enchanted);
}
public Item lore(String... lore) {
return new Item(type, amount, damage, name, lore, enchanted);
}
public Item lore(String... lore) {
return new Item(type, amount, damage, name, lore, enchanted);
}
public Item enchanted(boolean enchanted) {
return new Item(type, amount, damage, name, lore, enchanted);
}
public Item enchanted(boolean enchanted) {
return new Item(type, amount, damage, name, lore, enchanted);
}
public Button buildButton(Placeholder... placeholders) {
return new Button(build(placeholders));
}
public Button buildButton(Placeholder... placeholders) {
return new Button(build(placeholders));
}
public Button buildButton(Callable<MenuResponse> callable, Placeholder... placeholders) {
return new Button(build(placeholders), callable);
}
public Button buildButton(Callable<MenuResponse> callable, Placeholder... placeholders) {
return new Button(build(placeholders), callable);
}
public ItemStack build(Placeholder... placeholders) {
return build(null, placeholders);
}
public ItemStack build(Placeholder... placeholders) {
return build(null, placeholders);
}
public ItemStack build(Function<String, Boolean> loreFilter, Placeholder... placeholders) {
Checks.ensureNonNull(placeholders, "placeholders");
public ItemStack build(Function<String, Boolean> loreFilter, Placeholder... placeholders) {
Checks.ensureNonNull(placeholders, "placeholders");
ItemStack item = new ItemStack(type, amount, damage);
ItemStack item = new ItemStack(type, amount, damage);
ItemMeta meta = item.getItemMeta();
ItemMeta meta = item.getItemMeta();
if(meta == null)
return item;
if (meta == null)
return item;
if(name != null) {
String displayName = ChatColor.translateAlternateColorCodes('&', name);
if (name != null) {
String displayName = ChatColor.translateAlternateColorCodes('&', name);
displayName = Placeholder.applyAll(displayName, placeholders);
displayName = Placeholder.applyAll(displayName, placeholders);
meta.setDisplayName(displayName);
}
meta.setDisplayName(displayName);
}
if(lore != null) {
String[] itemLore = Placeholder.colourAll(lore);
if (lore != null) {
String[] itemLore = Placeholder.colourAll(lore);
itemLore = Placeholder.filterAndApplyAll(itemLore, loreFilter, placeholders);
meta.setLore(Arrays.asList(itemLore));
}
item.setItemMeta(meta);
if(enchanted) {
item = ItemNBT.addGlow(item);
}
itemLore = Placeholder.filterAndApplyAll(itemLore, loreFilter, placeholders);
return item;
}
meta.setLore(Arrays.asList(itemLore));
}
public void save(ConfigurationSection section, String key) {
section.set(key, null);
save(section.createSection(key));
}
item.setItemMeta(meta);
public void save(ConfigurationSection section) {
section.set("type", getTypeName(type));
if (enchanted) {
item = ItemNBT.addGlow(item);
}
if(amount != 1) {
section.set("amount", amount);
}
return item;
}
if(damage != 0) {
section.set("damage", damage);
}
public void save(ConfigurationSection section, String key) {
section.set(key, null);
save(section.createSection(key));
}
if(name != null) {
section.set("name", name);
}
public void save(ConfigurationSection section) {
section.set("type", getTypeName(type));
if(lore != null) {
section.set("lore", Arrays.asList(lore));
}
if (amount != 1) {
section.set("amount", amount);
}
if(enchanted) {
section.set("enchanted", true);
}
}
if (damage != 0) {
section.set("damage", damage);
}
@Override
public boolean equals(Object obj) {
if(!(obj instanceof Item))
return false;
if (name != null) {
section.set("name", name);
}
Item other = (Item) obj;
if (lore != null) {
section.set("lore", Arrays.asList(lore));
}
return other.type == type
&& other.amount == amount
&& Objects.equals(other.name, name)
&& (other.lore == null ? lore == null : Arrays.equals(other.lore, lore))
&& other.enchanted == enchanted;
}
if (enchanted) {
section.set("enchanted", true);
}
}
@Override
public String toString() {
Stringify.Builder properties = Stringify.builder();
{
properties.entry("type", getTypeName(type));
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Item))
return false;
if(amount != 1) {
properties.entry("amount", amount);
}
Item other = (Item) obj;
if(name != null) {
properties.entry("name", name);
}
return other.type == type && other.amount == amount && Objects.equals(other.name, name) && (other.lore == null ? lore == null : Arrays.equals(other.lore, lore)) && other.enchanted == enchanted;
}
if(Version.isBelow(Version.v1_13)) {
if(damage != 0) {
properties.entry("data", damage);
}
} else {
if(damage != 0) {
properties.entry("damage", damage);
}
}
if(lore != null) {
properties.entry("lore", lore);
}
if(enchanted) {
properties.entry("enchanted", true);
}
}
return properties.toString();
}
public static Item create(Material type) {
return new Item(type);
}
/**
* @deprecated data is only supported pre-1.13
*/
@Deprecated
public static Item create(Material type, byte data) {
return new Item(type, 1, data, null, null, false);
}
public static Item create(ItemStack itemStack) {
Item item = create(itemStack.getType())
.amount(itemStack.getAmount())
.damage(itemStack.getDurability());
ItemMeta meta = itemStack.getItemMeta();
if(meta == null)
return item;
if(meta.hasDisplayName()) {
String name = meta.getDisplayName().replace(ChatColor.COLOR_CHAR, '&');
item = item.name(name);
}
if(meta.hasLore()) {
List<String> rawLore = meta.getLore();
String[] lore = new String[rawLore.size()];
for(int index = 0; index < lore.length; ++index) {
lore[index] = rawLore.get(index).replace(ChatColor.COLOR_CHAR, '&');
}
item = item.lore(lore);
}
if(meta.hasEnchants()) {
item = item.enchanted(true);
}
return item;
}
private static void updateLegacyTypes(String filename, ConfigurationSection section, AtomicBoolean shouldSave) {
if(!section.isSet("type"))
return;
if(Version.isBelow(Version.v1_13) && section.isSet("data")) {
section.set("damage", section.get("data"));
section.set("data", null);
shouldSave.set(true);
}
String typeName = section.getString("type");
String typeData = section.getString("damage", null);
Material type = Material.matchMaterial(typeName);
if(type != null && !section.isInt("type"))
return;
if(section.isInt("type")) {
int typeId = section.getInt("type");
String convertedType = Heads.getLegacyIDs().fromId(typeId);
if(convertedType == null) {
Heads.warning("Invalid type of item " + section.getCurrentPath() + ", " +
"unknown type id " + typeId);
return;
}
if(Version.isBelow(Version.v1_13)) {
type = Material.matchMaterial(convertedType);
} else {
type = null;
}
section.set("type", convertedType.toLowerCase());
}
boolean legacy = false;
if(type == null && !Version.isBelow(Version.v1_13)) {
type = Material.valueOf("LEGACY_" + section.getString("type").toUpperCase().replace(' ', '_'));
legacy = true;
}
if(type == null) {
Heads.warning("Invalid type of item " + section.getCurrentPath() + ", could not find type " + typeName);
return;
}
if(legacy && !Version.isBelow(Version.v1_13)) {
Material legacyType = type;
int data = section.getInt("damage");
byte byteData = (byte) (data >= 0 && data < 16 ? data : 0);
// Get a type to begin with, to check if the data is a damage value
Material withoutData = fromLegacyType(legacyType, (byte) 0);
type = fromLegacyType(legacyType, byteData);
if(type == null) {
Heads.warning("Invalid legacy type of item " + section.getCurrentPath() + ": " +
"Could not convert " + legacyType + ":" + data + " to non-legacy format");
return;
}
if(withoutData != type) {
section.set("damage", null);
}
}
section.set("type", type.name().toLowerCase());
String from = typeName + (typeData != null ? ":" + typeData : "");
String to = type.name().toLowerCase() + (section.isSet("damage") ? ":" + section.get("damage") : "");
Heads.info("1.13 Update - " + from + " converted to " + to +
" for " + filename + " -> " + section.getCurrentPath());
shouldSave.set(true);
}
public static Item load(String filename, ConfigurationSection section, AtomicBoolean shouldSave) {
// Convert from legacy type ids to type names
updateLegacyTypes(filename, section, shouldSave);
if (!section.isSet("type") || !section.isString("type")) {
Heads.warning("Invalid type of item " + section.getCurrentPath() + " in " + filename + ", " +
"expected a type name");
return null;
}
String typeName = section.getString("type");
Material type = Material.matchMaterial(typeName);
if(type == null) {
Heads.warning("Invalid type of item " + section.getCurrentPath() + ", " +
"unknown material for type name " + typeName);
return null;
}
short damage = (short) section.getInt("damage", 0);
if(damage < 0) {
Heads.warning("Invalid damage of item " + section.getCurrentPath() + ", " +
"damage must be at least 0");
return null;
}
int amount = section.getInt("amount", 1);
if(amount < 1) {
Heads.warning("Invalid amount of item " + section.getCurrentPath() + ", " +
"amount must be at least 1");
return null;
}
String name = section.getString("name", null);
String[] lore = section.getStringList("lore").toArray(new String[0]);
boolean enchanted = section.getBoolean("enchanted", false);
return new Item(type, amount, damage, name, lore, enchanted);
}
public static String getTypeName(Material type) {
return type.name().toLowerCase();
}
public static Material getType(String typeName) {
Material type = Material.matchMaterial(typeName);
if(type != null || Version.isBelow(Version.v1_13))
return type;
return Material.matchMaterial(typeName, true);
}
public static Material fromLegacyType(Material legacyType, byte data) {
return Bukkit.getUnsafe().fromLegacy(new MaterialData(legacyType, data));
}
@Override
public String toString() {
Stringify.Builder properties = Stringify.builder();
{
properties.entry("type", getTypeName(type));
if (amount != 1) {
properties.entry("amount", amount);
}
if (name != null) {
properties.entry("name", name);
}
if (Version.isBelow(Version.v1_13)) {
if (damage != 0) {
properties.entry("data", damage);
}
} else {
if (damage != 0) {
properties.entry("damage", damage);
}
}
if (lore != null) {
properties.entry("lore", lore);
}
if (enchanted) {
properties.entry("enchanted", true);
}
}
return properties.toString();
}
public static Item create(Material type) {
return new Item(type);
}
public static Item create(Material type, byte data) {
if (Version.isBelow(Version.v1_13)) {
return new Item(type, 1, data, null, null, false);
}
return new Item(type, 1, (short) 0, null, null, false);
}
public static Item create(ItemStack itemStack) {
Item item = create(itemStack.getType()).amount(itemStack.getAmount()).damage(itemStack.getDurability());
ItemMeta meta = itemStack.getItemMeta();
if (meta == null)
return item;
if (meta.hasDisplayName()) {
String name = meta.getDisplayName().replace(ChatColor.COLOR_CHAR, '&');
item = item.name(name);
}
if (meta.hasLore()) {
List<String> rawLore = meta.getLore();
String[] lore = new String[rawLore.size()];
for (int index = 0; index < lore.length; ++index) {
lore[index] = rawLore.get(index).replace(ChatColor.COLOR_CHAR, '&');
}
item = item.lore(lore);
}
if (meta.hasEnchants()) {
item = item.enchanted(true);
}
return item;
}
private static void updateLegacyTypes(String filename, ConfigurationSection section, AtomicBoolean shouldSave) {
if (!section.isSet("type"))
return;
if (Version.isBelow(Version.v1_13) && section.isSet("data")) {
section.set("damage", section.get("data"));
section.set("data", null);
shouldSave.set(true);
}
String typeName = section.getString("type");
String typeData = section.getString("damage", null);
Material type = Material.matchMaterial(typeName);
if (type != null && !section.isInt("type"))
return;
if (section.isInt("type")) {
int typeId = section.getInt("type");
String convertedType = Heads.getLegacyIDs().fromId(typeId);
if (convertedType == null) {
Heads.warning("Invalid type of item " + section.getCurrentPath() + ", " + "unknown type id " + typeId);
return;
}
if (Version.isBelow(Version.v1_13)) {
type = Material.matchMaterial(convertedType);
} else {
type = null;
}
section.set("type", convertedType.toLowerCase());
}
boolean legacy = false;
if (type == null && !Version.isBelow(Version.v1_13)) {
type = Material.valueOf("LEGACY_" + section.getString("type").toUpperCase().replace(' ', '_'));
legacy = true;
}
if (type == null) {
Heads.warning("Invalid type of item " + section.getCurrentPath() + ", could not find type " + typeName);
return;
}
if (legacy && !Version.isBelow(Version.v1_13)) {
Material legacyType = type;
int data = section.getInt("damage");
byte byteData = (byte) (data >= 0 && data < 16 ? data : 0);
// Get a type to begin with, to check if the data is a damage value
Material withoutData = fromLegacyType(legacyType, (byte) 0);
type = fromLegacyType(legacyType, byteData);
if (type == null) {
Heads.warning("Invalid legacy type of item " + section.getCurrentPath() + ": " + "Could not convert " + legacyType + ":" + data + " to non-legacy format");
return;
}
if (withoutData != type) {
section.set("damage", null);
}
}
section.set("type", type.name().toLowerCase());
String from = typeName + (typeData != null ? ":" + typeData : "");
String to = type.name().toLowerCase() + (section.isSet("damage") ? ":" + section.get("damage") : "");
Heads.info("1.13 Update - " + from + " converted to " + to + " for " + filename + " -> " + section.getCurrentPath());
shouldSave.set(true);
}
public static Item load(String filename, ConfigurationSection section, AtomicBoolean shouldSave) {
// Convert from legacy type ids to type names
updateLegacyTypes(filename, section, shouldSave);
if (!section.isSet("type") || !section.isString("type")) {
Heads.warning("Invalid type of item " + section.getCurrentPath() + " in " + filename + ", " + "expected a type name");
return null;
}
String typeName = section.getString("type");
Material type = Material.matchMaterial(typeName);
if (type == null) {
Heads.warning("Invalid type of item " + section.getCurrentPath() + ", " + "unknown material for type name " + typeName);
return null;
}
short damage = (short) section.getInt("damage", 0);
if (damage < 0) {
Heads.warning("Invalid damage of item " + section.getCurrentPath() + ", " + "damage must be at least 0");
return null;
}
int amount = section.getInt("amount", 1);
if (amount < 1) {
Heads.warning("Invalid amount of item " + section.getCurrentPath() + ", " + "amount must be at least 1");
return null;
}
String name = section.getString("name", null);
String[] lore = section.getStringList("lore").toArray(new String[0]);
boolean enchanted = section.getBoolean("enchanted", false);
return new Item(type, amount, damage, name, lore, enchanted);
}
public static String getTypeName(Material type) {
return type.name().toLowerCase();
}
public static Material getType(String typeName) {
Material type = Material.matchMaterial(typeName);
if (type != null || Version.isBelow(Version.v1_13))
return type;
return Material.matchMaterial(typeName, true);
}
public static Material fromLegacyType(Material legacyType, byte data) {
return Bukkit.getUnsafe().fromLegacy(new MaterialData(legacyType, data));
}
}

View File

@ -2,44 +2,47 @@ package net.sothatsit.heads.util;
public abstract class ExceptionDetailer {
private static class DetailException extends Exception {
public DetailException(String detail) {
super(detail);
}
}
private static class DetailException extends Exception {
public RuntimeException detail(RuntimeException exception) {
return (RuntimeException) detail((Exception) exception);
}
private static final long serialVersionUID = 7714839411923164464L;
public abstract Exception detail(Exception exception);
public DetailException(String detail) {
super(detail);
}
}
public static ExceptionDetailer constructorDetailer() {
final DetailException constructorStackTrace = new DetailException("Object constructed at");
public RuntimeException detail(RuntimeException exception) {
return (RuntimeException) detail((Exception) exception);
}
return new ExceptionDetailer() {
@Override
public Exception detail(Exception exception) {
try {
return appendInfo(exception, constructorStackTrace);
} catch(Exception e) {
new Exception("Exception appending info to exception", e).printStackTrace();
public abstract Exception detail(Exception exception);
constructorStackTrace.printStackTrace();
public static ExceptionDetailer constructorDetailer() {
final DetailException constructorStackTrace = new DetailException("Object constructed at");
return exception;
}
}
};
}
return new ExceptionDetailer() {
@Override
public Exception detail(Exception exception) {
try {
return appendInfo(exception, constructorStackTrace);
} catch (Exception e) {
new Exception("Exception appending info to exception", e).printStackTrace();
public static Exception appendInfo(Exception exception, DetailException info) {
Checks.ensureNonNull(exception, "exception");
Checks.ensureNonNull(info, "info");
constructorStackTrace.printStackTrace();
exception.addSuppressed(info);
return exception;
}
}
};
}
return exception;
}
public static Exception appendInfo(Exception exception, DetailException info) {
Checks.ensureNonNull(exception, "exception");
Checks.ensureNonNull(info, "info");
exception.addSuppressed(info);
return exception;
}
}

View File

@ -1,64 +1,65 @@
package net.sothatsit.heads.volatilecode;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import net.sothatsit.heads.menu.ui.item.Item;
import net.sothatsit.heads.volatilecode.reflection.Version;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
/**
* Methods to deal with items on different Spigot versions.
*/
public class Items {
public static boolean isSkull(ItemStack item) {
if(item == null)
return false;
public static boolean isSkull(ItemStack item) {
if (item == null)
return false;
if(Version.isBelow(Version.v1_13))
return item.getType().name().equals("SKULL_ITEM") && item.getDurability() == 3;
if (Version.isBelow(Version.v1_13))
return item.getType().name().equals("SKULL_ITEM") && item.getDurability() == 3;
return item.getType() == Material.PLAYER_HEAD;
}
return item.getType() == Material.PLAYER_HEAD;
}
public static Item createSkull() {
if(Version.isBelow(Version.v1_13))
return Item.create(Material.valueOf("SKULL_ITEM"), (byte) 3);
public static Item createSkull() {
if (Version.isBelow(Version.v1_13))
return Item.create(Material.valueOf("SKULL_ITEM"), (byte) 3);
return Item.create(Material.PLAYER_HEAD);
}
return Item.create(Material.PLAYER_HEAD);
}
public static Item createRedStainedClay() {
if(Version.isBelow(Version.v1_13))
return Item.create(Material.valueOf("STAINED_CLAY"), (byte) 14);
public static Item createRedStainedClay() {
if (Version.isBelow(Version.v1_13))
return Item.create(Material.valueOf("STAINED_CLAY"), (byte) 14);
return Item.create(Material.RED_TERRACOTTA);
}
return Item.create(Material.RED_TERRACOTTA);
}
public static Item createGreenStainedClay() {
if(Version.isBelow(Version.v1_13))
return Item.create(Material.valueOf("STAINED_CLAY"), (byte) 5);
public static Item createGreenStainedClay() {
if (Version.isBelow(Version.v1_13))
return Item.create(Material.valueOf("STAINED_CLAY"), (byte) 5);
return Item.create(Material.GREEN_TERRACOTTA);
}
return Item.create(Material.GREEN_TERRACOTTA);
}
public static Item createRedStainedGlassPane() {
if(Version.isBelow(Version.v1_13))
return Item.create(Material.valueOf("STAINED_GLASS_PANE"), (byte) 14);
public static Item createRedStainedGlassPane() {
if (Version.isBelow(Version.v1_13))
return Item.create(Material.valueOf("STAINED_GLASS_PANE"), (byte) 14);
return Item.create(Material.RED_STAINED_GLASS_PANE);
}
return Item.create(Material.RED_STAINED_GLASS_PANE);
}
public static Item createBlackStainedGlassPane() {
if(Version.isBelow(Version.v1_13))
return Item.create(Material.valueOf("STAINED_GLASS_PANE"), (byte) 15);
public static Item createBlackStainedGlassPane() {
if (Version.isBelow(Version.v1_13))
return Item.create(Material.valueOf("STAINED_GLASS_PANE"), (byte) 15);
return Item.create(Material.BLACK_STAINED_GLASS_PANE);
}
return Item.create(Material.BLACK_STAINED_GLASS_PANE);
}
public static Item createEmptyMap() {
if(Version.isBelow(Version.v1_13))
return Item.create(Material.valueOf("EMPTY_MAP"));
public static Item createEmptyMap() {
if (Version.isBelow(Version.v1_13))
return Item.create(Material.valueOf("EMPTY_MAP"));
return Item.create(Material.MAP);
}
return Item.create(Material.MAP);
}
}

View File

@ -1,119 +1,118 @@
package net.sothatsit.heads.volatilecode.reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import org.bukkit.Bukkit;
public final class ReflectionUtils {
public static String getServerVersion() {
String name = Bukkit.getServer().getClass().getPackage().getName();
return name.substring(name.lastIndexOf('.') + 1);
}
public static Class<?> getNMSClass(String ClassName) {
String className = "net.minecraft.server." + getServerVersion() + "." + ClassName;
try {
return Class.forName(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
public static Class<?> getCraftBukkitClass(String ClassPackageName) {
String className = "org.bukkit.craftbukkit." + getServerVersion() + "." + ClassPackageName;
try {
return Class.forName(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
public static Constructor<?> getConstructor(Class<?> clazz, Class<?>... params) {
outer: for (Constructor<?> c : clazz.getDeclaredConstructors()) {
Class<?>[] para = c.getParameterTypes();
if (para.length != params.length) {
continue;
}
for (int i = 0; i < para.length; i++) {
if (!para[i].equals(params[i])) {
continue outer;
}
}
return c;
}
reportNotFound("Could not find constructor in class " + clazz);
return null;
}
public static Method getMethod(Class<?> clazz, String name) {
for (Method m : clazz.getDeclaredMethods()) {
if (m.getName().equals(name)) {
m.setAccessible(true);
return m;
}
}
reportNotFound("Could not find method " + name + " in class " + clazz);
return null;
}
public static Method getMethod(Class<?> clazz, Class<?> returnType, Class<?>... params) {
return getMethod(clazz, null, false, returnType, params);
}
public static Method getMethod(Class<?> clazz, String name, Class<?> returnType, Class<?>... params) {
return getMethod(clazz, name, false, returnType, params);
}
public static Method getMethod(Class<?> clazz, boolean staticMethod, Class<?> returnType, Class<?>... params) {
return getMethod(clazz, null, staticMethod, returnType, params);
}
public static Method getMethod(Class<?> clazz, String name, boolean staticMethod, Class<?> returnType, Class<?>... params) {
outer: for (Method m : clazz.getDeclaredMethods()) {
if (name != null && !m.getName().equals(name)) {
continue;
}
if (staticMethod != Modifier.isStatic(m.getModifiers())) {
continue;
}
if (!m.getReturnType().equals(returnType)) {
continue;
}
Class<?>[] para = m.getParameterTypes();
if (para.length != params.length) {
continue;
}
for (int i = 0; i < para.length; i++) {
if (!para[i].equals(params[i])) {
continue outer;
}
}
return m;
}
reportNotFound("Could not find method " + name + " in class " + clazz);
return null;
}
public static void reportNotFound(String message) {
new Exception(message).printStackTrace();
}
public static String getServerVersion() {
String name = Bukkit.getServer().getClass().getPackage().getName();
return name.substring(name.lastIndexOf('.') + 1);
}
public static Class<?> getNMSClass(String ClassName) {
String className = "net.minecraft.server." + getServerVersion() + "." + ClassName;
try {
return Class.forName(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
public static Class<?> getCraftBukkitClass(String ClassPackageName) {
String className = "org.bukkit.craftbukkit." + getServerVersion() + "." + ClassPackageName;
try {
return Class.forName(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
public static Constructor<?> getConstructor(Class<?> clazz, Class<?>... params) {
outer: for (Constructor<?> c : clazz.getDeclaredConstructors()) {
Class<?>[] para = c.getParameterTypes();
if (para.length != params.length) {
continue;
}
for (int i = 0; i < para.length; i++) {
if (!para[i].equals(params[i])) {
continue outer;
}
}
return c;
}
reportNotFound("Could not find constructor in class " + clazz);
return null;
}
public static Method getMethod(Class<?> clazz, String name) {
for (Method m : clazz.getDeclaredMethods()) {
if (m.getName().equals(name)) {
m.setAccessible(true);
return m;
}
}
reportNotFound("Could not find method " + name + " in class " + clazz);
return null;
}
public static Method getMethod(Class<?> clazz, Class<?> returnType, Class<?>... params) {
return getMethod(clazz, null, false, returnType, params);
}
public static Method getMethod(Class<?> clazz, String name, Class<?> returnType, Class<?>... params) {
return getMethod(clazz, name, false, returnType, params);
}
public static Method getMethod(Class<?> clazz, boolean staticMethod, Class<?> returnType, Class<?>... params) {
return getMethod(clazz, null, staticMethod, returnType, params);
}
public static Method getMethod(Class<?> clazz, String name, boolean staticMethod, Class<?> returnType, Class<?>... params) {
outer: for (Method m : clazz.getDeclaredMethods()) {
if (name != null && !m.getName().equals(name)) {
continue;
}
if (staticMethod != Modifier.isStatic(m.getModifiers())) {
continue;
}
if (!m.getReturnType().equals(returnType)) {
continue;
}
Class<?>[] para = m.getParameterTypes();
if (para.length != params.length) {
continue;
}
for (int i = 0; i < para.length; i++) {
if (!para[i].equals(params[i])) {
continue outer;
}
}
return m;
}
reportNotFound("Could not find method " + name + " in class " + clazz);
return null;
}
public static void reportNotFound(String message) {
new Exception(message).printStackTrace();
}
}

View File

@ -1,7 +1,7 @@
main: net.sothatsit.heads.Heads
author: Marido
name: Heads
version: 2.0.1
version: 2.0.2
api-version: 1.13
softdepend: [Vault, PlayerPoints, BlockStore]
loadbefore: [DeluxeMenus]