Merge branch 'development'

This commit is contained in:
Brianna 2019-12-28 22:07:51 -05:00
commit 1ceacd6918
46 changed files with 2564 additions and 1613 deletions

View File

@ -1,21 +0,0 @@
stages:
- build
variables:
name: "EpicEnchants"
path: "/builds/$CI_PROJECT_PATH"
version: "1.0.10"
build:
stage: build
image: maven:3.5.3-jdk-8
script:
- find $path/ -type f -name "*.xml" -print0 | xargs -0 sed -i -e s/maven-version-number/$version/g
- find $path/ -type f -name "*.yml" -print0 | xargs -0 sed -i -e s/maven-version-number/$version/g
- mvn clean package
- find $path/ -depth -path '*original*' -delete
- mv $path/target/*.jar $path/
artifacts:
name: $name-$version
paths:
- "$path/*.jar"

53
pom.xml
View File

@ -2,7 +2,7 @@
<groupId>com.songoda</groupId>
<artifactId>EpicEnchants</artifactId>
<modelVersion>4.0.0</modelVersion>
<version>maven-version-number</version>
<version>1.1</version>
<build>
<defaultGoal>clean install</defaultGoal>
<finalName>EpicEnchants-${project.version}</finalName>
@ -16,6 +16,28 @@
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>com.google.code.maven-replacer-plugin</groupId>
<artifactId>replacer</artifactId>
<version>1.5.3</version>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>replace</goal>
</goals>
</execution>
</executions>
<configuration>
<file>${project.build.directory}/classes/plugin.yml</file>
<replacements>
<replacement>
<token>maven-version-number</token>
<value>${project.version}</value>
</replacement>
</replacements>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
@ -32,7 +54,7 @@
<createDependencyReducedPom>false</createDependencyReducedPom>
<artifactSet>
<includes>
<include>com.songoda:songodaupdater</include>
<include>com.songoda:SongodaCore</include>
<include>fr.mymicky:FastInv</include>
</includes>
</artifactSet>
@ -58,10 +80,6 @@
<id>private</id>
<url>http://repo.songoda.com/artifactory/private/</url>
</repository>
<repository>
<id>reserve-repo</id>
<url>https://dl.bintray.com/theneweconomy/java/</url>
</repository>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
@ -72,7 +90,7 @@
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId>
<version>1.14.4</version>
<version>1.15</version>
</dependency>
<dependency>
<groupId>fr.mrmicky</groupId>
@ -82,24 +100,9 @@
</dependency>
<dependency>
<groupId>com.songoda</groupId>
<artifactId>songodaupdater</artifactId>
<version>1</version>
</dependency>
<dependency>
<groupId>net.tnemc</groupId>
<artifactId>Reserve</artifactId>
<version>0.1.3.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.black_ixx</groupId>
<artifactId>playerpoints</artifactId>
<version>2.1.4</version>
</dependency>
<dependency>
<groupId>net.milkbowl</groupId>
<artifactId>vault</artifactId>
<version>1.7.1</version>
<artifactId>SongodaCore</artifactId>
<version>LATEST</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.songoda</groupId>

View File

@ -1,10 +1,11 @@
package com.songoda.epicenchants;
import com.songoda.core.SongodaCore;
import com.songoda.core.SongodaPlugin;
import com.songoda.core.compatibility.CompatibleMaterial;
import com.songoda.core.configuration.Config;
import com.songoda.core.hooks.EconomyManager;
import com.songoda.epicenchants.command.CommandManager;
import com.songoda.epicenchants.economy.Economy;
import com.songoda.epicenchants.economy.PlayerPointsEconomy;
import com.songoda.epicenchants.economy.ReserveEconomy;
import com.songoda.epicenchants.economy.VaultEconomy;
import com.songoda.epicenchants.listeners.ArmorListener;
import com.songoda.epicenchants.listeners.EntityListener;
import com.songoda.epicenchants.listeners.PlayerListener;
@ -16,27 +17,21 @@ import com.songoda.epicenchants.managers.*;
import com.songoda.epicenchants.objects.Enchant;
import com.songoda.epicenchants.utils.EnchantUtils;
import com.songoda.epicenchants.utils.Metrics;
import com.songoda.epicenchants.utils.ServerVersion;
import com.songoda.epicenchants.utils.SpecialItems;
import com.songoda.epicenchants.utils.locale.Locale;
import com.songoda.epicenchants.utils.objects.FastInv;
import com.songoda.epicenchants.utils.settings.Setting;
import com.songoda.epicenchants.utils.settings.SettingsManager;
import com.songoda.epicenchants.utils.single.ItemGroup;
import com.songoda.epicenchants.utils.updateModules.LocaleModule;
import com.songoda.update.Plugin;
import com.songoda.update.SongodaUpdate;
import org.apache.commons.lang.ArrayUtils;
import org.bukkit.Bukkit;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.List;
import java.util.stream.Collectors;
import static com.songoda.epicenchants.utils.single.GeneralUtils.color;
import static org.bukkit.Bukkit.getConsoleSender;
public class EpicEnchants extends JavaPlugin {
public class EpicEnchants extends SongodaPlugin {
private static EpicEnchants INSTANCE;
@ -48,12 +43,7 @@ public class EpicEnchants extends JavaPlugin {
private SettingsManager settingsManager;
private CommandManager commandManager;
private Locale locale;
private ServerVersion serverVersion = ServerVersion.fromPackageName(Bukkit.getServer().getClass().getPackage().getName());
private SpecialItems specialItems;
private Economy economy;
private EnchantUtils enchantUtils;
private ItemGroup itemGroup;
@ -62,25 +52,21 @@ public class EpicEnchants extends JavaPlugin {
}
@Override
public void onEnable() {
public void onPluginLoad() {
INSTANCE = this;
}
getConsoleSender().sendMessage(color("&a============================="));
getConsoleSender().sendMessage(color("&7" + getDescription().getName() + " " + getDescription().getVersion() + " by &5Songoda <3&7!"));
getConsoleSender().sendMessage(color("&7Action: &aEnabling&7..."));
@Override
public void onPluginEnable() {
// Run Songoda Updater
SongodaCore.registerPlugin(this, 67, CompatibleMaterial.DIAMOND_SWORD);
// Setup Setting Manager
this.settingsManager = new SettingsManager(this);
this.settingsManager.setupConfig();
// Setup Language
new Locale(this, "en_US");
this.locale = Locale.getLocale(getConfig().getString("System.Language Mode"));
// Running Songoda Updater
Plugin plugin = new Plugin(this, 67);
plugin.addModule(new LocaleModule());
SongodaUpdate.load(plugin);
this.setLocale(getConfig().getString("System.Language Mode"), false);
preload();
@ -109,13 +95,19 @@ public class EpicEnchants extends JavaPlugin {
pluginManager.registerEvents(new BlackScrollListener(this), this);
pluginManager.registerEvents(new DustListener(this), this);
String economyPlugin = null;
// Setup Economy
if (Setting.VAULT_ECONOMY.getBoolean() && pluginManager.isPluginEnabled("Vault"))
this.economy = new VaultEconomy();
economyPlugin = "Vault";
else if (Setting.RESERVE_ECONOMY.getBoolean() && pluginManager.isPluginEnabled("Reserve"))
this.economy = new ReserveEconomy();
economyPlugin = "Reserve";
else if (Setting.PLAYER_POINTS_ECONOMY.getBoolean() && pluginManager.isPluginEnabled("PlayerPoints"))
this.economy = new PlayerPointsEconomy();
economyPlugin = "PlayerPoints";
EconomyManager.load();
if (economyPlugin != null)
EconomyManager.getManager().setPreferredHook(economyPlugin);
// Start Metrics
new Metrics(this);
@ -123,8 +115,6 @@ public class EpicEnchants extends JavaPlugin {
if (!enchantManager.getValues().isEmpty()) {
getLogger().info("Successfully loaded enchants: " + enchantManager.getValues().stream().map(Enchant::getIdentifier).collect(Collectors.joining(", ")));
}
getConsoleSender().sendMessage(color("&a============================="));
}
private void preload() {
@ -134,13 +124,23 @@ public class EpicEnchants extends JavaPlugin {
}
@Override
public void onDisable() {
public void onPluginDisable() {
getConsoleSender().sendMessage(color("&a============================="));
getConsoleSender().sendMessage(color("&7" + getDescription().getName() + " " + getDescription().getVersion() + " by &5Songoda <3&7!"));
getConsoleSender().sendMessage(color("&7Action: &cDisabling&7..."));
getConsoleSender().sendMessage(color("&a============================="));
}
@Override
public void onConfigReload() {
}
@Override
public List<Config> getExtraConfig() {
return null;
}
public void reload() {
reloadConfig();
@ -156,26 +156,10 @@ public class EpicEnchants extends JavaPlugin {
infoManager.clear();
infoManager.loadMenus();
this.locale = Locale.getLocale(getConfig().getString("System.Language Mode"));
this.setLocale(getConfig().getString("System.Language Mode"), true);
this.locale.reloadMessages();
}
public ServerVersion getServerVersion() {
return serverVersion;
}
public boolean isServerVersion(ServerVersion version) {
return serverVersion == version;
}
public boolean isServerVersion(ServerVersion... versions) {
return ArrayUtils.contains(versions, serverVersion);
}
public boolean isServerVersionAtLeast(ServerVersion version) {
return serverVersion.ordinal() >= version.ordinal();
}
public EnchantManager getEnchantManager() {
return this.enchantManager;
}
@ -200,10 +184,6 @@ public class EpicEnchants extends JavaPlugin {
return this.specialItems;
}
public Economy getEconomy() {
return this.economy;
}
public EnchantUtils getEnchantUtils() {
return this.enchantUtils;
}
@ -212,10 +192,6 @@ public class EpicEnchants extends JavaPlugin {
return this.itemGroup;
}
public Locale getLocale() {
return locale;
}
public CommandManager getCommandManager() {
return commandManager;
}

View File

@ -1,15 +0,0 @@
package com.songoda.epicenchants.economy;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
public interface Economy {
boolean hasBalance(OfflinePlayer player, double cost);
double getBalance(Player player);
boolean withdrawBalance(OfflinePlayer player, double cost);
boolean deposit(OfflinePlayer player, double amount);
}

View File

@ -1,44 +0,0 @@
package com.songoda.epicenchants.economy;
import org.black_ixx.playerpoints.PlayerPoints;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
public class PlayerPointsEconomy implements Economy {
private final PlayerPoints playerPoints;
public PlayerPointsEconomy() {
this.playerPoints = (PlayerPoints) Bukkit.getServer().getPluginManager().getPlugin("PlayerPoints");
}
private int convertAmount(double amount) {
return (int) Math.ceil(amount);
}
@Override
public boolean hasBalance(OfflinePlayer player, double cost) {
int amount = convertAmount(cost);
return playerPoints.getAPI().look(player.getUniqueId()) >= amount;
}
@Override
public double getBalance(Player player) {
return playerPoints.getAPI().look(player.getUniqueId());
}
@Override
public boolean withdrawBalance(OfflinePlayer player, double cost) {
int amount = convertAmount(cost);
return playerPoints.getAPI().take(player.getUniqueId(), amount);
}
@Override
public boolean deposit(OfflinePlayer player, double amount) {
int amt = convertAmount(amount);
return playerPoints.getAPI().give(player.getUniqueId(), amt);
}
}

View File

@ -1,38 +0,0 @@
package com.songoda.epicenchants.economy;
import net.tnemc.core.Reserve;
import net.tnemc.core.economy.EconomyAPI;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import java.math.BigDecimal;
public class ReserveEconomy implements Economy {
EconomyAPI economyAPI;
public ReserveEconomy() {
if (Reserve.instance().economyProvided())
economyAPI = Reserve.instance().economy();
}
@Override
public boolean hasBalance(OfflinePlayer player, double cost) {
return economyAPI.hasHoldings(player.getUniqueId(), new BigDecimal(cost));
}
@Override
public double getBalance(Player player) {
return economyAPI.getHoldings(player.getUniqueId()).doubleValue();
}
@Override
public boolean withdrawBalance(OfflinePlayer player, double cost) {
return economyAPI.removeHoldings(player.getUniqueId(), new BigDecimal(cost));
}
@Override
public boolean deposit(OfflinePlayer player, double amount) {
return economyAPI.addHoldings(player.getUniqueId(), new BigDecimal(amount));
}
}

View File

@ -1,34 +0,0 @@
package com.songoda.epicenchants.economy;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
public class VaultEconomy implements Economy {
private final net.milkbowl.vault.economy.Economy vault;
public VaultEconomy() {
this.vault = Bukkit.getServicesManager().
getRegistration(net.milkbowl.vault.economy.Economy.class).getProvider();
}
@Override
public boolean hasBalance(OfflinePlayer player, double cost) {
return vault.has(player, cost);
}
@Override
public double getBalance(Player player) {
return vault.getBalance(player);
}
@Override
public boolean withdrawBalance(OfflinePlayer player, double cost) {
return vault.withdrawPlayer(player, cost).transactionSuccess();
}
@Override
public boolean deposit(OfflinePlayer player, double amount) {
return vault.depositPlayer(player, amount).transactionSuccess();
}
}

View File

@ -1,5 +1,6 @@
package com.songoda.epicenchants.effect.effects;
import com.songoda.core.compatibility.CompatibleMaterial;
import com.songoda.epicenchants.effect.EffectExecutor;
import com.songoda.epicenchants.enums.EventType;
import org.bukkit.Material;
@ -24,7 +25,7 @@ public class DropHead extends EffectExecutor {
}
private Optional<ItemStack> getHead(Entity entity) {
short data = 3;
ItemStack out = CompatibleMaterial.PLAYER_HEAD.getItem();
String skin = "";
switch (entity.getType()) {
@ -50,10 +51,10 @@ public class DropHead extends EffectExecutor {
skin = "MHF_Spider";
break;
case ZOMBIE:
data = 2;
out = CompatibleMaterial.ZOMBIE_HEAD.getItem();
break;
case SKELETON:
data = 0;
out = CompatibleMaterial.SKELETON_SKULL.getItem();
break;
case VILLAGER:
skin = "MHF_Villager";
@ -65,7 +66,7 @@ public class DropHead extends EffectExecutor {
skin = "MHF_Blaze";
break;
case CREEPER:
data = 4;
out = CompatibleMaterial.CREEPER_HEAD.getItem();
case ENDERMAN:
skin = "MHF_Enderman";
break;
@ -80,7 +81,6 @@ public class DropHead extends EffectExecutor {
return Optional.empty();
}
ItemStack out = new ItemStack(Material.LEGACY_SKULL_ITEM, 1, data);
SkullMeta skullMeta = (SkullMeta) out.getItemMeta();
skullMeta.setOwner(entity instanceof Player ? entity.getName() : skin);

View File

@ -3,10 +3,7 @@ package com.songoda.epicenchants.effect.effects;
import com.songoda.epicenchants.effect.EffectExecutor;
import com.songoda.epicenchants.enums.EventType;
import com.songoda.epicenchants.objects.LeveledModifier;
import com.songoda.epicenchants.utils.itemnbtapi.NBTEntity;
import com.songoda.epicenchants.utils.itemnbtapi.NBTList;
import com.songoda.epicenchants.utils.itemnbtapi.NBTListCompound;
import com.songoda.epicenchants.utils.itemnbtapi.NBTType;
import com.songoda.epicenchants.utils.itemnbtapi.*;
import com.songoda.epicenchants.utils.objects.ItemBuilder;
import org.bukkit.Location;
import org.bukkit.configuration.ConfigurationSection;
@ -92,17 +89,17 @@ public class SpawnMob extends EffectExecutor {
nbtEntity.setBoolean(user.getUniqueId().toString(), true);
NBTList list = nbtEntity.getList("Attributes", NBTType.NBTTagCompound);
NBTCompoundList list = nbtEntity.getCompoundList("Attributes");
for (int j = 0; j < list.size(); j++) {
NBTListCompound lc = list.getCompound(j);
NBTListCompound lc = list.get(j);
if (lc.getString("Name").equals("generic.attackDamage")) {
lc.setDouble("Base", attackDamage.get(level, (int) lc.getDouble("Base"), user, opponent));
lc.setDouble("Base", attackDamage.get(level, (int) Math.round(lc.getDouble("Base")), user, opponent));
continue;
}
if (lc.getString("Name").equals("generic.maxHealth")) {
lc.setDouble("Base", health.get(level, (int) lc.getDouble("Base"), user, opponent));
lc.setDouble("Base", health.get(level, (int) Math.round(lc.getDouble("Base")), user, opponent));
}
}
}

View File

@ -1,7 +1,7 @@
package com.songoda.epicenchants.managers;
import com.songoda.core.compatibility.ServerVersion;
import com.songoda.epicenchants.EpicEnchants;
import com.songoda.epicenchants.utils.ServerVersion;
import com.songoda.epicenchants.utils.objects.FileLocation;
import com.songoda.epicenchants.utils.settings.Setting;
import org.bukkit.Bukkit;
@ -81,8 +81,8 @@ public class FileManager extends Manager<String, FileConfiguration> {
public FileManager(EpicEnchants instance) {
super(instance);
directory = instance.isServerVersionAtLeast(ServerVersion.V1_13) ? "master" : "legacy";
Bukkit.getConsoleSender().sendMessage("Using the " + directory + " configurations because version is " + instance.getServerVersion().name());
directory = ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13) ? "master" : "legacy";
Bukkit.getConsoleSender().sendMessage("Using the " + directory + " configurations because version is " + ServerVersion.getServerVersion().name());
}
public void loadFiles() {

View File

@ -1,5 +1,6 @@
package com.songoda.epicenchants.menus;
import com.songoda.core.hooks.EconomyManager;
import com.songoda.epicenchants.EpicEnchants;
import com.songoda.epicenchants.objects.Enchant;
import com.songoda.epicenchants.objects.Group;
@ -263,12 +264,12 @@ public class AlchemistMenu extends FastInv {
of("eco_cost", ecoCost),
of("exp_cost", expCost)
).build(), event -> {
if (!instance.getEconomy().hasBalance(event.getPlayer(), ecoCost) || getExp(event.getPlayer()) < expCost) {
if (!EconomyManager.hasBalance(event.getPlayer(), ecoCost) || getExp(event.getPlayer()) < expCost) {
instance.getLocale().getMessage("alchemist.cannotafford").sendPrefixedMessage(event.getPlayer());
return;
}
instance.getEconomy().withdrawBalance(event.getPlayer(), ecoCost);
EconomyManager.withdrawBalance(event.getPlayer(), ecoCost);
changeExp(event.getPlayer(), -expCost);
instance.getLocale().getMessage("alchemist.success")
.processPlaceholder("eco_cost", ecoCost)

View File

@ -1,5 +1,6 @@
package com.songoda.epicenchants.menus;
import com.songoda.core.hooks.EconomyManager;
import com.songoda.epicenchants.EpicEnchants;
import com.songoda.epicenchants.objects.Group;
import com.songoda.epicenchants.utils.objects.FastInv;
@ -36,8 +37,8 @@ public class EnchanterMenu extends FastInv {
int ecoCost = section.getInt("eco-cost");
int xpLeft = Math.max(expCost - player.getLevel(), 0);
double ecoLeft = 0.0d;
if (instance.getEconomy() != null)
ecoLeft = ecoCost - instance.getEconomy().getBalance(player) < 0 ? 0 : ecoCost - instance.getEconomy().getBalance(player);
if (EconomyManager.isEnabled())
ecoLeft = ecoCost - EconomyManager.getBalance(player) < 0 ? 0 : ecoCost - EconomyManager.getBalance(player);
Group group = instance.getGroupManager().getValue(section.getString("group").toUpperCase())
.orElseThrow(() -> new IllegalArgumentException("Invalid group set in enchanter: " + section.getString("group")));
ItemStack itemStack = new ItemBuilder(section,
@ -52,13 +53,13 @@ public class EnchanterMenu extends FastInv {
return;
}
if (instance.getEconomy() != null && !instance.getEconomy().hasBalance((player), ecoCost) || getExp(player) < expCost) {
if (EconomyManager.isEnabled() && !EconomyManager.hasBalance((player), ecoCost) || getExp(player) < expCost) {
instance.getLocale().getMessage("enchanter.cannotafford").sendPrefixedMessage(player);
return;
}
if (instance.getEconomy() != null) {
instance.getEconomy().withdrawBalance(player, ecoCost);
if (EconomyManager.isEnabled()) {
EconomyManager.withdrawBalance(player, ecoCost);
instance.getLocale().getMessage("enchanter.success")
.processPlaceholder("group_name", group.getName())
.processPlaceholder("group_color", group.getColor())

View File

@ -1,5 +1,6 @@
package com.songoda.epicenchants.utils;
import com.songoda.core.utils.TextUtils;
import com.songoda.epicenchants.EpicEnchants;
import com.songoda.epicenchants.enums.EnchantResult;
import com.songoda.epicenchants.enums.EventType;
@ -132,9 +133,12 @@ public class EnchantUtils {
return itemStack;
}
String format = enchant.getFormat().replace("{level}", "").trim();
String text = format.isEmpty() ? enchant.getColoredIdentifier(false) : format;
nbtItem.getCompound("enchants").removeKey(enchant.getIdentifier());
ItemBuilder output = new ItemBuilder(nbtItem.getItem());
output.removeLore(enchant.getFormat().replace("{level}", "").trim());
output.removeLore(TextUtils.formatText(text));
return output.build();
}
}

View File

@ -1,5 +1,6 @@
package com.songoda.epicenchants.utils;
import com.songoda.core.compatibility.ServerVersion;
import com.songoda.epicenchants.EpicEnchants;
import org.bukkit.ChatColor;
import org.bukkit.Material;
@ -25,10 +26,10 @@ public class Methods {
int randomNum = 1 + (int) (Math.random() * 6);
ItemStack glass;
if (rainbow) {
glass = new ItemStack(EpicEnchants.getInstance().isServerVersionAtLeast(ServerVersion.V1_13) ?
glass = new ItemStack(ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13) ?
Material.LEGACY_STAINED_GLASS_PANE : Material.valueOf("STAINED_GLASS_PANE"), 1, (short) randomNum);
} else {
glass = new ItemStack(EpicEnchants.getInstance().isServerVersionAtLeast(ServerVersion.V1_13) ?
glass = new ItemStack(ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13) ?
Material.LEGACY_STAINED_GLASS_PANE : Material.valueOf("STAINED_GLASS_PANE"), 1, (short) type);
}
ItemMeta glassmeta = glass.getItemMeta();

View File

@ -1,27 +0,0 @@
package com.songoda.epicenchants.utils;
public enum ServerVersion {
UNKNOWN("unknown_server_version"),
V1_7("org.bukkit.craftbukkit.v1_7"),
V1_8("org.bukkit.craftbukkit.v1_8"),
V1_9("org.bukkit.craftbukkit.v1_9"),
V1_10("org.bukkit.craftbukkit.v1_10"),
V1_11("org.bukkit.craftbukkit.v1_11"),
V1_12("org.bukkit.craftbukkit.v1_12"),
V1_13("org.bukkit.craftbukkit.v1_13"),
V1_14("org.bukkit.craftbukkit.v1_14");
private final String packagePrefix;
private ServerVersion(String packagePrefix) {
this.packagePrefix = packagePrefix;
}
public static ServerVersion fromPackageName(String packageName) {
for (ServerVersion version : values())
if (packageName.startsWith(version.packagePrefix)) return version;
return ServerVersion.UNKNOWN;
}
}

View File

@ -1,37 +0,0 @@
package com.songoda.epicenchants.utils.itemnbtapi;
import org.bukkit.Bukkit;
public enum ClassWrapper {
CRAFT_ITEMSTACK("org.bukkit.craftbukkit.", ".inventory.CraftItemStack"),
CRAFT_ENTITY("org.bukkit.craftbukkit.", ".entity.CraftEntity"),
CRAFT_WORLD("org.bukkit.craftbukkit.", ".CraftWorld"),
NMS_NBTBASE("net.minecraft.server.", ".NBTBase"),
NMS_NBTTAGSTRING("net.minecraft.server.", ".NBTTagString"),
NMS_ITEMSTACK("net.minecraft.server.", ".ItemStack"),
NMS_NBTTAGCOMPOUND("net.minecraft.server.", ".NBTTagCompound"),
NMS_NBTTAGLIST("net.minecraft.server.", ".NBTTagList"),
NMS_NBTCOMPRESSEDSTREAMTOOLS("net.minecraft.server.", ".NBTCompressedStreamTools"),
NMS_MOJANGSONPARSER("net.minecraft.server.", ".MojangsonParser"),
NMS_TILEENTITY("net.minecraft.server.", ".TileEntity"),
NMS_BLOCKPOSITION("net.minecraft.server.", ".BlockPosition"),
NMS_WORLD("net.minecraft.server.", ".WorldServer"),
NMS_ENTITY("net.minecraft.server.", ".Entity"),;
private Class<?> clazz;
ClassWrapper(String pre, String suffix) {
try {
String version = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3];
clazz = Class.forName(pre + version + suffix);
} catch (Exception ex) {
ex.printStackTrace();
}
}
public Class<?> getClazz() {
return clazz;
}
}

View File

@ -1,10 +1,17 @@
package com.songoda.epicenchants.utils.itemnbtapi;
import com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion;
import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ReflectionMethod;
import java.io.Serializable;
import java.util.Set;
/**
* Base class representing NMS Compounds. For a standalone implementation check
* {@link NBTContainer}
*
* @author tr7zw
*/
public class NBTCompound {
private String compundName;
@ -15,11 +22,22 @@ public class NBTCompound {
this.parent = owner;
}
protected void saveCompound() {
if (parent != null)
parent.saveCompound();
}
/**
* @return The Compound name
*/
public String getName() {
return compundName;
}
protected Object getCompound() {
/**
* @return The NMS Compound behind this Object
*/
public Object getCompound() {
return parent.getCompound();
}
@ -27,18 +45,41 @@ public class NBTCompound {
parent.setCompound(compound);
}
/**
* @return The parent Compound
*/
public NBTCompound getParent() {
return parent;
}
/**
* Merges all data from comp into this compound. This is done in one action, so
* it also works with Tiles/Entities
*
* @param comp
*/
public void mergeCompound(NBTCompound comp) {
NBTReflectionUtil.addOtherNBTCompound(this, comp);
NBTReflectionUtil.mergeOtherNBTCompound(this, comp);
saveCompound();
}
/**
* Setter
*
* @param key
* @param value
*/
public void setString(String key, String value) {
NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_STRING, key, value);
saveCompound();
}
/**
* Getter
*
* @param key
* @return The stored value or NMS fallback
*/
public String getString(String key) {
return (String) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_STRING, key);
}
@ -47,153 +88,361 @@ public class NBTCompound {
return NBTReflectionUtil.getContent(this, key);
}
/**
* Setter
*
* @param key
* @param value
*/
public void setInteger(String key, Integer value) {
NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_INT, key, value);
saveCompound();
}
/**
* Getter
*
* @param key
* @return The stored value or NMS fallback
*/
public Integer getInteger(String key) {
return (Integer) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_INT, key);
}
/**
* Setter
*
* @param key
* @param value
*/
public void setDouble(String key, Double value) {
NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_DOUBLE, key, value);
saveCompound();
}
/**
* Getter
*
* @param key
* @return The stored value or NMS fallback
*/
public Double getDouble(String key) {
return (Double) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_DOUBLE, key);
}
/**
* Setter
*
* @param key
* @param value
*/
public void setByte(String key, Byte value) {
NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_BYTE, key, value);
saveCompound();
}
/**
* Getter
*
* @param key
* @return The stored value or NMS fallback
*/
public Byte getByte(String key) {
return (Byte) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_BYTE, key);
}
/**
* Setter
*
* @param key
* @param value
*/
public void setShort(String key, Short value) {
NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_SHORT, key, value);
saveCompound();
}
/**
* Getter
*
* @param key
* @return The stored value or NMS fallback
*/
public Short getShort(String key) {
return (Short) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_SHORT, key);
}
/**
* Setter
*
* @param key
* @param value
*/
public void setLong(String key, Long value) {
NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_LONG, key, value);
saveCompound();
}
/**
* Getter
*
* @param key
* @return The stored value or NMS fallback
*/
public Long getLong(String key) {
return (Long) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_LONG, key);
}
/**
* Setter
*
* @param key
* @param value
*/
public void setFloat(String key, Float value) {
NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_FLOAT, key, value);
saveCompound();
}
/**
* Getter
*
* @param key
* @return The stored value or NMS fallback
*/
public Float getFloat(String key) {
return (Float) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_FLOAT, key);
}
/**
* Setter
*
* @param key
* @param value
*/
public void setByteArray(String key, byte[] value) {
NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_BYTEARRAY, key, value);
saveCompound();
}
/**
* Getter
*
* @param key
* @return The stored value or NMS fallback
*/
public byte[] getByteArray(String key) {
return (byte[]) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_BYTEARRAY, key);
}
/**
* Setter
*
* @param key
* @param value
*/
public void setIntArray(String key, int[] value) {
NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_INTARRAY, key, value);
saveCompound();
}
/**
* Getter
*
* @param key
* @return The stored value or NMS fallback
*/
public int[] getIntArray(String key) {
return (int[]) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_INTARRAY, key);
}
/**
* Setter
*
* @param key
* @param value
*/
public void setBoolean(String key, Boolean value) {
NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_BOOLEAN, key, value);
saveCompound();
}
protected void set(String key, Object val) {
NBTReflectionUtil.set(this, key, val);
saveCompound();
}
/**
* Getter
*
* @param key
* @return The stored value or NMS fallback
*/
public Boolean getBoolean(String key) {
return (Boolean) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_BOOLEAN, key);
}
/**
* Uses Gson to store an {@link Serializable} Object
*
* @param key
* @param value
*/
public void setObject(String key, Object value) {
NBTReflectionUtil.setObject(this, key, value);
saveCompound();
}
/**
* Uses Gson to retrieve a stored Object
*
* @param key
* @param type Class of the Object
* @return The created Object or null if empty
*/
public <T> T getObject(String key, Class<T> type) {
return NBTReflectionUtil.getObject(this, key, type);
}
/**
* @param key
* @return True if the key is set
*/
public Boolean hasKey(String key) {
Boolean b = (Boolean) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_HAS_KEY, key);
if (b == null) return false;
if (b == null)
return false;
return b;
}
/**
* @param key Deletes the given Key
*/
public void removeKey(String key) {
NBTReflectionUtil.remove(this, key);
saveCompound();
}
/**
* @return Set of all stored Keys
*/
public Set<String> getKeys() {
return NBTReflectionUtil.getKeys(this);
}
/**
* Creates a subCompound
*
* @param name Key to use
* @return The subCompound Object
*/
public NBTCompound addCompound(String name) {
if (getType(name) == NBTType.NBTTagCompound) return getCompound(name);
if (getType(name) == NBTType.NBTTagCompound)
return getCompound(name);
NBTReflectionUtil.addNBTTagCompound(this, name);
return getCompound(name);
NBTCompound comp = getCompound(name);
if (comp == null)
throw new NbtApiException("Error while adding Compound, got null!");
saveCompound();
return comp;
}
/**
* @param name
* @return The Compound instance or null
*/
public NBTCompound getCompound(String name) {
if (getType(name) != NBTType.NBTTagCompound)
return null;
NBTCompound next = new NBTCompound(this, name);
if (NBTReflectionUtil.valideCompound(next)) return next;
if (NBTReflectionUtil.valideCompound(next))
return next;
return null;
}
public NBTList getList(String name, NBTType type) {
return NBTReflectionUtil.getList(this, name, type);
/**
* @param name
* @return The retrieved String List
*/
public NBTList<String> getStringList(String name) {
NBTList<String> list = NBTReflectionUtil.getList(this, name, NBTType.NBTTagString, String.class);
saveCompound();
return list;
}
/**
* @param name
* @return The retrieved Integer List
*/
public NBTList<Integer> getIntegerList(String name) {
NBTList<Integer> list = NBTReflectionUtil.getList(this, name, NBTType.NBTTagInt, Integer.class);
saveCompound();
return list;
}
/**
* @param name
* @return The retrieved Compound List
*/
public NBTCompoundList getCompoundList(String name) {
NBTCompoundList list = (NBTCompoundList) NBTReflectionUtil.getList(this, name, NBTType.NBTTagCompound, NBTListCompound.class);
saveCompound();
return list;
}
/**
* @param name
* @return The type of the given stored key or null
*/
public NBTType getType(String name) {
if (MinecraftVersion.getVersion() == MinecraftVersion.MC1_7_R4) return null;
if (MinecraftVersion.getVersion() == MinecraftVersion.MC1_7_R4)
return null;
Object o = NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_TYPE, name);
if (o == null) return null;
if (o == null)
return null;
return NBTType.valueOf((byte) o);
}
@Override
public String toString() {
StringBuilder result = new StringBuilder();
for (String key : getKeys()) {
result.append(toString(key));
}
return result.toString();
/*StringBuilder result = new StringBuilder();
for (String key : getKeys()) {
result.append(toString(key));
}
return result.toString();*/
return asNBTString();
}
/**
* @param key
* @return A string representation of the given key
* @deprecated Just use toString()
*/
@Deprecated
public String toString(String key) {
StringBuilder result = new StringBuilder();
NBTCompound compound = this;
while (compound.getParent() != null) {
result.append(" ");
compound = compound.getParent();
}
if (this.getType(key) == NBTType.NBTTagCompound) {
return this.getCompound(key).toString();
} else {
return result + "-" + key + ": " + getContent(key) + System.lineSeparator();
}
/*StringBuilder result = new StringBuilder();
NBTCompound compound = this;
while (compound.getParent() != null) {
result.append(" ");
compound = compound.getParent();
}
if (this.getType(key) == NBTType.NBTTagCompound) {
return this.getCompound(key).toString();
} else {
return result + "-" + key + ": " + getContent(key) + System.lineSeparator();
}*/
return asNBTString();
}
/**
* @return A json valid nbt string for this Compound
* @deprecated Just use toString()
*/
@Deprecated
public String asNBTString() {
Object comp = NBTReflectionUtil.gettoCompount(getCompound(), this);
if (comp == null) return "{}";
if (comp == null)
return "{}";
return comp.toString();
}

View File

@ -0,0 +1,108 @@
package com.songoda.epicenchants.utils.itemnbtapi;
import org.apache.commons.lang.NotImplementedException;
import com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion;
import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ClassWrapper;
import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ReflectionMethod;
/**
* {@link NBTListCompound} implementation for NBTLists
*
* @author tr7zw
*
*/
public class NBTCompoundList extends NBTList<NBTListCompound> {
protected NBTCompoundList(NBTCompound owner, String name, NBTType type, Object list) {
super(owner, name, type, list);
}
/**
* Adds a new Compound to the end of the List and returns it.
*
* @return The added {@link NBTListCompound}
*/
public NBTListCompound addCompound() {
return (NBTListCompound) addCompound(null);
}
/**
* Adds a copy of the Compound to the end of the List and returns it.
* When null is given, a new Compound will be created
*
* @param comp
* @return
*/
public NBTCompound addCompound(NBTCompound comp) {
try {
Object compound = ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz().newInstance();
if (MinecraftVersion.getVersion().getVersionId() >= MinecraftVersion.MC1_14_R1.getVersionId()) {
ReflectionMethod.LIST_ADD.run(listObject, size(), compound);
} else {
ReflectionMethod.LEGACY_LIST_ADD.run(listObject, compound);
}
getParent().saveCompound();
NBTListCompound listcomp = new NBTListCompound(this, compound);
if(comp != null){
listcomp.mergeCompound(comp);
}
return listcomp;
} catch (Exception ex) {
throw new NbtApiException(ex);
}
}
/**
* Adds a new Compound to the end of the List.
*
*
* @deprecated Please use addCompound!
* @param empty
* @return True, if compound was added
*/
@Override
@Deprecated
public boolean add(NBTListCompound empty) {
return addCompound(empty) != null;
}
@Override
public void add(int index, NBTListCompound element) {
if (element != null) {
throw new NotImplementedException("You need to pass null! ListCompounds from other lists won't work.");
}
try {
Object compound = ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz().newInstance();
if (MinecraftVersion.getVersion().getVersionId() >= MinecraftVersion.MC1_14_R1.getVersionId()) {
ReflectionMethod.LIST_ADD.run(listObject, index, compound);
} else {
ReflectionMethod.LEGACY_LIST_ADD.run(listObject, compound);
}
super.getParent().saveCompound();
} catch (Exception ex) {
throw new NbtApiException(ex);
}
}
@Override
public NBTListCompound get(int index) {
try {
Object compound = ReflectionMethod.LIST_GET_COMPOUND.run(listObject, index);
return new NBTListCompound(this, compound);
} catch (Exception ex) {
throw new NbtApiException(ex);
}
}
@Override
public NBTListCompound set(int index, NBTListCompound element) {
throw new NotImplementedException("This method doesn't work in the ListCompound context.");
}
@Override
protected Object asTag(NBTListCompound object) {
return null;
}
}

View File

@ -1,35 +1,60 @@
package com.songoda.epicenchants.utils.itemnbtapi;
import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ObjectCreator;
import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ReflectionMethod;
/**
* A Standalone {@link NBTCompound} implementation. All data is just kept inside
* this Object.
*
* @author tr7zw
*
*/
public class NBTContainer extends NBTCompound {
private Object nbt;
private Object nbt;
public NBTContainer() {
super(null, null);
nbt = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
}
/**
* Creates an empty, standalone NBTCompound
*/
public NBTContainer() {
super(null, null);
nbt = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
}
protected NBTContainer(Object nbt) {
super(null, null);
this.nbt = nbt;
}
/**
* Takes in any NMS Compound to wrap it
*
* @param nbt
*/
public NBTContainer(Object nbt) {
super(null, null);
this.nbt = nbt;
}
public NBTContainer(String nbtString) throws IllegalArgumentException {
super(null, null);
try {
nbt = ReflectionMethod.PARSE_NBT.run(null, nbtString);
} catch (Exception ex) {
ex.printStackTrace();
throw new IllegalArgumentException("Malformed Json: " + ex.getMessage());
}
}
/**
* Parses in a NBT String to a standalone {@link NBTCompound}. Can throw a
* {@link NbtApiException} in case something goes wrong.
*
* @param nbtString
*/
public NBTContainer(String nbtString) {
super(null, null);
try {
nbt = ReflectionMethod.PARSE_NBT.run(null, nbtString);
} catch (Exception ex) {
throw new NbtApiException("Unable to parse Malformed Json!", ex);
}
}
protected Object getCompound() {
return nbt;
}
@Override
public Object getCompound() {
return nbt;
}
protected void setCompound(Object tag) {
nbt = tag;
}
@Override
public void setCompound(Object tag) {
nbt = tag;
}
}

View File

@ -2,21 +2,34 @@ package com.songoda.epicenchants.utils.itemnbtapi;
import org.bukkit.entity.Entity;
/**
* NBT class to access vanilla tags from Entities. Entities don't support custom
* tags. Use the NBTInjector for custom tags. Changes will be instantly applied
* to the Entity, use the merge method to do many things at once.
*
* @author tr7zw
*
*/
public class NBTEntity extends NBTCompound {
private final Entity ent;
private final Entity ent;
public NBTEntity(Entity entity) {
super(null, null);
ent = entity;
}
/**
* @param entity Any valid Bukkit Entity
*/
public NBTEntity(Entity entity) {
super(null, null);
ent = entity;
}
protected Object getCompound() {
return NBTReflectionUtil.getEntityNBTTagCompound(NBTReflectionUtil.getNMSEntity(ent));
}
@Override
public Object getCompound() {
return NBTReflectionUtil.getEntityNBTTagCompound(NBTReflectionUtil.getNMSEntity(ent));
}
protected void setCompound(Object compound) {
NBTReflectionUtil.setEntityNBTTag(compound, NBTReflectionUtil.getNMSEntity(ent));
}
@Override
protected void setCompound(Object compound) {
NBTReflectionUtil.setEntityNBTTag(compound, NBTReflectionUtil.getNMSEntity(ent));
}
}

View File

@ -5,42 +5,68 @@ import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ObjectCreator;
/**
* {@link NBTCompound} implementation backed by a {@link File}
*
* @author tr7zw
*
*/
public class NBTFile extends NBTCompound {
private final File file;
private Object nbt;
private final File file;
private Object nbt;
public NBTFile(File file) throws IOException {
super(null, null);
this.file = file;
if (file.exists()) {
FileInputStream inputsteam = new FileInputStream(file);
nbt = NBTReflectionUtil.readNBTFile(inputsteam);
} else {
nbt = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
save();
}
}
/**
* Creates a NBTFile that uses @param file to store it's data. If this file
* exists, the data will be loaded.
*
* @param file
* @throws IOException
*/
public NBTFile(File file) throws IOException {
super(null, null);
this.file = file;
if (file.exists()) {
FileInputStream inputsteam = new FileInputStream(file);
nbt = NBTReflectionUtil.readNBTFile(inputsteam);
} else {
nbt = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
save();
}
}
public void save() throws IOException {
if (!file.exists()) {
file.getParentFile().mkdirs();
file.createNewFile();
}
FileOutputStream outStream = new FileOutputStream(file);
NBTReflectionUtil.saveNBTFile(nbt, outStream);
}
/**
* Saves the data to the file
*
* @throws IOException
*/
public void save() throws IOException {
if (!file.exists()) {
file.getParentFile().mkdirs();
if (!file.createNewFile())
throw new IOException("Unable to create file at " + file.getAbsolutePath());
}
FileOutputStream outStream = new FileOutputStream(file);
NBTReflectionUtil.saveNBTFile(nbt, outStream);
}
public File getFile() {
return file;
}
/**
* @return The File used to store the data
*/
public File getFile() {
return file;
}
protected Object getCompound() {
return nbt;
}
@Override
public Object getCompound() {
return nbt;
}
protected void setCompound(Object compound) {
nbt = compound;
}
@Override
protected void setCompound(Object compound) {
nbt = compound;
}
}

View File

@ -0,0 +1,45 @@
package com.songoda.epicenchants.utils.itemnbtapi;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ClassWrapper;
import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ReflectionMethod;
/**
* Integer implementation for NBTLists
*
* @author tr7zw
*
*/
public class NBTIntegerList extends NBTList<Integer> {
protected NBTIntegerList(NBTCompound owner, String name, NBTType type, Object list) {
super(owner, name, type, list);
}
@Override
protected Object asTag(Integer object) {
try {
Constructor<?> con = ClassWrapper.NMS_NBTTAGINT.getClazz().getDeclaredConstructor(int.class);
con.setAccessible(true);
return con.newInstance(object);
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
| NoSuchMethodException | SecurityException e) {
throw new NbtApiException("Error while wrapping the Object " + object + " to it's NMS object!", e);
}
}
@Override
public Integer get(int index) {
try {
Object obj = ReflectionMethod.LIST_GET.run(listObject, index);
return Integer.valueOf(obj.toString());
} catch (NumberFormatException nf) {
return 0;
} catch (Exception ex) {
throw new NbtApiException(ex);
}
}
}

View File

@ -2,51 +2,85 @@ package com.songoda.epicenchants.utils.itemnbtapi;
import org.bukkit.inventory.ItemStack;
import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ReflectionMethod;
/**
* NBT class to access vanilla/custom tags on ItemStacks. This class doesn't
* autosave to the Itemstack, use getItem to get the changed ItemStack
*
* @author tr7zw
*
*/
public class NBTItem extends NBTCompound {
private ItemStack bukkitItem;
private ItemStack bukkitItem;
public NBTItem(ItemStack item) {
super(null, null);
if (item == null) {
throw new NullPointerException("ItemStack can't be null!");
}
bukkitItem = item.clone();
}
/**
* Constructor for NBTItems. The ItemStack will be cloned!
*
* @param item
*/
public NBTItem(ItemStack item) {
super(null, null);
if (item == null) {
throw new NullPointerException("ItemStack can't be null!");
}
bukkitItem = item.clone();
}
public static NBTContainer convertItemtoNBT(ItemStack item) {
return NBTReflectionUtil.convertNMSItemtoNBTCompound(ReflectionMethod.ITEMSTACK_NMSCOPY.run(null, item));
}
@Override
public Object getCompound() {
return NBTReflectionUtil.getItemRootNBTTagCompound(ReflectionMethod.ITEMSTACK_NMSCOPY.run(null, bukkitItem));
}
public static ItemStack convertNBTtoItem(NBTCompound comp) {
return (ItemStack) ReflectionMethod.ITEMSTACK_BUKKITMIRROR.run(null, NBTReflectionUtil.convertNBTCompoundtoNMSItem(comp));
}
@Override
protected void setCompound(Object compound) {
Object stack = ReflectionMethod.ITEMSTACK_NMSCOPY.run(null, bukkitItem);
ReflectionMethod.ITEMSTACK_SET_TAG.run(stack, compound);
bukkitItem = (ItemStack) ReflectionMethod.ITEMSTACK_BUKKITMIRROR.run(null, stack);
}
protected Object getCompound() {
return NBTReflectionUtil.getItemRootNBTTagCompound(ReflectionMethod.ITEMSTACK_NMSCOPY.run(null, bukkitItem));
}
/**
* @return The modified ItemStack
*/
public ItemStack getItem() {
return bukkitItem;
}
protected void setCompound(Object compound) {
Object stack = ReflectionMethod.ITEMSTACK_NMSCOPY.run(null, bukkitItem);
ReflectionMethod.ITEMSTACK_SET_TAG.run(stack, compound);
bukkitItem = (ItemStack) ReflectionMethod.ITEMSTACK_BUKKITMIRROR.run(null, stack);
}
protected void setItem(ItemStack item) {
bukkitItem = item;
}
public ItemStack getItem() {
return bukkitItem;
}
/**
* This may return true even when the NBT is empty.
*
* @return Does the ItemStack have a NBTCompound.
*/
public boolean hasNBTData() {
return getCompound() != null;
}
protected void setItem(ItemStack item) {
bukkitItem = item;
}
/**
* Helper method that converts {@link ItemStack} to {@link NBTContainer} with
* all it's data like Material, Damage, Amount and Tags.
*
* @param item
* @return Standalone {@link NBTContainer} with the Item's data
*/
public static NBTContainer convertItemtoNBT(ItemStack item) {
return NBTReflectionUtil.convertNMSItemtoNBTCompound(ReflectionMethod.ITEMSTACK_NMSCOPY.run(null, item));
}
/**
* This may return true even when the NBT is empty.
*
* @return Does the ItemStack have a NBTCompound.
*/
public boolean hasNBTData() {
return getCompound() != null;
}
/**
* Helper method to do the inverse to "convertItemtoNBT". Creates an
* {@link ItemStack} using the {@link NBTCompound}
*
* @param comp
* @return ItemStack using the {@link NBTCompound}'s data
*/
public static ItemStack convertNBTtoItem(NBTCompound comp) {
return (ItemStack) ReflectionMethod.ITEMSTACK_BUKKITMIRROR.run(null,
NBTReflectionUtil.convertNBTCompoundtoNMSItem(comp));
}
}

View File

@ -1,127 +1,335 @@
package com.songoda.epicenchants.utils.itemnbtapi;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.NoSuchElementException;
import com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion;
import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ReflectionMethod;
public class NBTList {
/**
* Abstract List implementation for ListCompounds
*
* @author tr7zw
*
* @param <T>
*/
public abstract class NBTList<T> implements List<T> {
private String listName;
private NBTCompound parent;
private NBTType type;
private Object listObject;
private String listName;
private NBTCompound parent;
private NBTType type;
protected Object listObject;
protected NBTList(NBTCompound owner, String name, NBTType type, Object list) {
parent = owner;
listName = name;
this.type = type;
this.listObject = list;
if (!(type == NBTType.NBTTagString || type == NBTType.NBTTagCompound)) {
System.err.println("List types != String/Compound are currently not implemented!");
}
}
protected NBTList(NBTCompound owner, String name, NBTType type, Object list) {
parent = owner;
listName = name;
this.type = type;
this.listObject = list;
}
/**
* @return Name of this list-compound
*/
public String getName(){
return listName;
}
/**
* @return The Compound's parent Object
*/
public NBTCompound getParent() {
return parent;
}
protected void save() {
parent.set(listName, listObject);
}
protected void save() {
parent.set(listName, listObject);
}
public NBTListCompound addCompound() {
if (type != NBTType.NBTTagCompound) {
new Throwable("Using Compound method on a non Compound list!").printStackTrace();
return null;
}
try {
Object compound = ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz().newInstance();
if (MinecraftVersion.getVersion().getVersionId() >= MinecraftVersion.MC1_14_R1.getVersionId()) {
ReflectionMethod.LIST_ADD.run(listObject, 0, compound);
} else {
ReflectionMethod.LEGACY_LIST_ADD.run(listObject, compound);
}
return new NBTListCompound(this, compound);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
protected abstract Object asTag(T object);
public NBTListCompound getCompound(int id) {
if (type != NBTType.NBTTagCompound) {
new Throwable("Using Compound method on a non Compound list!").printStackTrace();
return null;
}
try {
Object compound = ReflectionMethod.LIST_GET.run(listObject, id);
return new NBTListCompound(this, compound);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
@Override
public boolean add(T element) {
try {
if (MinecraftVersion.getVersion().getVersionId() >= MinecraftVersion.MC1_14_R1.getVersionId()) {
ReflectionMethod.LIST_ADD.run(listObject, size(), asTag(element));
} else {
ReflectionMethod.LEGACY_LIST_ADD.run(listObject, asTag(element));
}
save();
return true;
} catch (Exception ex) {
throw new NbtApiException(ex);
}
}
public String getString(int i) {
if (type != NBTType.NBTTagString) {
new Throwable("Using String method on a non String list!").printStackTrace();
return null;
}
try {
return (String) ReflectionMethod.LIST_GET_STRING.run(listObject, i);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
@Override
public void add(int index, T element) {
try {
if (MinecraftVersion.getVersion().getVersionId() >= MinecraftVersion.MC1_14_R1.getVersionId()) {
ReflectionMethod.LIST_ADD.run(listObject, index, asTag(element));
} else {
ReflectionMethod.LEGACY_LIST_ADD.run(listObject, asTag(element));
}
save();
} catch (Exception ex) {
throw new NbtApiException(ex);
}
}
public void addString(String s) {
if (type != NBTType.NBTTagString) {
new Throwable("Using String method on a non String list!").printStackTrace();
return;
}
try {
if (MinecraftVersion.getVersion().getVersionId() >= MinecraftVersion.MC1_14_R1.getVersionId()) {
ReflectionMethod.LIST_ADD.run(listObject, 0,
ClassWrapper.NMS_NBTTAGSTRING.getClazz().getConstructor(String.class).newInstance(s));
} else {
ReflectionMethod.LEGACY_LIST_ADD.run(listObject,
ClassWrapper.NMS_NBTTAGSTRING.getClazz().getConstructor(String.class).newInstance(s));
}
save();
} catch (Exception ex) {
ex.printStackTrace();
}
}
@Override
public T set(int index, T element) {
try {
T prev = get(index);
ReflectionMethod.LIST_SET.run(listObject, index, asTag(element));
save();
return prev;
} catch (Exception ex) {
throw new NbtApiException(ex);
}
}
public void setString(int i, String s) {
if (type != NBTType.NBTTagString) {
new Throwable("Using String method on a non String list!").printStackTrace();
return;
}
try {
ReflectionMethod.LIST_SET.run(listObject, i,
ClassWrapper.NMS_NBTTAGSTRING.getClazz().getConstructor(String.class).newInstance(s));
save();
} catch (Exception ex) {
ex.printStackTrace();
}
}
public T remove(int i) {
try {
T old = get(i);
ReflectionMethod.LIST_REMOVE_KEY.run(listObject, i);
save();
return old;
} catch (Exception ex) {
throw new NbtApiException(ex);
}
}
public void remove(int i) {
try {
ReflectionMethod.LIST_REMOVE_KEY.run(listObject, i);
save();
} catch (Exception ex) {
ex.printStackTrace();
}
}
public int size() {
try {
return (int) ReflectionMethod.LIST_SIZE.run(listObject);
} catch (Exception ex) {
throw new NbtApiException(ex);
}
}
public int size() {
try {
return (int) ReflectionMethod.LIST_SIZE.run(listObject);
} catch (Exception ex) {
ex.printStackTrace();
}
return -1;
}
/**
* @return The type that this list contains
*/
public NBTType getType() {
return type;
}
public NBTType getType() {
return type;
}
@Override
public boolean isEmpty() {
return size() == 0;
}
}
@Override
public void clear() {
while (!isEmpty()) {
remove(0);
}
}
@Override
public boolean contains(Object o) {
for (int i = 0; i < size(); i++) {
if (o.equals(get(i)))
return true;
}
return false;
}
@Override
public int indexOf(Object o) {
for (int i = 0; i < size(); i++) {
if (o.equals(get(i)))
return i;
}
return -1;
}
@Override
public boolean addAll(Collection<? extends T> c) {
int size = size();
for (T ele : c) {
add(ele);
}
return size != size();
}
@Override
public boolean addAll(int index, Collection<? extends T> c) {
int size = size();
for (T ele : c) {
add(index++, ele);
}
return size != size();
}
@Override
public boolean containsAll(Collection<?> c) {
for (Object ele : c) {
if (!contains(ele))
return false;
}
return true;
}
@Override
public int lastIndexOf(Object o) {
int index = -1;
for (int i = 0; i < size(); i++) {
if (o.equals(get(i)))
index = i;
}
return index;
}
@Override
public boolean removeAll(Collection<?> c) {
int size = size();
for (Object obj : c) {
remove(obj);
}
return size != size();
}
@Override
public boolean retainAll(Collection<?> c) {
int size = size();
for (Object obj : c) {
for (int i = 0; i < size(); i++) {
if (!obj.equals(get(i))) {
remove(i--);
}
}
}
return size != size();
}
@Override
public boolean remove(Object o) {
int size = size();
int id = -1;
while ((id = indexOf(o)) != -1) {
remove(id);
}
return size != size();
}
@Override
public Iterator<T> iterator() {
return new Iterator<T>() {
private int index = 0;
@Override
public boolean hasNext() {
return size() > index + 1;
}
@Override
public T next() {
if (!hasNext())
throw new NoSuchElementException();
return get(++index);
}
};
}
@Override
public ListIterator<T> listIterator() {
return listIterator(0);
}
@Override
public ListIterator<T> listIterator(int startIndex) {
final NBTList<T> list = this;
return new ListIterator<T>() {
int index = startIndex;
@Override
public void add(T e) {
list.add(index, e);
}
@Override
public boolean hasNext() {
return size() > index + 1;
}
@Override
public boolean hasPrevious() {
return index > 0;
}
@Override
public T next() {
if (!hasNext())
throw new NoSuchElementException();
return get(++index);
}
@Override
public int nextIndex() {
return index + 1;
}
@Override
public T previous() {
return get(--index);
}
@Override
public int previousIndex() {
return index - 1;
}
@Override
public void remove() {
list.remove(index);
}
@Override
public void set(T e) {
list.set(index, e);
}
};
}
@Override
public Object[] toArray() {
Object[] ar = new Object[size()];
for (int i = 0; i < size(); i++)
ar[i] = get(i);
return ar;
}
@SuppressWarnings("unchecked")
@Override
public <E> E[] toArray(E[] a) {
E[] ar = Arrays.copyOf(a, size());
Arrays.fill(ar, null);
Class<?> arrayclass = a.getClass().getComponentType();
for (int i = 0; i < size(); i++) {
T obj = get(i);
if (arrayclass.isInstance(obj)) {
ar[i] = (E) get(i);
} else {
throw new ArrayStoreException("The array does not match the objects stored in the List.");
}
}
return ar;
}
@Override
public List<T> subList(int fromIndex, int toIndex) {
ArrayList<T> list = new ArrayList<>();
for (int i = fromIndex; i < toIndex; i++)
list.add(get(i));
return list;
}
}

View File

@ -1,102 +1,42 @@
package com.songoda.epicenchants.utils.itemnbtapi;
import java.util.HashSet;
import java.util.Set;
/**
* Cut down version of the {@link NBTCompound} for inside
* {@link NBTCompoundList} This Compound implementation is missing the ability
* for further subCompounds and Lists. This class probably will change in the
* future
*
* @author tr7zw
*
*/
public class NBTListCompound extends NBTCompound {
public class NBTListCompound {
private NBTList<?> owner;
private Object compound;
private NBTList owner;
private Object compound;
protected NBTListCompound(NBTList<?> parent, Object obj) {
super(null, null);
owner = parent;
compound = obj;
}
public NBTList<?> getListParent() {
return owner;
}
protected NBTListCompound(NBTList parent, Object obj) {
owner = parent;
compound = obj;
}
@Override
public Object getCompound() {
return compound;
}
public void setString(String key, String value) {
if (value == null) {
remove(key);
return;
}
try {
compound.getClass().getMethod("setString", String.class, String.class).invoke(compound, key, value);
owner.save();
} catch (Exception ex) {
ex.printStackTrace();
}
}
@Override
protected void setCompound(Object compound) {
this.compound = compound;
}
public void setInteger(String key, int value) {
try {
compound.getClass().getMethod("setInt", String.class, int.class).invoke(compound, key, value);
owner.save();
} catch (Exception ex) {
ex.printStackTrace();
}
}
public int getInteger(String value) {
try {
return (int) compound.getClass().getMethod("getInt", String.class).invoke(compound, value);
} catch (Exception ex) {
ex.printStackTrace();
}
return 0;
}
public void setDouble(String key, double value) {
try {
compound.getClass().getMethod("setDouble", String.class, double.class).invoke(compound, key, value);
owner.save();
} catch (Exception ex) {
ex.printStackTrace();
}
}
public double getDouble(String key) {
try {
return (double) compound.getClass().getMethod("getDouble", String.class).invoke(compound, key);
} catch (Exception ex) {
ex.printStackTrace();
}
return 0;
}
public String getString(String key) {
try {
return (String) compound.getClass().getMethod("getString", String.class).invoke(compound, key);
} catch (Exception ex) {
ex.printStackTrace();
}
return "";
}
public boolean hasKey(String key) {
try {
return (boolean) compound.getClass().getMethod("hasKey", String.class).invoke(compound, key);
} catch (Exception ex) {
ex.printStackTrace();
}
return false;
}
@SuppressWarnings("unchecked")
public Set<String> getKeys() {
try {
return (Set<String>) ReflectionMethod.LISTCOMPOUND_GET_KEYS.run(compound);
} catch (Exception ex) {
ex.printStackTrace();
}
return new HashSet<>();
}
public void remove(String key) {
try {
compound.getClass().getMethod("remove", String.class).invoke(compound, key);
} catch (Exception ex) {
ex.printStackTrace();
}
}
@Override
protected void saveCompound() {
owner.save();
}
}

View File

@ -1,347 +1,498 @@
package com.songoda.epicenchants.utils.itemnbtapi;
import com.songoda.epicenchants.utils.itemnbtapi.utils.GsonWrapper;
import com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion;
import org.bukkit.block.BlockState;
import org.bukkit.entity.Entity;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.io.Serializable;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Set;
import java.util.Stack;
import org.bukkit.block.BlockState;
import org.bukkit.entity.Entity;
import com.songoda.epicenchants.utils.itemnbtapi.utils.GsonWrapper;
import com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion;
import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ClassWrapper;
import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ObjectCreator;
import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ReflectionMethod;
/**
* Utility class for translating NBTApi calls to reflections into NMS code All
* methods are allowed to throw {@link NbtApiException}
*
* @author tr7zw
*
*/
public class NBTReflectionUtil {
public static Object getNMSEntity(Entity entity) {
try {
return ReflectionMethod.CRAFT_ENTITY_GET_HANDLE.run(ClassWrapper.CRAFT_ENTITY.getClazz().cast(entity));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* Hidden constructor
*/
private NBTReflectionUtil() {
public static Object readNBTFile(FileInputStream stream) {
try {
return ReflectionMethod.NBTFILE_READ.run(null, stream);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
public static Object saveNBTFile(Object nbt, FileOutputStream stream) {
try {
return ReflectionMethod.NBTFILE_WRITE.run(null, nbt, stream);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* Gets the NMS Entity for a given Bukkit Entity
*
* @param entity Bukkit Entity
* @return NMS Entity
*/
public static Object getNMSEntity(Entity entity) {
try {
return ReflectionMethod.CRAFT_ENTITY_GET_HANDLE.run(ClassWrapper.CRAFT_ENTITY.getClazz().cast(entity));
} catch (Exception e) {
throw new NbtApiException("Exception while getting the NMS Entity from a Bukkit Entity!", e);
}
}
@SuppressWarnings({"unchecked"})
public static Object getItemRootNBTTagCompound(Object nmsitem) {
@SuppressWarnings("rawtypes")
Class clazz = nmsitem.getClass();
Method method;
try {
method = clazz.getMethod("getTag");
Object answer = method.invoke(nmsitem);
return answer;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* Reads in a FileInputStream as NMS Compound
*
* @param stream InputStream of any NBT file
* @return NMS Compound
*/
public static Object readNBTFile(FileInputStream stream) {
try {
return ReflectionMethod.NBTFILE_READ.run(null, stream);
} catch (Exception e) {
throw new NbtApiException("Exception while reading a NBT File!", e);
}
}
@SuppressWarnings({"unchecked"})
public static Object convertNBTCompoundtoNMSItem(NBTCompound nbtcompound) {
@SuppressWarnings("rawtypes")
Class clazz = ClassWrapper.NMS_ITEMSTACK.getClazz();
try {
if (MinecraftVersion.getVersion().getVersionId() >= MinecraftVersion.MC1_12_R1.getVersionId()) {
Constructor<?> constructor = clazz.getConstructor(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz());
constructor.setAccessible(true);
return constructor.newInstance(nbtcompound.getCompound());
} else {
Method method = clazz.getMethod("createStack", ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz());
method.setAccessible(true);
return method.invoke(null, nbtcompound.getCompound());
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* Writes a NMS Compound to a FileOutputStream
*
* @param nbt NMS Compound
* @param stream Stream to write to
* @return ???
*/
public static Object saveNBTFile(Object nbt, FileOutputStream stream) {
try {
return ReflectionMethod.NBTFILE_WRITE.run(null, nbt, stream);
} catch (Exception e) {
throw new NbtApiException("Exception while saving a NBT File!", e);
}
}
@SuppressWarnings({"unchecked"})
public static NBTContainer convertNMSItemtoNBTCompound(Object nmsitem) {
@SuppressWarnings("rawtypes")
Class clazz = nmsitem.getClass();
Method method;
try {
method = clazz.getMethod("save", ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz());
Object answer = method.invoke(nmsitem, ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance());
return new NBTContainer(answer);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* Simulates getOrCreateTag. If an Item doesn't yet have a Tag, it will return a
* new empty tag.
*
* @param nmsitem
* @return NMS Compound
*/
public static Object getItemRootNBTTagCompound(Object nmsitem) {
try {
Object answer = ReflectionMethod.NMSITEM_GETTAG.run(nmsitem);
return answer != null ? answer : ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
} catch (Exception e) {
throw new NbtApiException("Exception while getting an Itemstack's NBTCompound!", e);
}
}
public static Object getEntityNBTTagCompound(Object NMSEntity) {
try {
Object nbt = ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz().newInstance();
Object answer = ReflectionMethod.NMS_ENTITY_GET_NBT.run(NMSEntity, nbt);
if (answer == null)
answer = nbt;
return answer;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* Converts {@link NBTCompound} to NMS ItemStacks
*
* @param nbtcompound Any valid {@link NBTCompound}
* @return NMS ItemStack
*/
public static Object convertNBTCompoundtoNMSItem(NBTCompound nbtcompound) {
try {
if (MinecraftVersion.getVersion().getVersionId() >= MinecraftVersion.MC1_11_R1.getVersionId()) {
return ObjectCreator.NMS_COMPOUNDFROMITEM.getInstance(nbtcompound.getCompound());
} else {
return ReflectionMethod.NMSITEM_CREATESTACK.run(null, nbtcompound.getCompound());
}
} catch (Exception e) {
throw new NbtApiException("Exception while converting NBTCompound to NMS ItemStack!", e);
}
}
public static Object setEntityNBTTag(Object NBTTag, Object NMSEntity) {
try {
ReflectionMethod.NMS_ENTITY_SET_NBT.run(NMSEntity, NBTTag);
return NMSEntity;
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
/**
* Converts NMS ItemStacks to {@link NBTContainer}
*
* @param nmsitem NMS ItemStack
* @return {@link NBTContainer} with all the data
*/
public static NBTContainer convertNMSItemtoNBTCompound(Object nmsitem) {
try {
Object answer = ReflectionMethod.NMSITEM_SAVE.run(nmsitem, ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance());
return new NBTContainer(answer);
} catch (Exception e) {
throw new NbtApiException("Exception while converting NMS ItemStack to NBTCompound!", e);
}
}
public static Object getTileEntityNBTTagCompound(BlockState tile) {
try {
Object pos = ObjectCreator.NMS_BLOCKPOSITION.getInstance(tile.getX(), tile.getY(), tile.getZ());
Object cworld = ClassWrapper.CRAFT_WORLD.getClazz().cast(tile.getWorld());
Object nmsworld = ReflectionMethod.CRAFT_WORLD_GET_HANDLE.run(cworld);
Object o = ReflectionMethod.NMS_WORLD_GET_TILEENTITY.run(nmsworld, pos);
Object tag = ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz().newInstance();
Object answer = ReflectionMethod.TILEENTITY_GET_NBT.run(o, tag);
if (answer == null)
answer = tag;
return answer;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* Gets the Vanilla NBT Compound from a given NMS Entity
*
* @param nmsEntity
* @return NMS NBT Compound
*/
public static Object getEntityNBTTagCompound(Object nmsEntity) {
try {
Object nbt = ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz().newInstance();
Object answer = ReflectionMethod.NMS_ENTITY_GET_NBT.run(nmsEntity, nbt);
if (answer == null)
answer = nbt;
return answer;
} catch (Exception e) {
throw new NbtApiException("Exception while getting NBTCompound from NMS Entity!", e);
}
}
public static void setTileEntityNBTTagCompound(BlockState tile, Object comp) {
try {
Object pos = ObjectCreator.NMS_BLOCKPOSITION.getInstance(tile.getX(), tile.getY(), tile.getZ());
Object cworld = ClassWrapper.CRAFT_WORLD.getClazz().cast(tile.getWorld());
Object nmsworld = ReflectionMethod.CRAFT_WORLD_GET_HANDLE.run(cworld);
Object o = ReflectionMethod.NMS_WORLD_GET_TILEENTITY.run(nmsworld, pos);
ReflectionMethod.TILEENTITY_SET_NBT.run(o, comp);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Loads all Vanilla tags from a NMS Compound into a NMS Entity
*
* @param nbtTag
* @param nmsEntity
* @return The NMS Entity
*/
public static Object setEntityNBTTag(Object nbtTag, Object nmsEntity) {
try {
ReflectionMethod.NMS_ENTITY_SET_NBT.run(nmsEntity, nbtTag);
return nmsEntity;
} catch (Exception ex) {
throw new NbtApiException("Exception while setting the NBTCompound of an Entity", ex);
}
}
/**
* Gets the NMS Compound from a given TileEntity
*
* @param tile
* @return NMS Compound with the Vanilla data
*/
public static Object getTileEntityNBTTagCompound(BlockState tile) {
try {
Object pos = ObjectCreator.NMS_BLOCKPOSITION.getInstance(tile.getX(), tile.getY(), tile.getZ());
Object cworld = ClassWrapper.CRAFT_WORLD.getClazz().cast(tile.getWorld());
Object nmsworld = ReflectionMethod.CRAFT_WORLD_GET_HANDLE.run(cworld);
Object o = ReflectionMethod.NMS_WORLD_GET_TILEENTITY.run(nmsworld, pos);
Object tag = ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz().newInstance();
Object answer = ReflectionMethod.TILEENTITY_GET_NBT.run(o, tag);
if (answer == null)
answer = tag;
return answer;
} catch (Exception e) {
throw new NbtApiException("Exception while getting NBTCompound from TileEntity!", e);
}
}
@SuppressWarnings("unchecked")
public static Object getSubNBTTagCompound(Object compound, String name) {
@SuppressWarnings("rawtypes")
Class c = compound.getClass();
Method method;
try {
method = c.getMethod("getCompound", String.class);
Object answer = method.invoke(compound, name);
return answer;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* Sets Vanilla tags from a NMS Compound to a TileEntity
*
* @param tile
* @param comp
*/
public static void setTileEntityNBTTagCompound(BlockState tile, Object comp) {
try {
Object pos = ObjectCreator.NMS_BLOCKPOSITION.getInstance(tile.getX(), tile.getY(), tile.getZ());
Object cworld = ClassWrapper.CRAFT_WORLD.getClazz().cast(tile.getWorld());
Object nmsworld = ReflectionMethod.CRAFT_WORLD_GET_HANDLE.run(cworld);
Object o = ReflectionMethod.NMS_WORLD_GET_TILEENTITY.run(nmsworld, pos);
ReflectionMethod.TILEENTITY_SET_NBT.run(o, comp);
} catch (Exception e) {
throw new NbtApiException("Exception while setting NBTData for a TileEntity!", e);
}
}
public static void addNBTTagCompound(NBTCompound comp, String name) {
if (name == null) {
remove(comp, name);
return;
}
Object nbttag = comp.getCompound();
if (nbttag == null) {
nbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
}
if (!valideCompound(comp)) return;
Object workingtag = gettoCompount(nbttag, comp);
Method method;
try {
method = workingtag.getClass().getMethod("set", String.class, ClassWrapper.NMS_NBTBASE.getClazz());
method.invoke(workingtag, name, ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz().newInstance());
comp.setCompound(nbttag);
return;
} catch (Exception ex) {
ex.printStackTrace();
}
return;
}
/**
* Gets the subCompound with a given name from a NMS Compound
*
* @param compound
* @param name
* @return NMS Compound or null
*/
public static Object getSubNBTTagCompound(Object compound, String name) {
try {
if ((boolean) ReflectionMethod.COMPOUND_HAS_KEY.run(compound, name)) {
return ReflectionMethod.COMPOUND_GET_COMPOUND.run(compound, name);
} else {
throw new NbtApiException("Tried getting invalide compound '" + name + "' from '" + compound + "'!");
}
} catch (Exception e) {
throw new NbtApiException("Exception while getting NBT subcompounds!", e);
}
}
public static Boolean valideCompound(NBTCompound comp) {
Object root = comp.getCompound();
if (root == null) {
root = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
}
return (gettoCompount(root, comp)) != null;
}
/**
* Creates a subCompound with a given name in the given NMS Compound
*
* @param comp
* @param name
*/
public static void addNBTTagCompound(NBTCompound comp, String name) {
if (name == null) {
remove(comp, name);
return;
}
Object nbttag = comp.getCompound();
if (nbttag == null) {
nbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
}
if (!valideCompound(comp))
return;
Object workingtag = gettoCompount(nbttag, comp);
try {
ReflectionMethod.COMPOUND_SET.run(workingtag, name,
ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz().newInstance());
comp.setCompound(nbttag);
} catch (Exception e) {
throw new NbtApiException("Exception while adding a Compound!", e);
}
}
static Object gettoCompount(Object nbttag, NBTCompound comp) {
Stack<String> structure = new Stack<>();
while (comp.getParent() != null) {
structure.add(comp.getName());
comp = comp.getParent();
}
while (!structure.isEmpty()) {
nbttag = getSubNBTTagCompound(nbttag, structure.pop());
if (nbttag == null) {
return null;
}
}
return nbttag;
}
/**
* Checks if the Compound is correctly linked to it's roots
*
* @param comp
* @return true if this is a valide Compound, else false
*/
public static Boolean valideCompound(NBTCompound comp) {
Object root = comp.getCompound();
if (root == null) {
root = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
}
return (gettoCompount(root, comp)) != null;
}
public static void addOtherNBTCompound(NBTCompound comp, NBTCompound nbtcompound) {
Object rootnbttag = comp.getCompound();
if (rootnbttag == null) {
rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
}
if (!valideCompound(comp)) return;
Object workingtag = gettoCompount(rootnbttag, comp);
try {
ReflectionMethod.COMPOUND_ADD.run(workingtag, nbtcompound.getCompound());
comp.setCompound(rootnbttag);
} catch (Exception ex) {
ex.printStackTrace();
}
}
protected static Object gettoCompount(Object nbttag, NBTCompound comp) {
Deque<String> structure = new ArrayDeque<>();
while (comp.getParent() != null) {
structure.add(comp.getName());
comp = comp.getParent();
}
while (!structure.isEmpty()) {
String target = structure.pollLast();
nbttag = getSubNBTTagCompound(nbttag, target);
if (nbttag == null) {
throw new NbtApiException("Unable to find tag '" + target + "' in " + nbttag);
}
}
return nbttag;
}
public static String getContent(NBTCompound comp, String key) {
Object rootnbttag = comp.getCompound();
if (rootnbttag == null) {
rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
}
if (!valideCompound(comp)) return null;
Object workingtag = gettoCompount(rootnbttag, comp);
Method method;
try {
method = workingtag.getClass().getMethod("get", String.class);
return method.invoke(workingtag, key).toString();
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
/**
* Merges the second {@link NBTCompound} into the first one
*
* @param comp Target for the merge
* @param nbtcompound Data to merge
*/
public static void mergeOtherNBTCompound(NBTCompound comp, NBTCompound nbtcompound) {
Object rootnbttag = comp.getCompound();
if (rootnbttag == null) {
rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
}
if (!valideCompound(comp))
throw new NbtApiException("The Compound wasn't able to be linked back to the root!");
Object workingtag = gettoCompount(rootnbttag, comp);
try {
ReflectionMethod.COMPOUND_MERGE.run(workingtag, nbtcompound.getCompound());
comp.setCompound(rootnbttag);
} catch (Exception e) {
throw new NbtApiException("Exception while merging two NBTCompounds!", e);
}
}
public static void set(NBTCompound comp, String key, Object val) {
if (val == null) {
remove(comp, key);
return;
}
Object rootnbttag = comp.getCompound();
if (rootnbttag == null) {
rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
}
if (!valideCompound(comp)) {
new Throwable("InvalideCompound").printStackTrace();
return;
}
Object workingtag = gettoCompount(rootnbttag, comp);
Method method;
try {
method = workingtag.getClass().getMethod("set", String.class, ClassWrapper.NMS_NBTBASE.getClazz());
method.invoke(workingtag, key, val);
comp.setCompound(rootnbttag);
} catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* Returns the content for a given key inside a Compound
*
* @param comp
* @param key
* @return Content saved under this key
*/
public static String getContent(NBTCompound comp, String key) {
Object rootnbttag = comp.getCompound();
if (rootnbttag == null) {
rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
}
if (!valideCompound(comp))
throw new NbtApiException("The Compound wasn't able to be linked back to the root!");
Object workingtag = gettoCompount(rootnbttag, comp);
try {
return ReflectionMethod.COMPOUND_GET.run(workingtag, key).toString();
} catch (Exception e) {
throw new NbtApiException("Exception while getting the Content for key '" + key + "'!", e);
}
}
public static NBTList getList(NBTCompound comp, String key, NBTType type) {
Object rootnbttag = comp.getCompound();
if (rootnbttag == null) {
rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
}
if (!valideCompound(comp)) return null;
Object workingtag = gettoCompount(rootnbttag, comp);
Method method;
try {
method = workingtag.getClass().getMethod("getList", String.class, int.class);
return new NBTList(comp, key, type, method.invoke(workingtag, key, type.getId()));
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
/**
* Sets a key in a {@link NBTCompound} to a given value
*
* @param comp
* @param key
* @param val
*/
public static void set(NBTCompound comp, String key, Object val) {
if (val == null) {
remove(comp, key);
return;
}
Object rootnbttag = comp.getCompound();
if (rootnbttag == null) {
rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
}
if (!valideCompound(comp)) {
throw new NbtApiException("The Compound wasn't able to be linked back to the root!");
}
Object workingtag = gettoCompount(rootnbttag, comp);
try {
ReflectionMethod.COMPOUND_SET.run(workingtag, key, val);
comp.setCompound(rootnbttag);
} catch (Exception e) {
throw new NbtApiException("Exception while setting key '" + key + "' to '" + val + "'!", e);
}
}
public static void setObject(NBTCompound comp, String key, Object value) {
if (!MinecraftVersion.hasGsonSupport()) return;
try {
String json = GsonWrapper.getString(value);
setData(comp, ReflectionMethod.COMPOUND_SET_STRING, key, json);
} catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* Returns the List saved with a given key.
*
* @param comp
* @param key
* @param type
* @param clazz
* @return The list at that key. Null if it's an invalide type
*/
@SuppressWarnings("unchecked")
public static <T> NBTList<T> getList(NBTCompound comp, String key, NBTType type, Class<T> clazz) {
Object rootnbttag = comp.getCompound();
if (rootnbttag == null) {
rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
}
if (!valideCompound(comp))
return null;
Object workingtag = gettoCompount(rootnbttag, comp);
try {
Object nbt = ReflectionMethod.COMPOUND_GET_LIST.run(workingtag, key, type.getId());
if (clazz == String.class) {
return (NBTList<T>) new NBTStringList(comp, key, type, nbt);
} else if (clazz == NBTListCompound.class) {
return (NBTList<T>) new NBTCompoundList(comp, key, type, nbt);
} else if (clazz == Integer.class) {
return (NBTList<T>) new NBTIntegerList(comp, key, type, nbt);
} else {
return null;
}
} catch (Exception ex) {
throw new NbtApiException("Exception while getting a list with the type '" + type + "'!", ex);
}
}
public static <T> T getObject(NBTCompound comp, String key, Class<T> type) {
if (!MinecraftVersion.hasGsonSupport()) return null;
String json = (String) getData(comp, ReflectionMethod.COMPOUND_GET_STRING, key);
if (json == null) {
return null;
}
return GsonWrapper.deserializeJson(json, type);
}
/**
* Uses Gson to set a {@link Serializable} value in a Compound
*
* @param comp
* @param key
* @param value
*/
public static void setObject(NBTCompound comp, String key, Object value) {
if (!MinecraftVersion.hasGsonSupport())
return;
try {
String json = GsonWrapper.getString(value);
setData(comp, ReflectionMethod.COMPOUND_SET_STRING, key, json);
} catch (Exception e) {
throw new NbtApiException("Exception while setting the Object '" + value + "'!", e);
}
}
public static void remove(NBTCompound comp, String key) {
Object rootnbttag = comp.getCompound();
if (rootnbttag == null) {
rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
}
if (!valideCompound(comp)) return;
Object workingtag = gettoCompount(rootnbttag, comp);
ReflectionMethod.COMPOUND_REMOVE_KEY.run(workingtag, key);
comp.setCompound(rootnbttag);
}
/**
* Uses Gson to load back a {@link Serializable} object from the Compound
*
* @param comp
* @param key
* @param type
* @return The loaded Object or null, if not found
*/
public static <T> T getObject(NBTCompound comp, String key, Class<T> type) {
if (!MinecraftVersion.hasGsonSupport())
return null;
String json = (String) getData(comp, ReflectionMethod.COMPOUND_GET_STRING, key);
if (json == null) {
return null;
}
return GsonWrapper.deserializeJson(json, type);
}
@SuppressWarnings("unchecked")
public static Set<String> getKeys(NBTCompound comp) {
Object rootnbttag = comp.getCompound();
if (rootnbttag == null) {
rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
}
if (!valideCompound(comp)) return null;
Object workingtag = gettoCompount(rootnbttag, comp);
return (Set<String>) ReflectionMethod.COMPOUND_GET_KEYS.run(workingtag);
}
/**
* Deletes the given key
*
* @param comp
* @param key
*/
public static void remove(NBTCompound comp, String key) {
Object rootnbttag = comp.getCompound();
if (rootnbttag == null) {
rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
}
if (!valideCompound(comp))
return;
Object workingtag = gettoCompount(rootnbttag, comp);
ReflectionMethod.COMPOUND_REMOVE_KEY.run(workingtag, key);
comp.setCompound(rootnbttag);
}
public static void setData(NBTCompound comp, ReflectionMethod type, String key, Object data) {
if (data == null) {
remove(comp, key);
return;
}
Object rootnbttag = comp.getCompound();
if (rootnbttag == null) {
rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
}
if (!valideCompound(comp)) return;
Object workingtag = gettoCompount(rootnbttag, comp);
type.run(workingtag, key, data);
comp.setCompound(rootnbttag);
}
/**
* Gets the Keyset inside this Compound
*
* @param comp
* @return Set of all keys
*/
@SuppressWarnings("unchecked")
public static Set<String> getKeys(NBTCompound comp) {
Object rootnbttag = comp.getCompound();
if (rootnbttag == null) {
rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
}
if (!valideCompound(comp))
throw new NbtApiException("The Compound wasn't able to be linked back to the root!");
Object workingtag = gettoCompount(rootnbttag, comp);
return (Set<String>) ReflectionMethod.COMPOUND_GET_KEYS.run(workingtag);
}
public static Object getData(NBTCompound comp, ReflectionMethod type, String key) {
Object rootnbttag = comp.getCompound();
if (rootnbttag == null) {
return null;
}
if (!valideCompound(comp)) return null;
Object workingtag = gettoCompount(rootnbttag, comp);
return type.run(workingtag, key);
}
/**
* Sets data inside the Compound
*
* @param comp
* @param type
* @param key
* @param data
*/
public static void setData(NBTCompound comp, ReflectionMethod type, String key, Object data) {
if (data == null) {
remove(comp, key);
return;
}
Object rootnbttag = comp.getCompound();
if (rootnbttag == null) {
rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance();
}
if (!valideCompound(comp))
throw new NbtApiException("The Compound wasn't able to be linked back to the root!");
Object workingtag = gettoCompount(rootnbttag, comp);
type.run(workingtag, key, data);
comp.setCompound(rootnbttag);
}
/**
* Gets data from the Compound
*
* @param comp
* @param type
* @param key
* @return The value or default fallback from NMS
*/
public static Object getData(NBTCompound comp, ReflectionMethod type, String key) {
Object rootnbttag = comp.getCompound();
if (rootnbttag == null) {
return null;
}
if (!valideCompound(comp))
throw new NbtApiException("The Compound wasn't able to be linked back to the root!");
Object workingtag = gettoCompount(rootnbttag, comp);
return type.run(workingtag, key);
}
}

View File

@ -0,0 +1,42 @@
package com.songoda.epicenchants.utils.itemnbtapi;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ClassWrapper;
import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ReflectionMethod;
/**
* String implementation for NBTLists
*
* @author tr7zw
*
*/
public class NBTStringList extends NBTList<String> {
protected NBTStringList(NBTCompound owner, String name, NBTType type, Object list) {
super(owner, name, type, list);
}
@Override
public String get(int index) {
try {
return (String) ReflectionMethod.LIST_GET_STRING.run(listObject, index);
} catch (Exception ex) {
throw new NbtApiException(ex);
}
}
@Override
protected Object asTag(String object) {
try {
Constructor<?> con = ClassWrapper.NMS_NBTTAGSTRING.getClazz().getDeclaredConstructor(String.class);
con.setAccessible(true);
return con.newInstance(object);
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
| NoSuchMethodException | SecurityException e) {
throw new NbtApiException("Error while wrapping the Object " + object + " to it's NMS object!", e);
}
}
}

View File

@ -2,21 +2,35 @@ package com.songoda.epicenchants.utils.itemnbtapi;
import org.bukkit.block.BlockState;
/**
* NBT class to access vanilla tags from TileEntities. TileEntities don't
* support custom tags. Use the NBTInjector for custom tags. Changes will be
* instantly applied to the Tile, use the merge method to do many things at
* once.
*
* @author tr7zw
*
*/
public class NBTTileEntity extends NBTCompound {
private final BlockState tile;
private final BlockState tile;
public NBTTileEntity(BlockState tile) {
super(null, null);
this.tile = tile;
}
/**
* @param tile BlockState from any TileEntity
*/
public NBTTileEntity(BlockState tile) {
super(null, null);
this.tile = tile;
}
protected Object getCompound() {
return NBTReflectionUtil.getTileEntityNBTTagCompound(tile);
}
@Override
public Object getCompound() {
return NBTReflectionUtil.getTileEntityNBTTagCompound(tile);
}
protected void setCompound(Object compound) {
NBTReflectionUtil.setTileEntityNBTTagCompound(tile, compound);
}
@Override
protected void setCompound(Object compound) {
NBTReflectionUtil.setTileEntityNBTTagCompound(tile, compound);
}
}

View File

@ -1,34 +1,48 @@
package com.songoda.epicenchants.utils.itemnbtapi;
/**
* Enum of all NBT Types Minecraft contains
*
* @author tr7zw
*
*/
@SuppressWarnings("javadoc")
public enum NBTType {
NBTTagEnd(0),
NBTTagEnd(0),
NBTTagByte(1),
NBTTagShort(2),
NBTTagInt(3),
NBTTagLong(4),
NBTTagFloat(5),
NBTTagDouble(6),
NBTTagByteArray(7),
NBTTagIntArray(11),
NBTTagString(8),
NBTTagList(9),
NBTTagCompound(10);
NBTTagShort(2),
NBTTagInt(3),
NBTTagLong(4),
NBTTagFloat(5),
NBTTagDouble(6),
NBTTagByteArray(7),
NBTTagIntArray(11),
NBTTagString(8),
NBTTagList(9),
NBTTagCompound(10);
private final int id;
NBTType(int i) {
id = i;
}
NBTType(int i) {
id = i;
}
private final int id;
public static NBTType valueOf(int id) {
for (NBTType t : values())
if (t.getId() == id)
return t;
return NBTType.NBTTagEnd;
}
/**
* @return Id used by Minecraft internally
*/
public int getId() {
return id;
}
public int getId() {
return id;
}
/**
* @param id Internal Minecraft id
* @return Enum representing the id, NBTTagEnd for invalide ids
*/
public static NBTType valueOf(int id) {
for (NBTType t : values())
if (t.getId() == id)
return t;
return NBTType.NBTTagEnd;
}
}

View File

@ -0,0 +1,56 @@
package com.songoda.epicenchants.utils.itemnbtapi;
/**
* A generic {@link RuntimeException} that can be thrown by most methods in the
* NBTAPI.
*
* @author tr7zw
*
*/
public class NbtApiException extends RuntimeException {
/**
*
*/
private static final long serialVersionUID = -993309714559452334L;
/**
*
*/
public NbtApiException() {
super();
}
/**
* @param message
* @param cause
* @param enableSuppression
* @param writableStackTrace
*/
public NbtApiException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
/**
* @param message
* @param cause
*/
public NbtApiException(String message, Throwable cause) {
super(message, cause);
}
/**
* @param message
*/
public NbtApiException(String message) {
super(message);
}
/**
* @param cause
*/
public NbtApiException(Throwable cause) {
super(cause);
}
}

View File

@ -1,28 +0,0 @@
package com.songoda.epicenchants.utils.itemnbtapi;
import java.lang.reflect.Constructor;
public enum ObjectCreator {
NMS_NBTTAGCOMPOUND(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()),
NMS_BLOCKPOSITION(ClassWrapper.NMS_BLOCKPOSITION.getClazz(), int.class, int.class, int.class);
private Constructor<?> construct;
ObjectCreator(Class<?> clazz, Class<?>... args) {
try {
construct = clazz.getConstructor(args);
} catch (Exception ex) {
ex.printStackTrace();
}
}
public Object getInstance(Object... args) {
try {
return construct.newInstance(args);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
}

View File

@ -0,0 +1,377 @@
package com.songoda.epicenchants.utils.itemnbtapi.utils;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.ServicePriority;
import javax.net.ssl.HttpsURLConnection;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;
import java.util.logging.Level;
import java.util.zip.GZIPOutputStream;
import static com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion.logger;
/**
* bStats collects some data for plugin authors.
* <p>
* Check out https://bStats.org/ to learn more about bStats!
*
* This class is modified by tr7zw to work when the api is shaded into other peoples plugins.
*/
public class ApiMetricsLite {
private static final String PLUGINNAME = "ItemNBTAPI"; // DO NOT CHANGE THE NAME! else it won't link the data on bStats
private static final String PLUGINVERSION = "2.2.0-SNAPSHOT"; // In case you fork the nbt-api for internal use in your network, plugins and so on, you *may* add that to the version here. (2.x.x-Timolia or something like that?)
// Not sure how good of an idea that is, so maybe just leave it as is ¯\_()_/¯
// The version of this bStats class
public static final int B_STATS_VERSION = 1;
// The version of the NBT-Api bStats
public static final int NBT_BSTATS_VERSION = 1;
// The url to which the data is sent
private static final String URL = "https://bStats.org/submitData/bukkit";
// Is bStats enabled on this server?
private boolean enabled;
// Should failed requests be logged?
private static boolean logFailedRequests;
// Should the sent data be logged?
private static boolean logSentData;
// Should the response text be logged?
private static boolean logResponseStatusText;
// The uuid of the server
private static String serverUUID;
// The plugin
private Plugin plugin;
/**
* Class constructor.
*
*/
public ApiMetricsLite() {
// The register method just uses any enabled plugin it can find to register. This *shouldn't* cause any problems, since the plugin isn't used any other way.
// Register our service
for(Plugin plug : Bukkit.getPluginManager().getPlugins()) {
plugin = plug;
if(plugin != null)
break;
}
if(plugin == null) {
return;// Didn't find any plugin that could work
}
// Get the config file
File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats");
File configFile = new File(bStatsFolder, "config.yml");
YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile);
// Check if the config file exists
if (!config.isSet("serverUuid")) {
// Add default values
config.addDefault("enabled", true);
// Every server gets it's unique random id.
config.addDefault("serverUuid", UUID.randomUUID().toString());
// Should failed request be logged?
config.addDefault("logFailedRequests", false);
// Should the sent data be logged?
config.addDefault("logSentData", false);
// Should the response text be logged?
config.addDefault("logResponseStatusText", false);
// Inform the server owners about bStats
config.options().header(
"bStats collects some data for plugin authors like how many servers are using their plugins.\n" +
"To honor their work, you should not disable it.\n" +
"This has nearly no effect on the server performance!\n" +
"Check out https://bStats.org/ to learn more :)"
).copyDefaults(true);
try {
config.save(configFile);
} catch (IOException ignored) { }
}
// Load the data
serverUUID = config.getString("serverUuid");
logFailedRequests = config.getBoolean("logFailedRequests", false);
enabled = config.getBoolean("enabled", true);
logSentData = config.getBoolean("logSentData", false);
logResponseStatusText = config.getBoolean("logResponseStatusText", false);
if (enabled) {
boolean found = false;
// Search for all other bStats Metrics classes to see if we are the first one
for (Class<?> service : Bukkit.getServicesManager().getKnownServices()) {
try {
service.getField("NBT_BSTATS_VERSION"); // Create only one instance of the nbt-api bstats.
return;
} catch (NoSuchFieldException ignored) { }
try {
service.getField("B_STATS_VERSION"); // Our identifier :)
found = true; // We aren't the first
break;
} catch (NoSuchFieldException ignored) { }
}
// Register our service
Bukkit.getServicesManager().register(ApiMetricsLite.class, this, plugin, ServicePriority.Normal);
if (!found) {
logger.info("[NBTAPI] Using the plugin '" + plugin.getName() + "' to create a bStats instance!");
// We are the first!
startSubmitting();
}
}
}
/**
* Checks if bStats is enabled.
*
* @return Whether bStats is enabled or not.
*/
public boolean isEnabled() {
return enabled;
}
/**
* Starts the Scheduler which submits our data every 30 minutes.
*/
private void startSubmitting() {
final Timer timer = new Timer(true); // We use a timer cause the Bukkit scheduler is affected by server lags
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
if (!plugin.isEnabled()) { // Plugin was disabled
timer.cancel();
return;
}
// Nevertheless we want our code to run in the Bukkit main thread, so we have to use the Bukkit scheduler
// Don't be afraid! The connection to the bStats server is still async, only the stats collection is sync ;)
Bukkit.getScheduler().runTask(plugin, () -> submitData());
}
}, 1000l * 60l * 5l, 1000l * 60l * 30l);
// Submit the data every 30 minutes, first time after 5 minutes to give other plugins enough time to start
// WARNING: Changing the frequency has no effect but your plugin WILL be blocked/deleted!
// WARNING: Just don't do it!
}
/**
* Gets the plugin specific data.
* This method is called using Reflection.
*
* @return The plugin specific data.
*/
public JsonObject getPluginData() {
JsonObject data = new JsonObject();
data.addProperty("pluginName", PLUGINNAME); // Append the name of the plugin
data.addProperty("pluginVersion", PLUGINVERSION); // Append the version of the plugin
data.add("customCharts", new JsonArray());
return data;
}
/**
* Gets the server specific data.
*
* @return The server specific data.
*/
private JsonObject getServerData() {
// Minecraft specific data
int playerAmount;
try {
// Around MC 1.8 the return type was changed to a collection from an array,
// This fixes java.lang.NoSuchMethodError: org.bukkit.Bukkit.getOnlinePlayers()Ljava/util/Collection;
Method onlinePlayersMethod = Class.forName("org.bukkit.Server").getMethod("getOnlinePlayers");
playerAmount = onlinePlayersMethod.getReturnType().equals(Collection.class)
? ((Collection<?>) onlinePlayersMethod.invoke(Bukkit.getServer())).size()
: ((Player[]) onlinePlayersMethod.invoke(Bukkit.getServer())).length;
} catch (Exception e) {
playerAmount = Bukkit.getOnlinePlayers().size(); // Just use the new method if the Reflection failed
}
int onlineMode = Bukkit.getOnlineMode() ? 1 : 0;
String bukkitVersion = Bukkit.getVersion();
String bukkitName = Bukkit.getName();
// OS/Java specific data
String javaVersion = System.getProperty("java.version");
String osName = System.getProperty("os.name");
String osArch = System.getProperty("os.arch");
String osVersion = System.getProperty("os.version");
int coreCount = Runtime.getRuntime().availableProcessors();
JsonObject data = new JsonObject();
data.addProperty("serverUUID", serverUUID);
data.addProperty("playerAmount", playerAmount);
data.addProperty("onlineMode", onlineMode);
data.addProperty("bukkitVersion", bukkitVersion);
data.addProperty("bukkitName", bukkitName);
data.addProperty("javaVersion", javaVersion);
data.addProperty("osName", osName);
data.addProperty("osArch", osArch);
data.addProperty("osVersion", osVersion);
data.addProperty("coreCount", coreCount);
return data;
}
/**
* Collects the data and sends it afterwards.
*/
private void submitData() {
final JsonObject data = getServerData();
JsonArray pluginData = new JsonArray();
// Search for all other bStats Metrics classes to get their plugin data
for (Class<?> service : Bukkit.getServicesManager().getKnownServices()) {
try {
service.getField("B_STATS_VERSION"); // Our identifier :)
for (RegisteredServiceProvider<?> provider : Bukkit.getServicesManager().getRegistrations(service)) {
try {
Object plugin = provider.getService().getMethod("getPluginData").invoke(provider.getProvider());
if (plugin instanceof JsonObject) {
pluginData.add((JsonObject) plugin);
} else { // old bstats version compatibility
try {
Class<?> jsonObjectJsonSimple = Class.forName("org.json.simple.JSONObject");
if (plugin.getClass().isAssignableFrom(jsonObjectJsonSimple)) {
Method jsonStringGetter = jsonObjectJsonSimple.getDeclaredMethod("toJSONString");
jsonStringGetter.setAccessible(true);
String jsonString = (String) jsonStringGetter.invoke(plugin);
JsonObject object = new JsonParser().parse(jsonString).getAsJsonObject();
pluginData.add(object);
}
} catch (ClassNotFoundException e) {
// minecraft version 1.14+
if (logFailedRequests) {
logger.log(Level.WARNING, "[NBTAPI][BSTATS] Encountered exception while posting request!", e);
// Not using the plugins logger since the plugin isn't the plugin containing the NBT-Api most of the time
//this.plugin.getLogger().log(Level.SEVERE, "Encountered unexpected exception ", e);
}
continue; // continue looping since we cannot do any other thing.
}
}
} catch (NullPointerException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) {
}
}
} catch (NoSuchFieldException ignored) { }
}
data.add("plugins", pluginData);
// Create a new thread for the connection to the bStats server
new Thread(new Runnable() {
@Override
public void run() {
try {
// Send the data
sendData(plugin, data);
} catch (Exception e) {
// Something went wrong! :(
if (logFailedRequests) {
logger.log(Level.WARNING, "[NBTAPI][BSTATS] Could not submit plugin stats of " + plugin.getName(), e);
// Not using the plugins logger since the plugin isn't the plugin containing the NBT-Api most of the time
//plugin.getLogger().log(Level.WARNING, "Could not submit plugin stats of " + plugin.getName(), e);
}
}
}
}).start();
}
/**
* Sends the data to the bStats server.
*
* @param plugin Any plugin. It's just used to get a logger instance.
* @param data The data to send.
* @throws Exception If the request failed.
*/
private static void sendData(Plugin plugin, JsonObject data) throws Exception {
if (data == null) {
throw new IllegalArgumentException("Data cannot be null!");
}
if (Bukkit.isPrimaryThread()) {
throw new IllegalAccessException("This method must not be called from the main thread!");
}
if (logSentData) {
System.out.println("[NBTAPI][BSTATS] Sending data to bStats: " + data.toString());
// Not using the plugins logger since the plugin isn't the plugin containing the NBT-Api most of the time
//plugin.getLogger().info("Sending data to bStats: " + data.toString());
}
HttpsURLConnection connection = (HttpsURLConnection) new URL(URL).openConnection();
// Compress the data to save bandwidth
byte[] compressedData = compress(data.toString());
// Add headers
connection.setRequestMethod("POST");
connection.addRequestProperty("Accept", "application/json");
connection.addRequestProperty("Connection", "close");
connection.addRequestProperty("Content-Encoding", "gzip"); // We gzip our request
connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length));
connection.setRequestProperty("Content-Type", "application/json"); // We send our data in JSON format
connection.setRequestProperty("User-Agent", "MC-Server/" + B_STATS_VERSION);
// Send data
connection.setDoOutput(true);
DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream());
outputStream.write(compressedData);
outputStream.flush();
outputStream.close();
InputStream inputStream = connection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder builder = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
builder.append(line);
}
bufferedReader.close();
if (logResponseStatusText) {
logger.info("[NBTAPI][BSTATS] Sent data to bStats and received response: " + builder.toString());
// Not using the plugins logger since the plugin isn't the plugin containing the NBT-Api most of the time
//plugin.getLogger().info("Sent data to bStats and received response: " + builder.toString());
}
}
/**
* Gzips the given String.
*
* @param str The string to gzip.
* @return The gzipped String.
* @throws IOException If the compression failed.
*/
private static byte[] compress(final String str) throws IOException {
if (str == null) {
return new byte[0];
}
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
GZIPOutputStream gzip = new GZIPOutputStream(outputStream);
gzip.write(str.getBytes(StandardCharsets.UTF_8));
gzip.close();
return outputStream.toByteArray();
}
}

View File

@ -2,26 +2,53 @@ package com.songoda.epicenchants.utils.itemnbtapi.utils;
import com.google.gson.Gson;
import com.songoda.epicenchants.utils.itemnbtapi.NbtApiException;
/**
* Helper class for 1.7 servers without Gson
*
* @author tr7zw
*
*/
public class GsonWrapper {
private static final Gson gson = new Gson();
/**
* Private constructor
*/
private GsonWrapper() {
public static String getString(Object obj) {
return gson.toJson(obj);
}
}
public static <T> T deserializeJson(String json, Class<T> type) {
try {
if (json == null) {
return null;
}
private static final Gson gson = new Gson();
T obj = gson.fromJson(json, type);
return type.cast(obj);
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
/**
* Turns Objects into Json Strings
*
* @param obj
* @return Json, representing the Object
*/
public static String getString(Object obj) {
return gson.toJson(obj);
}
/**
* Creates an Object of the given type using the Json String
*
* @param json
* @param type
* @return Object that got created, or null if the json is null
*/
public static <T> T deserializeJson(String json, Class<T> type) {
try {
if (json == null) {
return null;
}
T obj = gson.fromJson(json, type);
return type.cast(obj);
} catch (Exception ex) {
throw new NbtApiException("Error while converting json to " + type.getName(), ex);
}
}
}

View File

@ -1,63 +1,141 @@
package com.songoda.epicenchants.utils.itemnbtapi.utils;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.bukkit.Bukkit;
/**
* This class acts as the "Brain" of the NBTApi. It contains the main logger for
* other classes,registers bStats and checks rather Maven shading was done
* correctly.
*
* @author tr7zw
*
*/
@SuppressWarnings("javadoc")
public enum MinecraftVersion {
Unknown(Integer.MAX_VALUE),//Use the newest known mappings
MC1_7_R4(174),
MC1_8_R3(183),
MC1_9_R1(191),
MC1_9_R2(192),
MC1_10_R1(1101),
MC1_11_R1(1111),
MC1_12_R1(1121),
MC1_13_R1(1131),
MC1_13_R2(1132),
MC1_14_R1(1141);
UNKNOWN(Integer.MAX_VALUE), // Use the newest known mappings
MC1_7_R4(174),
MC1_8_R3(183),
MC1_9_R1(191),
MC1_9_R2(192),
MC1_10_R1(1101),
MC1_11_R1(1111),
MC1_12_R1(1121),
MC1_13_R1(1131),
MC1_13_R2(1132),
MC1_14_R1(1141),
MC1_15_R1(1151);
private static MinecraftVersion version;
private static Boolean hasGsonSupport;
private static MinecraftVersion version;
private static Boolean hasGsonSupport;
private static boolean bStatsDisabled = false;
private static boolean disablePackageWarning = false;
/**
* Logger used by the api
*/
public static final Logger logger = Logger.getLogger("NBTAPI");
private final int versionId;
private final int versionId;
MinecraftVersion(int versionId) {
this.versionId = versionId;
}
MinecraftVersion(int versionId) {
this.versionId = versionId;
}
public int getVersionId() {
return versionId;
}
/**
* @return A simple comparable Integer, representing the version.
*/
public int getVersionId() {
return versionId;
}
public static MinecraftVersion getVersion() {
if (version != null) {
return version;
}
final String ver = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3];
System.out.println("[NBTAPI] Found Spigot: " + ver + "! Trying to find NMS support");
try {
version = MinecraftVersion.valueOf(ver.replace("v", "MC"));
} catch (IllegalArgumentException ex) {
version = MinecraftVersion.Unknown;
}
if (version != Unknown) {
System.out.println("[NBTAPI] NMS support '" + version.name() + "' loaded!");
} else {
System.out.println("[NBTAPI] Wasn't able to find NMS Support! Some functions may not work!");
}
return version;
}
/**
* Getter for this servers MinecraftVersion. Also init's bStats and checks the
* shading.
*
* @return The enum for the MinecraftVersion this server is running
*/
public static MinecraftVersion getVersion() {
if (version != null) {
return version;
}
final String ver = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3];
logger.info("[NBTAPI] Found Spigot: " + ver + "! Trying to find NMS support");
try {
version = MinecraftVersion.valueOf(ver.replace("v", "MC"));
} catch (IllegalArgumentException ex) {
version = MinecraftVersion.UNKNOWN;
}
if (version != UNKNOWN) {
logger.info("[NBTAPI] NMS support '" + version.name() + "' loaded!");
} else {
logger.warning("[NBTAPI] Wasn't able to find NMS Support! Some functions may not work!");
}
init();
return version;
}
public static boolean hasGsonSupport() {
if (hasGsonSupport != null) {
return hasGsonSupport;
}
try {
System.out.println("Found Gson: " + Class.forName("com.google.gson.Gson"));
hasGsonSupport = true;
} catch (Exception ex) {
hasGsonSupport = false;
}
return hasGsonSupport;
}
private static void init() {
try {
if (!bStatsDisabled)
new ApiMetricsLite();
} catch (Exception ex) {
logger.log(Level.WARNING, "[NBTAPI] Error enabeling Metrics!", ex);
}
// Maven's Relocate is clever and changes strings, too. So we have to use this
// little "trick" ... :D (from bStats)
final String defaultPackage = new String(new byte[] { 'd', 'e', '.', 't', 'r', '7', 'z', 'w', '.', 'c', 'h',
'a', 'n', 'g', 'e', 'm', 'e', '.', 'n', 'b', 't', 'a', 'p', 'i', '.', 'u', 't', 'i', 'l', 's' });
if (!disablePackageWarning && MinecraftVersion.class.getPackage().getName().equals(defaultPackage)) {
logger.warning(
"#########################################- NBTAPI -#########################################");
logger.warning(
"The NBT-API package has not been moved! This *will* cause problems with other plugins containing");
logger.warning(
"a different version of the api! Please read the guide on the plugin page on how to get the");
logger.warning(
"Maven Shade plugin to relocate the api to your personal location! If you are not the developer,");
logger.warning("please check your plugins and contact their developer, so he can fix this issue.");
logger.warning(
"#########################################- NBTAPI -#########################################");
}
}
}
/**
* @return True, if Gson is usable
*/
public static boolean hasGsonSupport() {
if (hasGsonSupport != null) {
return hasGsonSupport;
}
try {
logger.info("[NBTAPI] Found Gson: " + Class.forName("com.google.gson.Gson"));
hasGsonSupport = true;
} catch (Exception ex) {
logger.info("[NBTAPI] Gson not found! This will not allow the usage of some methods!");
hasGsonSupport = false;
}
return hasGsonSupport;
}
/**
* Calling this function before the NBT-Api is used will disable bStats stats
* collection. Please consider not to do that, since it won't affect your plugin
* and helps the NBT-Api developer to see api's demand.
*/
public static void disableBStats() {
bStatsDisabled = true;
}
/**
* Forcefully disables the log message for plugins not shading the API to
* another location. This may be helpful for networks or development
* environments, but please don't use it for plugins that are uploaded to
* Spigotmc.
*/
public static void disablePackageWarning() {
disablePackageWarning = true;
}
}

View File

@ -0,0 +1,53 @@
package com.songoda.epicenchants.utils.itemnbtapi.utils;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import com.songoda.epicenchants.utils.itemnbtapi.NbtApiException;
public final class ReflectionUtil {
private static Field field_modifiers;
static {
try {
field_modifiers = Field.class.getDeclaredField("modifiers");
field_modifiers.setAccessible(true);
} catch (NoSuchFieldException ex) {
try {
// This hacky workaround is for newer jdk versions 11+?
Method fieldGetter = Class.class.getDeclaredMethod("getDeclaredFields0", boolean.class);
fieldGetter.setAccessible(true);
Field[] fields = (Field[]) fieldGetter.invoke(Field.class, false);
for (Field f : fields)
if (f.getName().equals("modifiers")) {
field_modifiers = f;
field_modifiers.setAccessible(true);
break;
}
} catch (Exception e) {
throw new NbtApiException(e);
}
}
if (field_modifiers == null) {
throw new NbtApiException("Unable to init the modifiers Field.");
}
}
public static Field makeNonFinal(Field field) throws IllegalArgumentException, IllegalAccessException {
int mods = field.getModifiers();
if (Modifier.isFinal(mods)) {
field_modifiers.set(field, mods & ~Modifier.FINAL);
}
return field;
}
public static void setFinal(Object obj, Field field, Object newValue)
throws IllegalArgumentException, IllegalAccessException {
field.setAccessible(true);
field = makeNonFinal(field);
field.set(obj, newValue);
}
}

View File

@ -0,0 +1,77 @@
package com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings;
import java.util.logging.Level;
import org.bukkit.Bukkit;
import com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion;
import static com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion.logger;
/**
* Wraps NMS and CRAFT classes
*
* @author tr7zw
*
*/
@SuppressWarnings("javadoc")
public enum ClassWrapper {
CRAFT_ITEMSTACK(PackageWrapper.CRAFTBUKKIT, "inventory.CraftItemStack"),
CRAFT_ENTITY(PackageWrapper.CRAFTBUKKIT, "entity.CraftEntity"),
CRAFT_WORLD(PackageWrapper.CRAFTBUKKIT, "CraftWorld"),
NMS_NBTBASE(PackageWrapper.NMS, "NBTBase"),
NMS_NBTTAGSTRING(PackageWrapper.NMS, "NBTTagString"),
NMS_NBTTAGINT(PackageWrapper.NMS, "NBTTagInt"),
NMS_ITEMSTACK(PackageWrapper.NMS, "ItemStack"),
NMS_NBTTAGCOMPOUND(PackageWrapper.NMS, "NBTTagCompound"),
NMS_NBTTAGLIST(PackageWrapper.NMS, "NBTTagList"),
NMS_NBTCOMPRESSEDSTREAMTOOLS(PackageWrapper.NMS, "NBTCompressedStreamTools"),
NMS_MOJANGSONPARSER(PackageWrapper.NMS, "MojangsonParser"),
NMS_TILEENTITY(PackageWrapper.NMS, "TileEntity"),
NMS_BLOCKPOSITION(PackageWrapper.NMS, "BlockPosition"),
NMS_WORLDSERVER(PackageWrapper.NMS, "WorldServer"),
NMS_MINECRAFTSERVER(PackageWrapper.NMS, "MinecraftServer"),
NMS_WORLD(PackageWrapper.NMS, "World"),
NMS_ENTITY(PackageWrapper.NMS, "Entity"),
NMS_ENTITYTYPES(PackageWrapper.NMS, "EntityTypes"),
NMS_REGISTRYSIMPLE(PackageWrapper.NMS, "RegistrySimple", MinecraftVersion.MC1_11_R1, MinecraftVersion.MC1_12_R1),
NMS_REGISTRYMATERIALS(PackageWrapper.NMS, "RegistryMaterials"),
NMS_IREGISTRY(PackageWrapper.NMS, "IRegistry"),
NMS_MINECRAFTKEY(PackageWrapper.NMS, "MinecraftKey");
private Class<?> clazz;
private boolean enabled = false;
ClassWrapper(PackageWrapper packageId, String suffix){
this(packageId, suffix, null, null);
}
ClassWrapper(PackageWrapper packageId, String suffix, MinecraftVersion from, MinecraftVersion to){
if(from != null && MinecraftVersion.getVersion().getVersionId() < from.getVersionId()) {
return;
}
if(to != null && MinecraftVersion.getVersion().getVersionId() > to.getVersionId()) {
return;
}
enabled = true;
try{
String version = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3];
clazz = Class.forName(packageId.getUri() + "." + version + "." + suffix);
}catch(Exception ex){
logger.log(Level.WARNING, "[NBTAPI] Error while trying to resolve the class '" + suffix + "'!", ex);
}
}
/**
* @return The wrapped class
*/
public Class<?> getClazz(){
return clazz;
}
/**
* @return Is this class available in this Version
*/
public boolean isEnabled() {
return enabled;
}
}

View File

@ -0,0 +1,55 @@
package com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings;
import java.lang.reflect.Constructor;
import java.util.logging.Level;
import com.songoda.epicenchants.utils.itemnbtapi.NbtApiException;
import com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion;
import static com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion.logger;
/**
* This Enum wraps Constructors for NMS classes
*
* @author tr7zw
*
*/
@SuppressWarnings("javadoc")
public enum ObjectCreator {
NMS_NBTTAGCOMPOUND(null, null, ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()),
NMS_BLOCKPOSITION(null, null, ClassWrapper.NMS_BLOCKPOSITION.getClazz(), int.class, int.class, int.class),
NMS_COMPOUNDFROMITEM(MinecraftVersion.MC1_11_R1, null, ClassWrapper.NMS_ITEMSTACK.getClazz(), ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()),
;
private Constructor<?> construct;
private Class<?> targetClass;
ObjectCreator(MinecraftVersion from, MinecraftVersion to, Class<?> clazz, Class<?>... args){
if(from != null && MinecraftVersion.getVersion().getVersionId() < from.getVersionId())
return;
if(to != null && MinecraftVersion.getVersion().getVersionId() > to.getVersionId())
return;
try{
this.targetClass = clazz;
construct = clazz.getDeclaredConstructor(args);
construct.setAccessible(true);
}catch(Exception ex){
logger.log(Level.SEVERE, "Unable to find the constructor for the class '" + clazz.getName() + "'", ex);
}
}
/**
* Creates an Object instance with given args
*
* @param args
* @return Object created
*/
public Object getInstance(Object... args){
try{
return construct.newInstance(args);
}catch(Exception ex){
throw new NbtApiException("Exception while creating a new instance of '" + targetClass + "'", ex);
}
}
}

View File

@ -0,0 +1,28 @@
package com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings;
/**
* Package enum
*
* @author tr7zw
*
*/
@SuppressWarnings("javadoc")
public enum PackageWrapper {
NMS("net.minecraft.server"),
CRAFTBUKKIT("org.bukkit.craftbukkit"),
;
private final String uri;
PackageWrapper(String uri) {
this.uri = uri;
}
/**
* @return The Uri for that package
*/
public String getUri() {
return uri;
}
}

View File

@ -1,12 +1,20 @@
package com.songoda.epicenchants.utils.itemnbtapi;
import com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion;
import org.bukkit.inventory.ItemStack;
package com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import org.bukkit.inventory.ItemStack;
import com.songoda.epicenchants.utils.itemnbtapi.NbtApiException;
import com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion;
/**
* This class caches method reflections, keeps track of method name changes between versions and allows early checking for problems
*
* @author tr7zw
*
*/
@SuppressWarnings("javadoc")
public enum ReflectionMethod {
COMPOUND_SET_FLOAT(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, float.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setFloat")),
@ -19,8 +27,11 @@ public enum ReflectionMethod {
COMPOUND_SET_BYTE(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, byte.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setByte")),
COMPOUND_SET_DOUBLE(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, double.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setDouble")),
COMPOUND_SET_BOOLEAN(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, boolean.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setBoolean")),
COMPOUND_ADD(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "a")), //FIXME: No Spigot mapping!
COMPOUND_MERGE(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "a")), //FIXME: No Spigot mapping!
COMPOUND_SET(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, ClassWrapper.NMS_NBTBASE.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "set")),
COMPOUND_GET(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "get")),
COMPOUND_GET_LIST(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, int.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getList")),
COMPOUND_GET_FLOAT(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getFloat")),
COMPOUND_GET_STRING(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getString")),
COMPOUND_GET_INT(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getInt")),
@ -31,10 +42,15 @@ public enum ReflectionMethod {
COMPOUND_GET_BYTE(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getByte")),
COMPOUND_GET_DOUBLE(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getDouble")),
COMPOUND_GET_BOOLEAN(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getBoolean")),
COMPOUND_GET_COMPOUND(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getCompound")),
NMSITEM_GETTAG(ClassWrapper.NMS_ITEMSTACK.getClazz(), new Class[] {}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getTag")),
NMSITEM_SAVE(ClassWrapper.NMS_ITEMSTACK.getClazz(), new Class[] {ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "save")),
NMSITEM_CREATESTACK(ClassWrapper.NMS_ITEMSTACK.getClazz(), new Class[] {ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_7_R4, MinecraftVersion.MC1_10_R1, new Since(MinecraftVersion.MC1_7_R4, "createStack")),
COMPOUND_REMOVE_KEY(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "remove")),
COMPOUND_HAS_KEY(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "hasKey")),
COMPOUND_GET_TYPE(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "b"), new Since(MinecraftVersion.MC1_9_R1, "d")), //FIXME: No Spigot mapping!
COMPOUND_GET_TYPE(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "b"), new Since(MinecraftVersion.MC1_9_R1, "d"), new Since(MinecraftVersion.MC1_15_R1, "e")), //FIXME: No Spigot mapping!
COMPOUND_GET_KEYS(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "c"), new Since(MinecraftVersion.MC1_13_R1, "getKeys")),
LISTCOMPOUND_GET_KEYS(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "c"), new Since(MinecraftVersion.MC1_13_R1, "getKeys")),
@ -44,85 +60,123 @@ public enum ReflectionMethod {
LEGACY_LIST_ADD(ClassWrapper.NMS_NBTTAGLIST.getClazz(), new Class[]{ClassWrapper.NMS_NBTBASE.getClazz()}, MinecraftVersion.MC1_7_R4, MinecraftVersion.MC1_13_R2, new Since(MinecraftVersion.MC1_7_R4, "add")),
LIST_ADD(ClassWrapper.NMS_NBTTAGLIST.getClazz(), new Class[]{int.class, ClassWrapper.NMS_NBTBASE.getClazz()}, MinecraftVersion.MC1_14_R1, new Since(MinecraftVersion.MC1_14_R1, "add")),
LIST_GET_STRING(ClassWrapper.NMS_NBTTAGLIST.getClazz(), new Class[]{int.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getString")),
LIST_GET(ClassWrapper.NMS_NBTTAGLIST.getClazz(), new Class[]{int.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "get")),
LIST_GET_COMPOUND(ClassWrapper.NMS_NBTTAGLIST.getClazz(), new Class[]{int.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "get")),
LIST_GET(ClassWrapper.NMS_NBTTAGLIST.getClazz(), new Class[]{int.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "g"), new Since(MinecraftVersion.MC1_9_R1, "h"), new Since(MinecraftVersion.MC1_12_R1, "i"), new Since(MinecraftVersion.MC1_13_R1, "get")),
ITEMSTACK_SET_TAG(ClassWrapper.NMS_ITEMSTACK.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setTag")),
ITEMSTACK_NMSCOPY(ClassWrapper.CRAFT_ITEMSTACK.getClazz(), new Class[]{ItemStack.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "asNMSCopy")),
ITEMSTACK_BUKKITMIRROR(ClassWrapper.CRAFT_ITEMSTACK.getClazz(), new Class[]{ClassWrapper.NMS_ITEMSTACK.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "asCraftMirror")),
CRAFT_WORLD_GET_HANDLE(ClassWrapper.CRAFT_WORLD.getClazz(), new Class[]{}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getHandle")),
NMS_WORLD_GET_TILEENTITY(ClassWrapper.NMS_WORLD.getClazz(), new Class[]{ClassWrapper.NMS_BLOCKPOSITION.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getTileEntity")),
NMS_WORLD_GET_TILEENTITY(ClassWrapper.NMS_WORLDSERVER.getClazz(), new Class[]{ClassWrapper.NMS_BLOCKPOSITION.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getTileEntity")),
NMS_WORLD_SET_TILEENTITY(ClassWrapper.NMS_WORLDSERVER.getClazz(), new Class[]{ClassWrapper.NMS_BLOCKPOSITION.getClazz(), ClassWrapper.NMS_TILEENTITY.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setTileEntity")),
NMS_WORLD_REMOVE_TILEENTITY(ClassWrapper.NMS_WORLDSERVER.getClazz(), new Class[]{ClassWrapper.NMS_BLOCKPOSITION.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "t"), new Since(MinecraftVersion.MC1_9_R1, "s"), new Since(MinecraftVersion.MC1_13_R1, "n"), new Since(MinecraftVersion.MC1_14_R1, "removeTileEntity")),
TILEENTITY_LOAD_LEGACY191(ClassWrapper.NMS_TILEENTITY.getClazz(), new Class[]{ClassWrapper.NMS_MINECRAFTSERVER.getClazz(), ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_9_R1, MinecraftVersion.MC1_9_R1, new Since(MinecraftVersion.MC1_9_R1, "a")), //FIXME: No Spigot mapping!
TILEENTITY_LOAD_LEGACY183(ClassWrapper.NMS_TILEENTITY.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_8_R3, MinecraftVersion.MC1_9_R2, new Since(MinecraftVersion.MC1_8_R3, "c"), new Since(MinecraftVersion.MC1_9_R1, "a"), new Since(MinecraftVersion.MC1_9_R2, "c")), //FIXME: No Spigot mapping!
TILEENTITY_LOAD_LEGACY1121(ClassWrapper.NMS_TILEENTITY.getClazz(), new Class[]{ClassWrapper.NMS_WORLD.getClazz(), ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_10_R1, MinecraftVersion.MC1_12_R1, new Since(MinecraftVersion.MC1_10_R1, "a"), new Since(MinecraftVersion.MC1_12_R1, "create")),
TILEENTITY_LOAD(ClassWrapper.NMS_TILEENTITY.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_12_R1, "create")),
TILEENTITY_GET_NBT(ClassWrapper.NMS_TILEENTITY.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "b"), new Since(MinecraftVersion.MC1_9_R1, "save")),
TILEENTITY_SET_NBT(ClassWrapper.NMS_TILEENTITY.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "a"), new Since(MinecraftVersion.MC1_12_R1, "load")),
CRAFT_ENTITY_GET_HANDLE(ClassWrapper.CRAFT_ENTITY.getClazz(), new Class[]{}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getHandle")),
NMS_ENTITY_SET_NBT(ClassWrapper.NMS_ENTITY.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "f")), //FIXME: No Spigot mapping!
NMS_ENTITY_GET_NBT(ClassWrapper.NMS_ENTITY.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "e"), new Since(MinecraftVersion.MC1_12_R1, "save")),
NMS_ENTITY_GETSAVEID(ClassWrapper.NMS_ENTITY.getClazz(), new Class[]{}, MinecraftVersion.MC1_14_R1,new Since(MinecraftVersion.MC1_14_R1, "getSaveID")),
NBTFILE_READ(ClassWrapper.NMS_NBTCOMPRESSEDSTREAMTOOLS.getClazz(), new Class[]{InputStream.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "a")), //FIXME: No Spigot mapping!
NBTFILE_WRITE(ClassWrapper.NMS_NBTCOMPRESSEDSTREAMTOOLS.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), OutputStream.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "a")), //FIXME: No Spigot mapping!
PARSE_NBT(ClassWrapper.NMS_MOJANGSONPARSER.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "parse")),
REGISTRY_KEYSET (ClassWrapper.NMS_REGISTRYSIMPLE.getClazz(), new Class[]{}, MinecraftVersion.MC1_11_R1, MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_11_R1, "keySet")),
REGISTRY_GET (ClassWrapper.NMS_REGISTRYSIMPLE.getClazz(), new Class[]{Object.class}, MinecraftVersion.MC1_11_R1, MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_11_R1, "get")),
REGISTRY_SET (ClassWrapper.NMS_REGISTRYSIMPLE.getClazz(), new Class[]{Object.class, Object.class}, MinecraftVersion.MC1_11_R1, MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_11_R1, "a")), //FIXME: No Spigot mapping!
REGISTRY_GET_INVERSE (ClassWrapper.NMS_REGISTRYMATERIALS.getClazz(), new Class[]{Object.class}, MinecraftVersion.MC1_11_R1, MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_11_R1, "b")), //FIXME: No Spigot mapping!
REGISTRYMATERIALS_KEYSET (ClassWrapper.NMS_REGISTRYMATERIALS.getClazz(), new Class[]{}, MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_13_R1, "keySet")),
REGISTRYMATERIALS_GET (ClassWrapper.NMS_REGISTRYMATERIALS.getClazz(), new Class[]{ClassWrapper.NMS_MINECRAFTKEY.getClazz()}, MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_13_R1, "get")),
;
;
private MinecraftVersion removedAfter;
private Since targetVersion;
private Method method;
private boolean loaded = false;
private boolean compatible = false;
ReflectionMethod(Class<?> targetClass, Class<?>[] args, MinecraftVersion addedSince, MinecraftVersion removedAfter, Since... methodnames) {
private String methodName = null;
ReflectionMethod(Class<?> targetClass, Class<?>[] args, MinecraftVersion addedSince, MinecraftVersion removedAfter, Since... methodnames){
this.removedAfter = removedAfter;
MinecraftVersion server = MinecraftVersion.getVersion();
if (server.compareTo(addedSince) < 0 || (this.removedAfter != null && server.getVersionId() > this.removedAfter.getVersionId()))
return;
MinecraftVersion server = MinecraftVersion.getVersion();
if(server.compareTo(addedSince) < 0 || (this.removedAfter != null && server.getVersionId() > this.removedAfter.getVersionId()))return;
compatible = true;
Since target = methodnames[0];
for (Since s : methodnames) {
if (s.version.getVersionId() <= server.getVersionId() && target.version.getVersionId() < s.version.getVersionId())
for(Since s : methodnames){
if(s.version.getVersionId() <= server.getVersionId() && target.version.getVersionId() < s.version.getVersionId())
target = s;
}
targetVersion = target;
try {
try{
method = targetClass.getMethod(targetVersion.name, args);
method.setAccessible(true);
loaded = true;
} catch (NullPointerException | NoSuchMethodException | SecurityException ex) {
ex.printStackTrace();
methodName = targetVersion.name;
}catch(NullPointerException | NoSuchMethodException | SecurityException ex){
System.out.println("[NBTAPI] Unable to find the method '" + targetVersion.name + "' in '" + targetClass.getSimpleName() + "' Enum: " + this); //NOSONAR This gets loaded before the logger is loaded
}
}
ReflectionMethod(Class<?> targetClass, Class<?>[] args, MinecraftVersion addedSince, Since... methodnames) {
this(targetClass, args, addedSince, null, methodnames);
ReflectionMethod(Class<?> targetClass, Class<?>[] args, MinecraftVersion addedSince, Since... methodnames){
this(targetClass, args, addedSince, null, methodnames);
}
public Object run(Object target, Object... args) {
try {
/**
* Runs the method on a given target object using the given args.
*
* @param target
* @param args
* @return Value returned by the method
*/
public Object run(Object target, Object... args){
if(method == null)
throw new NbtApiException("Method not loaded! '" + this + "'");
try{
return method.invoke(target, args);
} catch (Exception ex) {
ex.printStackTrace();
}catch(Exception ex){
throw new NbtApiException("Error while calling the method '" + methodName + "', loaded: " + loaded + ", Enum: " + this, ex);
}
return null;
}
/**
* @return The MethodName, used in this Minecraft Version
*/
public String getMethodName() {
return methodName;
}
/**
* @return Has this method been linked
*/
public boolean isLoaded() {
return loaded;
}
/**
* @return Is this method available in this Minecraft Version
*/
public boolean isCompatible() {
return compatible;
}
public static class Since {
protected static class Since{
public final MinecraftVersion version;
public final String name;
public Since(MinecraftVersion version, String name) {
this.version = version;
this.name = name;
}
}
}
}

View File

@ -1,302 +0,0 @@
package com.songoda.epicenchants.utils.locale;
import org.bukkit.plugin.java.JavaPlugin;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
* Assists in the utilization of localization files.
* Created to be used by the Songoda Team.
*
* @author Brianna O'Keefe - Songoda
*/
public class Locale {
private static final List<Locale> LOCALES = new ArrayList<>();
private static final Pattern NODE_PATTERN = Pattern.compile("(\\w+(?:\\.{1}\\w+)*)\\s*=\\s*\"(.*)\"");
private static final String FILE_EXTENSION = ".lang";
private static JavaPlugin plugin;
private static File localeFolder;
private final Map<String, String> nodes = new HashMap<>();
private static String defaultLocale;
private File file;
private String name;
/**
* Instantiate the Locale class for future use
*
* @param name the name of the instantiated language
*/
private Locale(String name) {
if (plugin == null)
return;
this.name = name;
String fileName = name + FILE_EXTENSION;
this.file = new File(localeFolder, fileName);
if (!this.reloadMessages()) return;
plugin.getLogger().info("Loaded locale \"" + fileName + "\"");
}
/**
* Initialize the class to load all existing language files and update them.
* This must be called before any other methods in this class as otherwise
* the methods will fail to invoke
*
* @param plugin the plugin instance
* @param defaultLocale the default language
*/
public Locale(JavaPlugin plugin, String defaultLocale) {
Locale.plugin = plugin;
Locale.localeFolder = new File(plugin.getDataFolder(), "locales/");
if (!localeFolder.exists()) localeFolder.mkdirs();
//Save the default locale file.
Locale.defaultLocale = defaultLocale;
saveLocale(defaultLocale);
for (File file : localeFolder.listFiles()) {
String fileName = file.getName();
if (!fileName.endsWith(FILE_EXTENSION)) continue;
String name = fileName.substring(0, fileName.lastIndexOf('.'));
if (name.split("_").length != 2) continue;
if (localeLoaded(name)) continue;
LOCALES.add(new Locale(name));
}
}
/**
* Save a locale file from the InputStream, to the locale folder
*
* @param fileName the name of the file to save
* @return true if the operation was successful, false otherwise
*/
public static boolean saveLocale(String fileName) {
return saveLocale(plugin.getResource(defaultLocale + FILE_EXTENSION), fileName);
}
/**
* Save a locale file from the InputStream, to the locale folder
*
* @param in file to save
* @param fileName the name of the file to save
* @return true if the operation was successful, false otherwise
*/
public static boolean saveLocale(InputStream in, String fileName) {
if (!localeFolder.exists()) localeFolder.mkdirs();
if (!fileName.endsWith(FILE_EXTENSION))
fileName = (fileName.lastIndexOf(".") == -1 ? fileName : fileName.substring(0, fileName.lastIndexOf('.'))) + FILE_EXTENSION;
File destinationFile = new File(localeFolder, fileName);
if (destinationFile.exists())
return compareFiles(in, destinationFile);
try (OutputStream outputStream = new FileOutputStream(destinationFile)) {
copy(in, outputStream);
fileName = fileName.substring(0, fileName.lastIndexOf('.'));
if (fileName.split("_").length != 2) return false;
LOCALES.add(new Locale(fileName));
if (defaultLocale == null) defaultLocale = fileName;
return true;
} catch (IOException e) {
return false;
}
}
// Write new changes to existing files, if any at all
private static boolean compareFiles(InputStream in, File existingFile) {
InputStream defaultFile =
in == null ? plugin.getResource((defaultLocale != null ? defaultLocale : "en_US") + FILE_EXTENSION) : in;
boolean changed = false;
List<String> defaultLines, existingLines;
try (BufferedReader defaultReader = new BufferedReader(new InputStreamReader(defaultFile));
BufferedReader existingReader = new BufferedReader(new FileReader(existingFile));
BufferedWriter writer = new BufferedWriter(new FileWriter(existingFile, true))) {
defaultLines = defaultReader.lines().collect(Collectors.toList());
existingLines = existingReader.lines().map(s -> s.split("\\s*=")[0]).collect(Collectors.toList());
for (String defaultValue : defaultLines) {
if (defaultValue.isEmpty() || defaultValue.startsWith("#")) continue;
String key = defaultValue.split("\\s*=")[0];
if (!existingLines.contains(key)) {
if (!changed) {
writer.newLine();
writer.newLine();
// Leave a note alerting the user of the newly added messages.
writer.write("# New messages for " + plugin.getName() + " v" + plugin.getDescription().getVersion() + ".");
// If changes were found outside of the default file leave a note explaining that.
if (in == null) {
writer.newLine();
writer.write("# These translations were found untranslated, join");
writer.newLine();
writer.write("# our translation Discord https://discord.gg/f7fpZEf");
writer.newLine();
writer.write("# to request an official update!");
}
}
writer.newLine();
writer.write(defaultValue);
changed = true;
}
}
if (in != null && !changed) compareFiles(null, existingFile);
} catch (IOException e) {
return false;
}
return changed;
}
/**
* Check whether a locale exists and is registered or not
*
* @param name the whole language tag (i.e. "en_US")
* @return true if it exists
*/
public static boolean localeLoaded(String name) {
for (Locale locale : LOCALES)
if (locale.getName().equals(name)) return true;
return false;
}
/**
* Get a locale by its entire proper name (i.e. "en_US")
*
* @param name the full name of the locale
* @return locale of the specified name
*/
public static Locale getLocale(String name) {
for (Locale locale : LOCALES)
if (locale.getName().equalsIgnoreCase(name)) return locale;
return null;
}
/**
* Clear the previous message cache and load new messages directly from file
*
* @return reload messages from file
*/
public boolean reloadMessages() {
if (!this.file.exists()) {
plugin.getLogger().warning("Could not find file for locale \"" + this.name + "\"");
return false;
}
this.nodes.clear(); // Clear previous data (if any)
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
String line;
for (int lineNumber = 0; (line = reader.readLine()) != null; lineNumber++) {
if (line.trim().isEmpty() || line.startsWith("#") /* Comment */) continue;
Matcher matcher = NODE_PATTERN.matcher(line);
if (!matcher.find()) {
System.err.println("Invalid locale syntax at (line=" + lineNumber + ")");
continue;
}
nodes.put(matcher.group(1), matcher.group(2));
}
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* Supply the Message object with the plugins prefix.
*
* @param message message to be applied
* @return applied message
*/
private Message supplyPrefix(Message message) {
return message.setPrefix(this.nodes.getOrDefault("general.nametag.prefix", "[Plugin]"));
}
/**
* Create a new unsaved Message
*
* @param message the message to create
* @return the created message
*/
public Message newMessage(String message) {
return supplyPrefix(new Message(message));
}
/**
* Get a message set for a specific node.
*
* @param node the node to get
* @return the message for the specified node
*/
public Message getMessage(String node) {
return this.getMessageOrDefault(node, node);
}
/**
* Get a message set for a specific node
*
* @param node the node to get
* @param defaultValue the default value given that a value for the node was not found
* @return the message for the specified node. Default if none found
*/
public Message getMessageOrDefault(String node, String defaultValue) {
return supplyPrefix(new Message(this.nodes.getOrDefault(node, defaultValue)));
}
/**
* Return the locale name (i.e. "en_US")
*
* @return the locale name
*/
public String getName() {
return name;
}
private static void copy(InputStream input, OutputStream output) {
int n;
byte[] buffer = new byte[1024 * 4];
try {
while ((n = input.read(buffer)) != -1) {
output.write(buffer, 0, n);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

View File

@ -1,128 +0,0 @@
package com.songoda.epicenchants.utils.locale;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
/**
* The Message object. This holds the message to be sent
* as well as the plugins prefix so that they can both be
* easily manipulated then deployed
*/
public class Message {
private String prefix = null;
private String message;
/**
* create a new message
*
* @param message the message text
*/
public Message(String message) {
this.message = message;
}
/**
* Format and send the held message to a player
*
* @param player player to send the message to
*/
public void sendMessage(Player player) {
player.sendMessage(this.getMessage());
}
/**
* Format and send the held message with the
* appended plugin prefix to a player
*
* @param player player to send the message to
*/
public void sendPrefixedMessage(Player player) {
player.sendMessage(this.getPrefixedMessage());
}
/**
* Format and send the held message to a player
*
* @param sender command sender to send the message to
*/
public void sendMessage(CommandSender sender) {
sender.sendMessage(this.getMessage());
}
/**
* Format and send the held message to a player as a title 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);
} else {
sender.sendMessage(this.getMessage());
}
}
/**
* Format and send the held message with the
* appended plugin prefix to a command sender
*
* @param sender command sender to send the message to
*/
public void sendPrefixedMessage(CommandSender sender) {
sender.sendMessage(this.getPrefixedMessage());
}
/**
* Format the held message and append the plugins
* prefix
*
* @return the prefixed message
*/
public String getPrefixedMessage() {
return ChatColor.translateAlternateColorCodes('&',(prefix == null ? "" : this.prefix)
+ " " + this.message);
}
/**
* Get and format the held message
*
* @return the message
*/
public String getMessage() {
return ChatColor.translateAlternateColorCodes('&', this.message);
}
/**
* Get the held message
*
* @return the message
*/
public String getUnformattedMessage() {
return this.message;
}
/**
* Replace the provided placeholder with the
* provided object
*
* @param placeholder the placeholder to replace
* @param replacement the replacement object
* @return the modified Message
*/
public Message processPlaceholder(String placeholder, Object replacement) {
this.message = message.replace("{" + placeholder + "}", replacement.toString());
return this;
}
Message setPrefix(String prefix) {
this.prefix = prefix;
return this;
}
@Override
public String toString() {
return this.message;
}
}

View File

@ -254,7 +254,7 @@ public class ItemBuilder {
}
public ItemBuilder unbreakable(boolean unbreakable) {
meta.spigot().setUnbreakable(unbreakable);
meta.setUnbreakable(unbreakable);
return this;
}
@ -304,6 +304,6 @@ public class ItemBuilder {
* Unbreakability:
*/
public boolean isUnbreakable() {
return meta.spigot().isUnbreakable();
return meta.isUnbreakable();
}
}

View File

@ -1,8 +1,8 @@
package com.songoda.epicenchants.utils.settings;
import com.songoda.core.compatibility.ServerVersion;
import com.songoda.epicenchants.EpicEnchants;
import com.songoda.epicenchants.utils.Methods;
import com.songoda.epicenchants.utils.ServerVersion;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
@ -119,7 +119,7 @@ public class SettingsManager implements Listener {
int slot = 10;
for (String key : plugin.getConfig().getDefaultSection().getKeys(false)) {
ItemStack item = new ItemStack(plugin.isServerVersionAtLeast(ServerVersion.V1_13) ? Material.LEGACY_WOOL : Material.valueOf("WOOL"), 1, (byte) (slot - 9));
ItemStack item = new ItemStack(ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13) ? Material.LEGACY_WOOL : Material.valueOf("WOOL"), 1, (byte) (slot - 9));
ItemMeta meta = item.getItemMeta();
meta.setLore(Collections.singletonList(Methods.formatText("&6Click To Edit This Category.")));
meta.setDisplayName(Methods.formatText("&f&l" + key));
@ -150,13 +150,13 @@ public class SettingsManager implements Listener {
item.setType(Material.PAPER);
lore.add(Methods.formatText("&7" + config.getString(fKey)));
} else if (config.isInt(fKey)) {
item.setType(plugin.isServerVersionAtLeast(ServerVersion.V1_13) ? Material.CLOCK : Material.valueOf("WATCH"));
item.setType(ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13) ? Material.CLOCK : Material.valueOf("WATCH"));
lore.add(Methods.formatText("&7" + config.getInt(fKey)));
} else if (config.isLong(fKey)) {
item.setType(plugin.isServerVersionAtLeast(ServerVersion.V1_13) ? Material.CLOCK : Material.valueOf("WATCH"));
item.setType(ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13) ? Material.CLOCK : Material.valueOf("WATCH"));
lore.add(Methods.formatText("&7" + config.getLong(fKey)));
} else if (config.isDouble(fKey)) {
item.setType(plugin.isServerVersionAtLeast(ServerVersion.V1_13) ? Material.CLOCK : Material.valueOf("WATCH"));
item.setType(ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13) ? Material.CLOCK : Material.valueOf("WATCH"));
lore.add(Methods.formatText("&7" + config.getDouble(fKey)));
}

View File

@ -2,8 +2,8 @@ package com.songoda.epicenchants.utils.single;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.songoda.core.compatibility.ServerVersion;
import com.songoda.epicenchants.EpicEnchants;
import com.songoda.epicenchants.utils.ServerVersion;
import org.apache.commons.lang.StringUtils;
import org.bukkit.Material;
@ -19,7 +19,7 @@ public class ItemGroup {
public ItemGroup(EpicEnchants instance) {
groupMap = HashMultimap.create();
if (instance.isServerVersionAtLeast(ServerVersion.V1_13)) setupMaster();
if (com.songoda.core.compatibility.ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)) setupMaster();
else setupLegacy();
}

View File

@ -1,32 +0,0 @@
package com.songoda.epicenchants.utils.updateModules;
import com.songoda.epicenchants.EpicEnchants;
import com.songoda.update.Module;
import com.songoda.update.Plugin;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
public class LocaleModule implements Module {
@Override
public void run(Plugin plugin) {
JSONObject json = plugin.getJson();
try {
JSONArray files = (JSONArray) json.get("neededFiles");
for (Object o : files) {
JSONObject file = (JSONObject) o;
if (file.get("type").equals("locale")) {
InputStream in = new URL((String) file.get("link")).openStream();
EpicEnchants.getInstance().getLocale().saveLocale(in, (String) file.get("name"));
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

View File

@ -15,7 +15,7 @@ description:
- "more EXP when killing mobs."
# How the enchant should be formatted on the enchanted item.
applied-format: "&cInquistive {level}"
applied-format: "&cInquisitive {level}"
# What items this enchant can be applied too.
item-whitelist: