mirror of
https://gitlab.com/phoenix-dvpmt/mmoitems.git
synced 2024-12-22 04:37:42 +01:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
fca42be9bf
@ -119,7 +119,8 @@ public class ReforgeOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Keeps the display name of the item.
|
* If the item should be rerolled when updated. In the contrary,
|
||||||
|
* the previous RNG will be transferred onto the newest item.
|
||||||
*/
|
*/
|
||||||
public boolean shouldReRoll() {
|
public boolean shouldReRoll() {
|
||||||
return reRoll;
|
return reRoll;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package net.Indyuce.mmoitems.api;
|
package net.Indyuce.mmoitems.api;
|
||||||
|
|
||||||
import io.lumine.mythic.lib.MythicLib;
|
import io.lumine.mythic.lib.MythicLib;
|
||||||
|
import io.lumine.mythic.lib.UtilityMethods;
|
||||||
import io.lumine.mythic.lib.api.item.NBTItem;
|
import io.lumine.mythic.lib.api.item.NBTItem;
|
||||||
import io.lumine.mythic.lib.player.modifier.ModifierSource;
|
import io.lumine.mythic.lib.player.modifier.ModifierSource;
|
||||||
import net.Indyuce.mmoitems.MMOItems;
|
import net.Indyuce.mmoitems.MMOItems;
|
||||||
@ -298,10 +299,9 @@ public class Type {
|
|||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public static Type get(@Nullable String id) {
|
public static Type get(@Nullable String id) {
|
||||||
if (id == null) {
|
if (id == null) return null;
|
||||||
return null;
|
|
||||||
}
|
String format = UtilityMethods.enumName(id);
|
||||||
String format = id.toUpperCase().replace("-", "_").replace(" ", "_");
|
|
||||||
return MMOItems.plugin.getTypes().has(format) ? MMOItems.plugin.getTypes().get(format) : null;
|
return MMOItems.plugin.getTypes().has(format) ? MMOItems.plugin.getTypes().get(format) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,163 +12,165 @@ import java.util.logging.Level;
|
|||||||
|
|
||||||
public class CraftingStatus {
|
public class CraftingStatus {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* saves data about items being constructed in specific stations. players
|
* saves data about items being constructed in specific stations. players
|
||||||
* must go back to the station GUI and claim their item once it's ready
|
* must go back to the station GUI and claim their item once it's ready
|
||||||
*/
|
*/
|
||||||
private final Map<String, CraftingQueue> queues = new HashMap<>();
|
private final Map<String, CraftingQueue> queues = new HashMap<>();
|
||||||
|
|
||||||
public void load(PlayerData data, ConfigurationSection config) {
|
public void load(PlayerData data, ConfigurationSection config) {
|
||||||
String name = data.isOnline() ? data.getPlayer().getName() : "Unknown Player";
|
String name = data.isOnline() ? data.getPlayer().getName() : "Unknown Player";
|
||||||
|
|
||||||
for (String stationId : config.getKeys(false)) {
|
|
||||||
if (!MMOItems.plugin.getCrafting().hasStation(stationId)) {
|
|
||||||
MMOItems.plugin.getLogger().log(Level.WARNING,
|
|
||||||
"An error occurred while trying to load crafting station recipe data of '" + name + "': "
|
|
||||||
+ "could not find crafting station with ID '" + stationId
|
|
||||||
+ "', make sure you backup that player data file before the user logs off.");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
CraftingStation station = MMOItems.plugin.getCrafting().getStation(stationId);
|
for (String stationId : config.getKeys(false)) {
|
||||||
CraftingQueue queue = new CraftingQueue(station);
|
if (!MMOItems.plugin.getCrafting().hasStation(stationId)) {
|
||||||
queues.put(stationId, queue);
|
MMOItems.plugin.getLogger().log(Level.WARNING,
|
||||||
|
"An error occurred while trying to load crafting station recipe data of '" + name + "': "
|
||||||
|
+ "could not find crafting station with ID '" + stationId
|
||||||
|
+ "', make sure you backup that player data file before the user logs off.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
for (String recipeConfigId : config.getConfigurationSection(stationId).getKeys(false)) {
|
CraftingStation station = MMOItems.plugin.getCrafting().getStation(stationId);
|
||||||
String recipeId = config.getString(stationId + "." + recipeConfigId + ".recipe");
|
CraftingQueue queue = new CraftingQueue(station);
|
||||||
if (recipeId == null || !station.hasRecipe(recipeId)) {
|
queues.put(stationId, queue);
|
||||||
MMOItems.plugin.getLogger().log(Level.WARNING,
|
|
||||||
"An error occurred while trying to load crafting station recipe data of '" + name + "': "
|
|
||||||
+ "could not find recipe with ID '" + recipeId
|
|
||||||
+ "', make sure you backup that player data file before the user logs off.");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Recipe recipe = station.getRecipe(recipeId);
|
for (String recipeConfigId : config.getConfigurationSection(stationId).getKeys(false)) {
|
||||||
if (!(recipe instanceof CraftingRecipe)) {
|
String recipeId = config.getString(stationId + "." + recipeConfigId + ".recipe");
|
||||||
MMOItems.plugin.getLogger().log(Level.WARNING, "An error occurred while trying to load crafting station recipe data of '"
|
if (recipeId == null || !station.hasRecipe(recipeId)) {
|
||||||
+ name + "': " + "recipe '" + recipe.getId() + "' is not a CRAFTING recipe.");
|
MMOItems.plugin.getLogger().log(Level.WARNING,
|
||||||
continue;
|
"An error occurred while trying to load crafting station recipe data of '" + name + "': "
|
||||||
}
|
+ "could not find recipe with ID '" + recipeId
|
||||||
|
+ "', make sure you backup that player data file before the user logs off.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
queue.add((CraftingRecipe) recipe, config.getLong(stationId + "." + recipeConfigId + ".started"),
|
Recipe recipe = station.getRecipe(recipeId);
|
||||||
config.getLong(stationId + "." + recipeConfigId + ".delay"));
|
if (!(recipe instanceof CraftingRecipe)) {
|
||||||
}
|
MMOItems.plugin.getLogger().log(Level.WARNING, "An error occurred while trying to load crafting station recipe data of '"
|
||||||
}
|
+ name + "': " + "recipe '" + recipe.getId() + "' is not a CRAFTING recipe.");
|
||||||
}
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
public void save(ConfigurationSection config) {
|
queue.add((CraftingRecipe) recipe, config.getLong(stationId + "." + recipeConfigId + ".started"),
|
||||||
for (String station : queues.keySet()) {
|
config.getLong(stationId + "." + recipeConfigId + ".delay"));
|
||||||
CraftingQueue queue = queues.get(station);
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (CraftingInfo craft : queue.getCrafts()) {
|
public void save(ConfigurationSection config) {
|
||||||
config.set(station + ".recipe-" + craft.getUniqueId().toString() + ".recipe", craft.getRecipe().getId());
|
for (String station : queues.keySet()) {
|
||||||
config.set(station + ".recipe-" + craft.getUniqueId().toString() + ".started", craft.started);
|
CraftingQueue queue = queues.get(station);
|
||||||
config.set(station + ".recipe-" + craft.getUniqueId().toString() + ".delay", craft.delay);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public CraftingQueue getQueue(CraftingStation station) {
|
for (CraftingInfo craft : queue.getCrafts()) {
|
||||||
if (!queues.containsKey(station.getId()))
|
config.set(station + ".recipe-" + craft.getUniqueId().toString() + ".recipe", craft.getRecipe().getId());
|
||||||
queues.put(station.getId(), new CraftingQueue(station));
|
config.set(station + ".recipe-" + craft.getUniqueId().toString() + ".started", craft.started);
|
||||||
return queues.get(station.getId());
|
config.set(station + ".recipe-" + craft.getUniqueId().toString() + ".delay", craft.delay);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class CraftingQueue {
|
public CraftingQueue getQueue(CraftingStation station) {
|
||||||
private final String station;
|
if (!queues.containsKey(station.getId()))
|
||||||
private final List<CraftingInfo> crafts = new ArrayList<>();
|
queues.put(station.getId(), new CraftingQueue(station));
|
||||||
|
return queues.get(station.getId());
|
||||||
|
}
|
||||||
|
|
||||||
public CraftingQueue(CraftingStation station) {
|
public static class CraftingQueue {
|
||||||
this.station = station.getId();
|
private final String station;
|
||||||
}
|
private final List<CraftingInfo> crafts = new ArrayList<>();
|
||||||
|
|
||||||
public List<CraftingInfo> getCrafts() {
|
public CraftingQueue(CraftingStation station) {
|
||||||
return crafts;
|
this.station = station.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isFull(CraftingStation station) {
|
public List<CraftingInfo> getCrafts() {
|
||||||
return crafts.size() >= station.getMaxQueueSize();
|
return crafts;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void remove(CraftingInfo craft) {
|
public boolean isFull(CraftingStation station) {
|
||||||
int index = crafts.indexOf(craft);
|
return crafts.size() >= station.getMaxQueueSize();
|
||||||
if (index != -1)
|
}
|
||||||
for (int j = index; j < crafts.size(); j++)
|
|
||||||
crafts.get(j).removeDelay(Math.max(0, craft.getLeft() - craft.getElapsed()));
|
|
||||||
crafts.remove(craft);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CraftingInfo getCraft(UUID uuid) {
|
public void remove(CraftingInfo craft) {
|
||||||
for (CraftingInfo craft : crafts)
|
int index = crafts.indexOf(craft);
|
||||||
if (craft.getUniqueId().equals(uuid))
|
if (index != -1)
|
||||||
return craft;
|
for (int j = index + 1; j < crafts.size(); j++) {
|
||||||
return null;
|
CraftingInfo nextCraft = crafts.get(j);
|
||||||
}
|
nextCraft.delay = Math.max(0, nextCraft.delay - craft.getLeft());
|
||||||
|
}
|
||||||
|
crafts.remove(craft);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
public CraftingInfo getCraft(UUID uuid) {
|
||||||
* when adding a crafting recipe, the delay is the actual crafting time
|
for (CraftingInfo craft : crafts)
|
||||||
* PLUS the delay left for the previous item since it's a queue.
|
if (craft.getUniqueId().equals(uuid))
|
||||||
*/
|
return craft;
|
||||||
public void add(CraftingRecipe recipe) {
|
return null;
|
||||||
add(recipe, System.currentTimeMillis(),
|
}
|
||||||
(crafts.size() == 0 ? 0 : crafts.get(crafts.size() - 1).getLeft()) + (long) recipe.getCraftingTime() * 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void add(CraftingRecipe recipe, long started, long delay) {
|
/*
|
||||||
crafts.add(new CraftingInfo(recipe, started, delay));
|
* when adding a crafting recipe, the delay is the actual crafting time
|
||||||
}
|
* PLUS the delay left for the previous item since it's a queue.
|
||||||
|
*/
|
||||||
|
public void add(CraftingRecipe recipe) {
|
||||||
|
add(recipe, System.currentTimeMillis(),
|
||||||
|
(crafts.size() == 0 ? 0 : crafts.get(crafts.size() - 1).getLeft()) + (long) recipe.getCraftingTime() * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
@Deprecated
|
private void add(CraftingRecipe recipe, long started, long delay) {
|
||||||
public CraftingStation getStation() {
|
crafts.add(new CraftingInfo(recipe, started, delay));
|
||||||
return MMOItems.plugin.getCrafting().getStation(station);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public class CraftingInfo {
|
@Deprecated
|
||||||
private final String recipe;
|
public CraftingStation getStation() {
|
||||||
private final UUID uuid = UUID.randomUUID();
|
return MMOItems.plugin.getCrafting().getStation(station);
|
||||||
private final long started;
|
}
|
||||||
private long delay;
|
|
||||||
|
|
||||||
private CraftingInfo(CraftingRecipe recipe, long started, long delay) {
|
public class CraftingInfo {
|
||||||
this.recipe = recipe.getId();
|
private final String recipe;
|
||||||
this.started = started;
|
private final UUID uuid = UUID.randomUUID();
|
||||||
this.delay = delay;
|
private final long started;
|
||||||
}
|
private long delay;
|
||||||
|
|
||||||
public UUID getUniqueId() {
|
private CraftingInfo(CraftingRecipe recipe, long started, long delay) {
|
||||||
return uuid;
|
this.recipe = recipe.getId();
|
||||||
}
|
this.started = started;
|
||||||
|
this.delay = delay;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
public UUID getUniqueId() {
|
||||||
* @deprecated /mi reload stations force MI to save the recipe
|
return uuid;
|
||||||
* IDs instead of a direct reference to the crafting recipe
|
}
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public CraftingRecipe getRecipe() {
|
|
||||||
return (CraftingRecipe) getStation().getRecipe(recipe);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isReady() {
|
/**
|
||||||
return getLeft() == 0;
|
* @deprecated /mi reload stations force MI to save the recipe
|
||||||
}
|
* IDs instead of a direct reference to the crafting recipe
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public CraftingRecipe getRecipe() {
|
||||||
|
return (CraftingRecipe) getStation().getRecipe(recipe);
|
||||||
|
}
|
||||||
|
|
||||||
public void removeDelay(long amount) {
|
public boolean isReady() {
|
||||||
this.delay -= amount;
|
return getLeft() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getElapsed() {
|
public void removeDelay(long amount) {
|
||||||
return Math.max((long) getRecipe().getCraftingTime() * 1000, System.currentTimeMillis() - started);
|
this.delay -= amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getLeft() {
|
public long getElapsed() {
|
||||||
return Math.max(0, started + delay - System.currentTimeMillis());
|
return Math.max((long) getRecipe().getCraftingTime() * 1000, System.currentTimeMillis() - started);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public long getLeft() {
|
||||||
public boolean equals(Object obj) {
|
return Math.max(0, started + delay - System.currentTimeMillis());
|
||||||
return obj instanceof CraftingInfo && ((CraftingInfo) obj).uuid.equals(uuid);
|
}
|
||||||
}
|
|
||||||
}
|
@Override
|
||||||
}
|
public boolean equals(Object obj) {
|
||||||
|
return obj instanceof CraftingInfo && ((CraftingInfo) obj).uuid.equals(uuid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,232 +30,273 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
public class CraftingRecipe extends Recipe {
|
public class CraftingRecipe extends Recipe {
|
||||||
@NotNull public static final String UNSPECIFIED = "N/A";
|
@NotNull
|
||||||
|
public static final String UNSPECIFIED = "N/A";
|
||||||
|
|
||||||
public CraftingRecipe(@NotNull ConfigurationSection config) throws IllegalArgumentException {
|
public CraftingRecipe(@NotNull ConfigurationSection config) throws IllegalArgumentException {
|
||||||
super(config);
|
super(config);
|
||||||
|
|
||||||
craftingTime = config.getDouble("crafting-time");
|
craftingTime = config.getDouble("crafting-time");
|
||||||
|
|
||||||
// Legacy loading
|
// Legacy loading
|
||||||
String uiFilter = config.getString("output.item", UNSPECIFIED);
|
String uiFilter = config.getString("output.item", UNSPECIFIED);
|
||||||
String miType = config.getString("output.type", UNSPECIFIED).toUpperCase().replace("-", "_").replace(" ", "_");
|
String miType = config.getString("output.type", UNSPECIFIED).toUpperCase().replace("-", "_").replace(" ", "_");
|
||||||
String miID = config.getString("output.id", UNSPECIFIED).toUpperCase().replace("-", "_").replace(" ", "_");
|
String miID = config.getString("output.id", UNSPECIFIED).toUpperCase().replace("-", "_").replace(" ", "_");
|
||||||
|
|
||||||
// Yes
|
// Yes
|
||||||
FriendlyFeedbackProvider ffp = new FriendlyFeedbackProvider(FFPMMOItems.get());
|
FriendlyFeedbackProvider ffp = new FriendlyFeedbackProvider(FFPMMOItems.get());
|
||||||
|
|
||||||
// Both legacy specified?
|
// Both legacy specified?
|
||||||
if (!UNSPECIFIED.equals(miType) && !UNSPECIFIED.equals(miID)) {
|
if (!UNSPECIFIED.equals(miType) && !UNSPECIFIED.equals(miID)) {
|
||||||
|
|
||||||
// Generate filter
|
// Generate filter
|
||||||
ProvidedUIFilter sweetOutput = UIFilterManager.getUIFilter("m", miType, miID, config.getString("output.amount", "1"), ffp);
|
ProvidedUIFilter sweetOutput = UIFilterManager.getUIFilter("m", miType, miID, config.getString("output.amount", "1"), ffp);
|
||||||
|
|
||||||
// Is it null?
|
// Is it null?
|
||||||
if (sweetOutput == null) {
|
if (sweetOutput == null) {
|
||||||
|
|
||||||
// Throw message
|
// Throw message
|
||||||
throw new IllegalArgumentException(SilentNumbers.collapseList(SilentNumbers.transcribeList(ffp.getFeedbackOf(FriendlyFeedbackCategory.ERROR), message -> { if (message instanceof FriendlyFeedbackMessage) { return ((FriendlyFeedbackMessage) message).forConsole(FFPMMOItems.get()); } return ""; }), ""));
|
throw new IllegalArgumentException(SilentNumbers.collapseList(SilentNumbers.transcribeList(ffp.getFeedbackOf(FriendlyFeedbackCategory.ERROR), message -> {
|
||||||
}
|
if (message instanceof FriendlyFeedbackMessage) {
|
||||||
|
return ((FriendlyFeedbackMessage) message).forConsole(FFPMMOItems.get());
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}), ""));
|
||||||
|
}
|
||||||
|
|
||||||
// Accept
|
// Accept
|
||||||
output = sweetOutput;
|
output = sweetOutput;
|
||||||
|
|
||||||
// New method specified?
|
// New method specified?
|
||||||
} else if (!UNSPECIFIED.equals(uiFilter)) {
|
} else if (!UNSPECIFIED.equals(uiFilter)) {
|
||||||
|
|
||||||
// Generate filter
|
// Generate filter
|
||||||
ProvidedUIFilter sweetOutput = UIFilterManager.getUIFilter(uiFilter, ffp);
|
ProvidedUIFilter sweetOutput = UIFilterManager.getUIFilter(uiFilter, ffp);
|
||||||
|
|
||||||
// Is it null?
|
// Is it null?
|
||||||
if (sweetOutput == null) {
|
if (sweetOutput == null) {
|
||||||
|
|
||||||
// Throw message
|
// Throw message
|
||||||
throw new IllegalArgumentException(SilentNumbers.collapseList(SilentNumbers.transcribeList(ffp.getFeedbackOf(FriendlyFeedbackCategory.ERROR), message -> { if (message instanceof FriendlyFeedbackMessage) { return ((FriendlyFeedbackMessage) message).forConsole(FFPMMOItems.get()); } return ""; }), ""));
|
throw new IllegalArgumentException(SilentNumbers.collapseList(SilentNumbers.transcribeList(ffp.getFeedbackOf(FriendlyFeedbackCategory.ERROR), message -> {
|
||||||
}
|
if (message instanceof FriendlyFeedbackMessage) {
|
||||||
|
return ((FriendlyFeedbackMessage) message).forConsole(FFPMMOItems.get());
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}), ""));
|
||||||
|
}
|
||||||
|
|
||||||
// Accept
|
// Accept
|
||||||
output = sweetOutput;
|
output = sweetOutput;
|
||||||
|
|
||||||
// Invalid filter
|
// Invalid filter
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// Throw message
|
// Throw message
|
||||||
throw new IllegalArgumentException(FriendlyFeedbackProvider.quickForConsole(FFPMMOItems.get(), "Config must contain a valid Type and ID, or a valid UIFilter. "));
|
throw new IllegalArgumentException(FriendlyFeedbackProvider.quickForConsole(FFPMMOItems.get(), "Config must contain a valid Type and ID, or a valid UIFilter. "));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Valid UIFilter?
|
// Valid UIFilter?
|
||||||
if (!output.isValid(ffp)) {
|
if (!output.isValid(ffp)) {
|
||||||
|
|
||||||
// Throw message
|
// Throw message
|
||||||
throw new IllegalArgumentException(SilentNumbers.collapseList(SilentNumbers.transcribeList(ffp.getFeedbackOf(FriendlyFeedbackCategory.ERROR), message -> { if (message instanceof FriendlyFeedbackMessage) { return ((FriendlyFeedbackMessage) message).forConsole(FFPMMOItems.get()); } return ""; }), ""));
|
throw new IllegalArgumentException(SilentNumbers.collapseList(SilentNumbers.transcribeList(ffp.getFeedbackOf(FriendlyFeedbackCategory.ERROR), message -> {
|
||||||
}
|
if (message instanceof FriendlyFeedbackMessage) {
|
||||||
|
return ((FriendlyFeedbackMessage) message).forConsole(FFPMMOItems.get());
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}), ""));
|
||||||
|
}
|
||||||
|
|
||||||
// Valid UIFilter?
|
// Valid UIFilter?
|
||||||
if (output.getItemStack(ffp) == null) {
|
if (output.getItemStack(ffp) == null) {
|
||||||
|
|
||||||
// Throw message
|
// Throw message
|
||||||
throw new IllegalArgumentException(SilentNumbers.collapseList(SilentNumbers.transcribeList(ffp.getFeedbackOf(FriendlyFeedbackCategory.ERROR), message -> { if (message instanceof FriendlyFeedbackMessage) { return ((FriendlyFeedbackMessage) message).forConsole(FFPMMOItems.get()); } return ""; }), ""));
|
throw new IllegalArgumentException(SilentNumbers.collapseList(SilentNumbers.transcribeList(ffp.getFeedbackOf(FriendlyFeedbackCategory.ERROR), message -> {
|
||||||
}
|
if (message instanceof FriendlyFeedbackMessage) {
|
||||||
|
return ((FriendlyFeedbackMessage) message).forConsole(FFPMMOItems.get());
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}), ""));
|
||||||
|
}
|
||||||
|
|
||||||
// Its a MMOItem UIFilter, then?
|
// Its a MMOItem UIFilter, then?
|
||||||
if (output.getParent() instanceof MMOItemUIFilter) {
|
if (output.getParent() instanceof MMOItemUIFilter) {
|
||||||
|
|
||||||
// Find template
|
// Find template
|
||||||
MMOItemTemplate template = MMOItems.plugin.getTemplates().getTemplate(MMOItems.plugin.getTypes().get(output.getArgument()), output.getData());
|
MMOItemTemplate template = MMOItems.plugin.getTemplates().getTemplate(MMOItems.plugin.getTypes().get(output.getArgument()), output.getData());
|
||||||
|
|
||||||
// Not possible tho
|
// Not possible tho
|
||||||
if (template == null) {
|
if (template == null) {
|
||||||
|
|
||||||
// Throw message
|
// Throw message
|
||||||
throw new IllegalArgumentException(FriendlyFeedbackProvider.quickForConsole(FFPMMOItems.get(), "This should be impossible, please contact $egunging$b: $fThe ProvidedUIFilter was flagged as 'valid' but clearly is not. $enet.Indyuce.mmoitems.api.crafting.recipe$b. "));
|
throw new IllegalArgumentException(FriendlyFeedbackProvider.quickForConsole(FFPMMOItems.get(), "This should be impossible, please contact $egunging$b: $fThe ProvidedUIFilter was flagged as 'valid' but clearly is not. $enet.Indyuce.mmoitems.api.crafting.recipe$b. "));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Identify MMOItems operation
|
// Identify MMOItems operation
|
||||||
identifiedMMO = new ConfigMMOItem(template, output.getAmount(1));
|
identifiedMMO = new ConfigMMOItem(template, output.getAmount(1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* There can't be any crafting time for upgrading recipes since there is no
|
* There can't be any crafting time for upgrading recipes since there is no
|
||||||
* way to save an MMOItem in the config file TODO save as ItemStack
|
* way to save an MMOItem in the config file TODO save as ItemStack
|
||||||
*/
|
*/
|
||||||
private final double craftingTime;
|
private final double craftingTime;
|
||||||
public double getCraftingTime() { return craftingTime; }
|
|
||||||
public boolean isInstant() { return craftingTime <= 0; }
|
|
||||||
|
|
||||||
/**
|
public double getCraftingTime() {
|
||||||
* @return The item specified by the player that will be produced by this recipe.
|
return craftingTime;
|
||||||
*/
|
}
|
||||||
@NotNull public ProvidedUIFilter getOutput() { return output; }
|
|
||||||
@NotNull private final ProvidedUIFilter output;
|
|
||||||
|
|
||||||
@Nullable ConfigMMOItem identifiedMMO;
|
public boolean isInstant() {
|
||||||
/**
|
return craftingTime <= 0;
|
||||||
* @return The output ItemStack from this
|
}
|
||||||
*/
|
|
||||||
@SuppressWarnings("ConstantConditions")
|
|
||||||
@NotNull public ItemStack getOutputItemStack(@Nullable RPGPlayer rpg) {
|
|
||||||
|
|
||||||
// Generate as MMOItem
|
/**
|
||||||
if (identifiedMMO != null && rpg != null) {
|
* @return The item specified by the player that will be produced by this recipe.
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public ProvidedUIFilter getOutput() {
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
@NotNull
|
||||||
* Generate in the legacy way. I do this way to preserve
|
private final ProvidedUIFilter output;
|
||||||
* backwards compatibility, since this is how it used to
|
|
||||||
* be done. Don't want to break that without good reason.
|
|
||||||
*/
|
|
||||||
return identifiedMMO.generate(rpg);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate from ProvidedUIFilter, guaranteed to not be null don't listen to the inspection.
|
@Nullable
|
||||||
return output.getItemStack(null);
|
ConfigMMOItem identifiedMMO;
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @return The preview ItemStack from this
|
|
||||||
*/
|
|
||||||
@NotNull public ItemStack getPreviewItemStack() {
|
|
||||||
|
|
||||||
// Generate as MMOItem
|
/**
|
||||||
if (identifiedMMO != null) {
|
* @return The output ItemStack from this
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("ConstantConditions")
|
||||||
|
@NotNull
|
||||||
|
public ItemStack getOutputItemStack(@Nullable RPGPlayer rpg) {
|
||||||
|
|
||||||
/*
|
// Generate as MMOItem
|
||||||
* Generate in the legacy way. I do this way to preserve
|
if (identifiedMMO != null && rpg != null) {
|
||||||
* backwards compatibility, since this is how it used to
|
|
||||||
* be done. Don't want to break that without good reason.
|
|
||||||
*/
|
|
||||||
return identifiedMMO.getPreview();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate from ProvidedUIFilter, guaranteed to not be null don't listen to the inspection.
|
/*
|
||||||
//return output.getParent().getDisplayStack(output.getArgument(), output.getData(), null);
|
* Generate in the legacy way. I do this way to preserve
|
||||||
//return output.getDisplayStack(null);
|
* backwards compatibility, since this is how it used to
|
||||||
ItemStack gen = output.getParent().getDisplayStack(output.getArgument(), output.getData(), null);
|
* be done. Don't want to break that without good reason.
|
||||||
gen.setAmount(output.getAmount(1));
|
*/
|
||||||
ItemMeta itemMeta = gen.getItemMeta();
|
return identifiedMMO.generate(rpg);
|
||||||
if (itemMeta != null) {
|
}
|
||||||
itemMeta.setDisplayName(SilentNumbers.getItemName(gen, false) + "\u00a7\u02ab");
|
|
||||||
gen.setItemMeta(itemMeta); }
|
|
||||||
return gen;
|
|
||||||
}
|
|
||||||
public int getOutputAmount() { return output.getAmount(1); }
|
|
||||||
|
|
||||||
@Override
|
// Generate from ProvidedUIFilter, guaranteed to not be null don't listen to the inspection.
|
||||||
public boolean whenUsed(PlayerData data, IngredientInventory inv, CheckedRecipe recipe, CraftingStation station) {
|
return output.getItemStack(null);
|
||||||
if (!data.isOnline())
|
}
|
||||||
return false;
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* If the recipe is instant, take the ingredients off
|
* @return The preview ItemStack from this
|
||||||
* and directly add the output to the player's inventory
|
*/
|
||||||
*/
|
@NotNull
|
||||||
if (isInstant()) {
|
public ItemStack getPreviewItemStack() {
|
||||||
|
|
||||||
ItemStack result = hasOption(RecipeOption.OUTPUT_ITEM) ? getOutputItemStack(data.getRPG()) : null;
|
// Generate as MMOItem
|
||||||
PlayerUseCraftingStationEvent event = new PlayerUseCraftingStationEvent(data, station, recipe, result);
|
if (identifiedMMO != null) {
|
||||||
Bukkit.getPluginManager().callEvent(event);
|
|
||||||
if (event.isCancelled())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Since instant recipes bypass the crafting queue MI still needs
|
* Generate in the legacy way. I do this way to preserve
|
||||||
* to apply the trigger list when using an instant recipe
|
* backwards compatibility, since this is how it used to
|
||||||
*/
|
* be done. Don't want to break that without good reason.
|
||||||
recipe.getRecipe().whenClaimed().forEach(trigger -> trigger.whenCrafting(data));
|
*/
|
||||||
|
return identifiedMMO.getPreview();
|
||||||
|
}
|
||||||
|
|
||||||
if (result != null)
|
// Generate from ProvidedUIFilter, guaranteed to not be null don't listen to the inspection.
|
||||||
new SmartGive(data.getPlayer()).give(result);
|
//return output.getParent().getDisplayStack(output.getArgument(), output.getData(), null);
|
||||||
|
//return output.getDisplayStack(null);
|
||||||
|
ItemStack gen = output.getParent().getDisplayStack(output.getArgument(), output.getData(), null);
|
||||||
|
gen.setAmount(output.getAmount(1));
|
||||||
|
ItemMeta itemMeta = gen.getItemMeta();
|
||||||
|
if (itemMeta != null) {
|
||||||
|
itemMeta.setDisplayName(SilentNumbers.getItemName(gen, false) + "\u00a7\u02ab");
|
||||||
|
gen.setItemMeta(itemMeta);
|
||||||
|
}
|
||||||
|
return gen;
|
||||||
|
}
|
||||||
|
|
||||||
// Play sound
|
public int getOutputAmount() {
|
||||||
if (!hasOption(RecipeOption.SILENT_CRAFT))
|
return output.getAmount(1);
|
||||||
data.getPlayer().playSound(data.getPlayer().getLocation(), station.getSound(), 1, 1);
|
}
|
||||||
|
|
||||||
// Recipe was successfully used
|
@Override
|
||||||
return true;
|
public boolean whenUsed(PlayerData data, IngredientInventory inv, CheckedRecipe recipe, CraftingStation station) {
|
||||||
|
if (!data.isOnline())
|
||||||
|
return false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the recipe is not instant, add the item to the crafting queue
|
* If the recipe is instant, take the ingredients off
|
||||||
*/
|
* and directly add the output to the player's inventory
|
||||||
} else {
|
*/
|
||||||
|
if (isInstant()) {
|
||||||
|
ItemStack result = hasOption(RecipeOption.OUTPUT_ITEM) ? getOutputItemStack(data.getRPG()) : null;
|
||||||
|
PlayerUseCraftingStationEvent event = new PlayerUseCraftingStationEvent(data, station, recipe, result);
|
||||||
|
Bukkit.getPluginManager().callEvent(event);
|
||||||
|
if (event.isCancelled())
|
||||||
|
return false;
|
||||||
|
|
||||||
PlayerUseCraftingStationEvent called = new PlayerUseCraftingStationEvent(data, station, recipe);
|
/*
|
||||||
Bukkit.getPluginManager().callEvent(called);
|
* Since instant recipes bypass the crafting queue MI still needs
|
||||||
if (called.isCancelled())
|
* to apply the trigger list when using an instant recipe
|
||||||
return false;
|
*/
|
||||||
|
recipe.getRecipe().whenClaimed().forEach(trigger -> trigger.whenCrafting(data));
|
||||||
|
|
||||||
// Play sound
|
if (result != null)
|
||||||
if (!hasOption(RecipeOption.SILENT_CRAFT))
|
new SmartGive(data.getPlayer()).give(result);
|
||||||
data.getPlayer().playSound(data.getPlayer().getLocation(), station.getSound(), 1, 1);
|
|
||||||
|
|
||||||
data.getCrafting().getQueue(station).add(this);
|
// Play sound
|
||||||
|
if (!hasOption(RecipeOption.SILENT_CRAFT))
|
||||||
|
data.getPlayer().playSound(data.getPlayer().getLocation(), station.getSound(), 1, 1);
|
||||||
|
|
||||||
// Recipe was successfully used
|
// Recipe was successfully used
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
/*
|
||||||
public boolean canUse(PlayerData data, IngredientInventory inv, CheckedRecipe recipe, CraftingStation station) {
|
* If the recipe is not instant, add the item to the crafting queue
|
||||||
if (isInstant())
|
*/
|
||||||
return true;
|
}
|
||||||
|
|
||||||
CraftingQueue queue = data.getCrafting().getQueue(station);
|
PlayerUseCraftingStationEvent called = new PlayerUseCraftingStationEvent(data, station, recipe);
|
||||||
if (queue.isFull(station)) {
|
Bukkit.getPluginManager().callEvent(called);
|
||||||
if (!data.isOnline())
|
if (called.isCancelled())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Message.CRAFTING_QUEUE_FULL.format(ChatColor.RED).send(data.getPlayer());
|
// Play sound
|
||||||
data.getPlayer().playSound(data.getPlayer().getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 1);
|
if (!hasOption(RecipeOption.SILENT_CRAFT))
|
||||||
return false;
|
data.getPlayer().playSound(data.getPlayer().getLocation(), station.getSound(), 1, 1);
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
data.getCrafting().getQueue(station).add(this);
|
||||||
public ItemStack display(CheckedRecipe recipe) { return ConfigItems.CRAFTING_RECIPE_DISPLAY.newBuilder(recipe).build(); }
|
|
||||||
|
|
||||||
@Override
|
// Recipe was successfully used
|
||||||
public CheckedRecipe evaluateRecipe(PlayerData data, IngredientInventory inv) {
|
return true;
|
||||||
return new CheckedRecipe(this, data, inv);
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
|
public boolean canUse(PlayerData data, IngredientInventory inv, CheckedRecipe recipe, CraftingStation station) {
|
||||||
|
if (isInstant())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
CraftingQueue queue = data.getCrafting().getQueue(station);
|
||||||
|
if (queue.isFull(station)) {
|
||||||
|
if (!data.isOnline())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Message.CRAFTING_QUEUE_FULL.format(ChatColor.RED).send(data.getPlayer());
|
||||||
|
data.getPlayer().playSound(data.getPlayer().getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 1);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack display(CheckedRecipe recipe) {
|
||||||
|
return ConfigItems.CRAFTING_RECIPE_DISPLAY.newBuilder(recipe).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CheckedRecipe evaluateRecipe(PlayerData data, IngredientInventory inv) {
|
||||||
|
return new CheckedRecipe(this, data, inv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,10 +33,9 @@ public class ItemSkin extends UseItem {
|
|||||||
if (targetType == Type.SKIN)
|
if (targetType == Type.SKIN)
|
||||||
return new ApplyResult(ResultType.NONE);
|
return new ApplyResult(ResultType.NONE);
|
||||||
|
|
||||||
if (MMOItems.plugin.getConfig().getBoolean("locked-skins") && target.getBoolean("MMOITEMS_HAS_SKIN")) {
|
if (MMOItems.plugin.getConfig().getBoolean("locked-skins") && MMOUtils.isNonEmpty(target.getString(ItemSkin.SKIN_ID_TAG))) {
|
||||||
player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 1);
|
player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 1);
|
||||||
Message.SKIN_REJECTED.format(ChatColor.RED, "#item#", MMOUtils.getDisplayName(target.getItem()))
|
Message.SKIN_REJECTED.format(ChatColor.RED, "#item#", MMOUtils.getDisplayName(target.getItem())).send(player);
|
||||||
.send(player);
|
|
||||||
return new ApplyResult(ResultType.NONE);
|
return new ApplyResult(ResultType.NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,8 +101,6 @@ public class ItemSkin extends UseItem {
|
|||||||
return new ApplyResult(item);
|
return new ApplyResult(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final String HAS_SKIN_TAG = "MMOITEMS_HAS_SKIN";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When applying a skin to an item, the skin item ID is saved
|
* When applying a skin to an item, the skin item ID is saved
|
||||||
* in the target item so that if deskined, it can be retrieved
|
* in the target item so that if deskined, it can be retrieved
|
||||||
@ -113,118 +110,67 @@ public class ItemSkin extends UseItem {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies the skin information from a skin consumable onto any item.
|
* Applies the skin information from a skin consumable onto any item.
|
||||||
|
* <p>
|
||||||
|
* This methods also works if the provided VolatileMMOItem matches an item
|
||||||
|
* that already has a skin information stored inside of it, in which case it
|
||||||
|
* will fetch the value of the {@link #SKIN_ID_TAG} nbttag.
|
||||||
*
|
*
|
||||||
* @param target Target item that the skin has been <b>successfully</b> applied to
|
* @param target Target item that the skin has been <b>successfully</b> applied to
|
||||||
* @param skinItemMMO Skin consumable
|
* @param volSkin Skin consumable
|
||||||
* @return Built ItemStack from the target NBT but with the skin data contained in the skin consumable
|
* @return Built ItemStack from the target NBT but with the skin data contained in the skin consumable
|
||||||
|
* @deprecated Badly implemented. This handles individual stats and should use some SkinStat interface
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
@NotNull
|
@NotNull
|
||||||
public static ItemStack applySkin(@NotNull NBTItem target, @NotNull VolatileMMOItem skinItemMMO) {
|
public static ItemStack applySkin(@NotNull NBTItem target, @NotNull VolatileMMOItem volSkin) {
|
||||||
final NBTItem skinItemNBT = skinItemMMO.getNBT();
|
final NBTItem nbtSkin = volSkin.getNBT();
|
||||||
|
|
||||||
target.addTag(new ItemTag(HAS_SKIN_TAG, true));
|
// Apply skin ID to new item
|
||||||
target.addTag(new ItemTag(SKIN_ID_TAG, skinItemNBT.getString("MMOITEMS_ITEM_ID")));
|
@Nullable String appliedSkinId = volSkin.getNBT().getString(SKIN_ID_TAG);
|
||||||
if (skinItemNBT.getInteger("CustomModelData") != 0)
|
appliedSkinId = MMOUtils.isNonEmpty(appliedSkinId) ? appliedSkinId : nbtSkin.getString("MMOITEMS_ITEM_ID");
|
||||||
target.addTag(new ItemTag("CustomModelData", skinItemNBT.getInteger("CustomModelData")));
|
target.addTag(new ItemTag(SKIN_ID_TAG, appliedSkinId));
|
||||||
|
|
||||||
if (!skinItemNBT.getString("MMOITEMS_ITEM_PARTICLES").isEmpty())
|
// Custom model data
|
||||||
target.addTag(new ItemTag("MMOITEMS_ITEM_PARTICLES", skinItemNBT.getString("MMOITEMS_ITEM_PARTICLES")));
|
if (nbtSkin.getInteger("CustomModelData") != 0)
|
||||||
|
target.addTag(new ItemTag("CustomModelData", nbtSkin.getInteger("CustomModelData")));
|
||||||
|
|
||||||
ItemStack item = target.toItem();
|
// Particles
|
||||||
if (item.getType() != skinItemNBT.getItem().getType())
|
if (!nbtSkin.getString("MMOITEMS_ITEM_PARTICLES").isEmpty())
|
||||||
item.setType(skinItemNBT.getItem().getType());
|
target.addTag(new ItemTag("MMOITEMS_ITEM_PARTICLES", nbtSkin.getString("MMOITEMS_ITEM_PARTICLES")));
|
||||||
|
|
||||||
ItemMeta meta = item.getItemMeta();
|
final ItemStack item = target.toItem();
|
||||||
ItemMeta skinMeta = skinItemNBT.getItem().getItemMeta();
|
if (item.getType() != nbtSkin.getItem().getType())
|
||||||
|
item.setType(nbtSkin.getItem().getType());
|
||||||
|
|
||||||
|
final ItemMeta meta = item.getItemMeta();
|
||||||
|
final ItemMeta skinMeta = nbtSkin.getItem().getItemMeta();
|
||||||
if (skinMeta != null && meta != null) {
|
if (skinMeta != null && meta != null) {
|
||||||
|
|
||||||
// TODO factorize with a ItemSkinStat stat interface
|
// TODO SkinStat interface
|
||||||
|
|
||||||
|
// Unbreakable & durability
|
||||||
if (skinMeta.isUnbreakable()) {
|
if (skinMeta.isUnbreakable()) {
|
||||||
meta.setUnbreakable(true);
|
meta.setUnbreakable(true);
|
||||||
if (meta instanceof Damageable && skinMeta instanceof Damageable)
|
if (meta instanceof Damageable && skinMeta instanceof Damageable)
|
||||||
((Damageable) meta).setDamage(((Damageable) skinMeta).getDamage());
|
((Damageable) meta).setDamage(((Damageable) skinMeta).getDamage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Leather armor
|
||||||
if (skinMeta instanceof LeatherArmorMeta && meta instanceof LeatherArmorMeta)
|
if (skinMeta instanceof LeatherArmorMeta && meta instanceof LeatherArmorMeta)
|
||||||
((LeatherArmorMeta) meta).setColor(((LeatherArmorMeta) skinMeta).getColor());
|
((LeatherArmorMeta) meta).setColor(((LeatherArmorMeta) skinMeta).getColor());
|
||||||
|
|
||||||
if (skinItemMMO.hasData(ItemStats.SKULL_TEXTURE) && item.getType() == VersionMaterial.PLAYER_HEAD.toMaterial()
|
// Skull texture
|
||||||
&& skinItemNBT.getItem().getType() == VersionMaterial.PLAYER_HEAD.toMaterial()) {
|
if (volSkin.hasData(ItemStats.SKULL_TEXTURE)
|
||||||
|
&& item.getType() == VersionMaterial.PLAYER_HEAD.toMaterial()
|
||||||
|
&& nbtSkin.getItem().getType() == VersionMaterial.PLAYER_HEAD.toMaterial())
|
||||||
try {
|
try {
|
||||||
Field profileField = meta.getClass().getDeclaredField("profile");
|
final Field profileField = meta.getClass().getDeclaredField("profile");
|
||||||
profileField.setAccessible(true);
|
profileField.setAccessible(true);
|
||||||
profileField.set(meta,
|
profileField.set(meta,
|
||||||
((SkullTextureData) skinItemMMO.getData(ItemStats.SKULL_TEXTURE)).getGameProfile());
|
((SkullTextureData) volSkin.getData(ItemStats.SKULL_TEXTURE)).getGameProfile());
|
||||||
} catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) {
|
} catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) {
|
||||||
MMOItems.plugin.getLogger().warning("Could not read skull texture");
|
MMOItems.plugin.getLogger().warning("Could not read skull texture");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
item.setItemMeta(meta);
|
|
||||||
}
|
|
||||||
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copies a skin from one item to another
|
|
||||||
*
|
|
||||||
* @param target Target item that you are copying the skin onto
|
|
||||||
* @param originalItemNBT Item with a skin already, as NBT. Operation will fail
|
|
||||||
* if it doesnt have a skin.
|
|
||||||
* @return Built ItemStack from the target NBT but with the skin data contained in the skin consumable
|
|
||||||
* @author Gunging
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public static ItemStack applySkin(@NotNull NBTItem target, @NotNull NBTItem originalItemNBT) {
|
|
||||||
|
|
||||||
// No skin no service
|
|
||||||
if (!originalItemNBT.getBoolean(HAS_SKIN_TAG)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy over data
|
|
||||||
target.addTag(new ItemTag(HAS_SKIN_TAG, true));
|
|
||||||
target.addTag(new ItemTag(SKIN_ID_TAG, originalItemNBT.getString("MMOITEMS_ITEM_ID")));
|
|
||||||
if (originalItemNBT.getInteger("CustomModelData") != 0) {
|
|
||||||
target.addTag(new ItemTag("CustomModelData", originalItemNBT.getInteger("CustomModelData")));
|
|
||||||
}
|
|
||||||
if (!originalItemNBT.getString("MMOITEMS_ITEM_PARTICLES").isEmpty()) {
|
|
||||||
target.addTag(new ItemTag("MMOITEMS_ITEM_PARTICLES", originalItemNBT.getString("MMOITEMS_ITEM_PARTICLES")));
|
|
||||||
}
|
|
||||||
|
|
||||||
// ItemMeta values copy-over
|
|
||||||
ItemStack item = target.toItem();
|
|
||||||
if (item.getType() != originalItemNBT.getItem().getType()) {
|
|
||||||
item.setType(originalItemNBT.getItem().getType());
|
|
||||||
}
|
|
||||||
|
|
||||||
ItemMeta meta = item.getItemMeta();
|
|
||||||
ItemMeta originalMeta = originalItemNBT.getItem().getItemMeta();
|
|
||||||
if (originalMeta != null && meta != null) {
|
|
||||||
|
|
||||||
if (originalMeta.isUnbreakable()) {
|
|
||||||
meta.setUnbreakable(true);
|
|
||||||
if (meta instanceof Damageable && originalMeta instanceof Damageable)
|
|
||||||
((Damageable) meta).setDamage(((Damageable) originalMeta).getDamage());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (originalMeta instanceof LeatherArmorMeta && meta instanceof LeatherArmorMeta)
|
|
||||||
((LeatherArmorMeta) meta).setColor(((LeatherArmorMeta) originalMeta).getColor());
|
|
||||||
|
|
||||||
VolatileMMOItem originalVolatile = new VolatileMMOItem(originalItemNBT);
|
|
||||||
if (originalVolatile.hasData(ItemStats.SKULL_TEXTURE) && item.getType() == VersionMaterial.PLAYER_HEAD.toMaterial()
|
|
||||||
&& originalItemNBT.getItem().getType() == VersionMaterial.PLAYER_HEAD.toMaterial()) {
|
|
||||||
|
|
||||||
try {
|
|
||||||
Field profileField = meta.getClass().getDeclaredField("profile");
|
|
||||||
profileField.setAccessible(true);
|
|
||||||
profileField.set(meta,
|
|
||||||
((SkullTextureData) originalVolatile.getData(ItemStats.SKULL_TEXTURE)).getGameProfile());
|
|
||||||
} catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) {
|
|
||||||
MMOItems.plugin.getLogger().warning("Could not read skull texture");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
item.setItemMeta(meta);
|
item.setItemMeta(meta);
|
||||||
}
|
}
|
||||||
|
@ -175,40 +175,22 @@ public class MMOItemBuilder {
|
|||||||
* with strictly higher priority. If there are none, adds modifier and
|
* with strictly higher priority. If there are none, adds modifier and
|
||||||
* clears less priority modifiers
|
* clears less priority modifiers
|
||||||
*
|
*
|
||||||
* @param modifier Name modifier which needs to be added
|
* @param modifier Name modifier which needs to be added
|
||||||
* @param mod UUID of storage into the Stat History of name
|
* @param modifierId UUID of storage into the Stat History of name
|
||||||
*/
|
*/
|
||||||
public void addModifier(@NotNull NameModifier modifier, @NotNull UUID mod) {
|
public void addModifier(@NotNull NameModifier modifier, @NotNull UUID modifierId) {
|
||||||
|
|
||||||
// Might overwrite a modifier yes
|
// Might overwrite a modifier
|
||||||
ArrayList<UUID> removedObs = new ArrayList<>();
|
final Iterator<NameModifier> ite = nameModifiers.values().iterator();
|
||||||
for (UUID cUID : nameModifiers.keySet()) {
|
while (ite.hasNext()) {
|
||||||
|
final NameModifier obs = ite.next();
|
||||||
// Remove obs?
|
|
||||||
NameModifier obs = nameModifiers.get(cUID);
|
|
||||||
|
|
||||||
// Are they the same type?
|
|
||||||
if (obs.getType() == modifier.getType()) {
|
if (obs.getType() == modifier.getType()) {
|
||||||
|
if (obs.getPriority() > modifier.getPriority()) return;
|
||||||
// Choose greater priority
|
else if (obs.getPriority() < modifier.getPriority()) ite.remove();
|
||||||
if (obs.getPriority() > modifier.getPriority()) {
|
|
||||||
|
|
||||||
// Keep old one
|
|
||||||
return;
|
|
||||||
|
|
||||||
} else if (obs.getPriority() < modifier.getPriority()) {
|
|
||||||
|
|
||||||
// Remove old one and add new one
|
|
||||||
removedObs.add(cUID);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove
|
nameModifiers.put(modifierId, modifier);
|
||||||
for (UUID ro : removedObs) {
|
|
||||||
nameModifiers.remove(ro);
|
|
||||||
}
|
|
||||||
nameModifiers.put(mod, modifier);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4,16 +4,17 @@ import io.lumine.mythic.lib.api.item.NBTItem;
|
|||||||
import net.Indyuce.mmoitems.MMOItems;
|
import net.Indyuce.mmoitems.MMOItems;
|
||||||
import net.Indyuce.mmoitems.api.util.message.Message;
|
import net.Indyuce.mmoitems.api.util.message.Message;
|
||||||
import net.Indyuce.mmoitems.stat.type.ItemRestriction;
|
import net.Indyuce.mmoitems.stat.type.ItemRestriction;
|
||||||
|
import net.Indyuce.mmoitems.util.MMOUtils;
|
||||||
import org.bukkit.ChatColor;
|
import org.bukkit.ChatColor;
|
||||||
import org.bukkit.Sound;
|
import org.bukkit.Sound;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface class between RPG core plugins like Heroes, MythicCore, SkillAPI
|
* Interface class between RPG core plugins like
|
||||||
* and MMOItems
|
* Heroes, MythicCore, SkillAPI, MMOCore and MMOItems
|
||||||
*
|
*
|
||||||
* @author indyuce
|
* @author Jules
|
||||||
*/
|
*/
|
||||||
public abstract class RPGPlayer {
|
public abstract class RPGPlayer {
|
||||||
private final PlayerData playerData;
|
private final PlayerData playerData;
|
||||||
@ -106,7 +107,9 @@ public abstract class RPGPlayer {
|
|||||||
* if it fails (returning true even if it is not met).
|
* if it fails (returning true even if it is not met).
|
||||||
* @see ItemRestriction#isDynamic()
|
* @see ItemRestriction#isDynamic()
|
||||||
*/
|
*/
|
||||||
public boolean canUse(NBTItem item, boolean message, boolean allowDynamic) {
|
public boolean canUse(@NotNull NBTItem item, boolean message, boolean allowDynamic) {
|
||||||
|
|
||||||
|
// Unidentification
|
||||||
if (item.hasTag("MMOITEMS_UNIDENTIFIED_ITEM")) {
|
if (item.hasTag("MMOITEMS_UNIDENTIFIED_ITEM")) {
|
||||||
if (message) {
|
if (message) {
|
||||||
Message.UNIDENTIFIED_ITEM.format(ChatColor.RED).send(player.getPlayer());
|
Message.UNIDENTIFIED_ITEM.format(ChatColor.RED).send(player.getPlayer());
|
||||||
@ -115,13 +118,13 @@ public abstract class RPGPlayer {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//REQ//MMOItems. Log("Checking REQS");
|
// Item has been disabled
|
||||||
for (ItemRestriction condition : MMOItems.plugin.getStats().getItemRestrictionStats())
|
if (MMOItems.plugin.getLanguage().disableRemovedItems && MMOUtils.hasBeenRemoved(item)) return false;
|
||||||
if (!condition.isDynamic() || !allowDynamic)
|
|
||||||
if (!condition.canUse(this, item, message))
|
// Stat-based requirements
|
||||||
return false;
|
for (ItemRestriction condition : MMOItems.plugin.getStats().getItemRestrictionStats())
|
||||||
|
if (!condition.isDynamic() || !allowDynamic) if (!condition.canUse(this, item, message)) return false;
|
||||||
|
|
||||||
//REQ//MMOItems. Log(" \u00a7a> Success use");
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,18 +28,13 @@ import java.util.ArrayList;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class to manage modification of items with reference to what they used to be
|
* A class to manage modification of items with reference to what
|
||||||
* (and apparently also used to automatically apply SoulBounds):
|
* they used to be. Updating/reforging refers to changing the base
|
||||||
|
* stats of a MMOItem instance to what the template currently has,
|
||||||
|
* usually keeping gem stones and upgrade level. This won't reroll
|
||||||
|
* RNG stats unless the specific option is toggled on.
|
||||||
*
|
*
|
||||||
* <p><code><b>updating</b></code> refers to changing the base stats
|
* @author Gunging, Jules
|
||||||
* of a MMOItem instance to what the template currently has, usually
|
|
||||||
* keeping gem stones and upgrade level. This wont reroll RNG stats.</p>
|
|
||||||
*
|
|
||||||
* <p><code><b>reforging</b></code> same thing as updating, but rerolling
|
|
||||||
* the RNG stats - basically transferring the data specified by the
|
|
||||||
* {@link ReforgeOptions} into a new item of the same Type-ID</p>
|
|
||||||
*
|
|
||||||
* @author Gunging
|
|
||||||
*/
|
*/
|
||||||
public class MMOItemReforger {
|
public class MMOItemReforger {
|
||||||
|
|
||||||
@ -135,7 +130,7 @@ public class MMOItemReforger {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The meta of {@link #getStack()} but without that
|
* @return The meta of {@link #getStack()} but without that
|
||||||
* pesky {@link Nullable} annotation.
|
* pesky {@link Nullable} annotation.
|
||||||
*/
|
*/
|
||||||
@NotNull
|
@NotNull
|
||||||
@Deprecated
|
@Deprecated
|
||||||
@ -183,8 +178,8 @@ public class MMOItemReforger {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The MMOItem being updated. For safety, it should be cloned,
|
* @return The MMOItem being updated. For safety, it should be cloned,
|
||||||
* in case any plugin decides to make changes in it... though
|
* in case any plugin decides to make changes in it... though
|
||||||
* this should be entirely for <b>reading purposes only</b>.
|
* this should be entirely for <b>reading purposes only</b>.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({"NullableProblems", "ConstantConditions"})
|
@SuppressWarnings({"NullableProblems", "ConstantConditions"})
|
||||||
@NotNull
|
@NotNull
|
||||||
@ -222,7 +217,7 @@ public class MMOItemReforger {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The Updated version of the MMOItem, with
|
* @return The Updated version of the MMOItem, with
|
||||||
* its revised stats.
|
* its revised stats.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({"NullableProblems", "ConstantConditions"})
|
@SuppressWarnings({"NullableProblems", "ConstantConditions"})
|
||||||
@NotNull
|
@NotNull
|
||||||
@ -241,7 +236,7 @@ public class MMOItemReforger {
|
|||||||
/**
|
/**
|
||||||
* @return If this is a loaded template. That's all required.
|
* @return If this is a loaded template. That's all required.
|
||||||
* @deprecated Ambigous method, not finding a corresponding item
|
* @deprecated Ambigous method, not finding a corresponding item
|
||||||
* template isn't the only fail factor.
|
* template isn't the only fail factor.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public boolean canReforge() {
|
public boolean canReforge() {
|
||||||
@ -330,7 +325,7 @@ public class MMOItemReforger {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The item level modifying the values of RandomStatData
|
* @return The item level modifying the values of RandomStatData
|
||||||
* upon creating a new MMOItem from the template.
|
* upon creating a new MMOItem from the template.
|
||||||
*/
|
*/
|
||||||
public int getGenerationItemLevel() {
|
public int getGenerationItemLevel() {
|
||||||
return generationItemLevel;
|
return generationItemLevel;
|
||||||
@ -361,42 +356,18 @@ public class MMOItemReforger {
|
|||||||
public boolean reforge(@NotNull ReforgeOptions options, @Nullable RPGPlayer player) {
|
public boolean reforge(@NotNull ReforgeOptions options, @Nullable RPGPlayer player) {
|
||||||
|
|
||||||
// Throw fail
|
// Throw fail
|
||||||
if (!hasTemplate())
|
if (!hasTemplate()) return false;
|
||||||
return false;
|
|
||||||
|
|
||||||
// Prepare everything properly
|
// Prepare everything properly
|
||||||
oldMMOItem = new LiveMMOItem(getNBTItem());
|
oldMMOItem = new LiveMMOItem(getNBTItem());
|
||||||
|
|
||||||
// Not blacklisted right!?
|
// Not blacklisted right!?
|
||||||
if (options.isBlacklisted(getOldMMOItem().getId()))
|
if (options.isBlacklisted(getOldMMOItem().getId())) return false;
|
||||||
return false;
|
|
||||||
|
|
||||||
this.player = player;
|
this.player = player;
|
||||||
|
|
||||||
/*
|
|
||||||
* This chunk will determine the level the item was, and
|
|
||||||
* regenerate a new one based on that level ~ the "Item Level" which
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* which I honestly don't know how to use I've just been
|
|
||||||
* copying and pasting this around, leaving this code untouched
|
|
||||||
* since I first started polishing the RevID workings.
|
|
||||||
*
|
|
||||||
* - gunging
|
|
||||||
*/
|
|
||||||
int iLevel = MMOItemReforger.defaultItemLevel;
|
|
||||||
|
|
||||||
// What level with the regenerated item will be hmmmm.....
|
// What level with the regenerated item will be hmmmm.....
|
||||||
generationItemLevel =
|
generationItemLevel = (getOldMMOItem().hasData(ItemStats.ITEM_LEVEL) ? (int) ((DoubleData) getOldMMOItem().getData(ItemStats.ITEM_LEVEL)).getValue() : 0);
|
||||||
|
|
||||||
// No default level specified?
|
|
||||||
(iLevel == -32767) ?
|
|
||||||
|
|
||||||
// Does the item have level?
|
|
||||||
(getOldMMOItem().hasData(ItemStats.ITEM_LEVEL) ? (int) ((DoubleData) getOldMMOItem().getData(ItemStats.ITEM_LEVEL)).getValue() : 0)
|
|
||||||
|
|
||||||
// Default level was specified, use that.
|
|
||||||
: iLevel;
|
|
||||||
|
|
||||||
// Identify tier.
|
// Identify tier.
|
||||||
ItemTier tier =
|
ItemTier tier =
|
||||||
@ -420,8 +391,7 @@ public class MMOItemReforger {
|
|||||||
Bukkit.getPluginManager().callEvent(mmoREV);
|
Bukkit.getPluginManager().callEvent(mmoREV);
|
||||||
|
|
||||||
// Cancelled? it ends there
|
// Cancelled? it ends there
|
||||||
if (mmoREV.isCancelled())
|
if (mmoREV.isCancelled()) return false;
|
||||||
return false;
|
|
||||||
|
|
||||||
// Properly recalculate all based on histories
|
// Properly recalculate all based on histories
|
||||||
for (StatHistory hist : getFreshMMOItem().getStatHistories())
|
for (StatHistory hist : getFreshMMOItem().getStatHistories())
|
||||||
@ -455,12 +425,10 @@ public class MMOItemReforger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//region Config Values
|
//region Config Values
|
||||||
public static int defaultItemLevel = -32767;
|
|
||||||
public static boolean keepTiersWhenReroll = true;
|
public static boolean keepTiersWhenReroll = true;
|
||||||
public static boolean gemstonesRevIDWhenUnsocket = false;
|
public static boolean gemstonesRevIDWhenUnsocket = false;
|
||||||
|
|
||||||
public static void reload() {
|
public static void reload() {
|
||||||
defaultItemLevel = MMOItems.plugin.getConfig().getInt("item-revision.default-item-level", -32767);
|
|
||||||
keepTiersWhenReroll = MMOItems.plugin.getConfig().getBoolean("item-revision.keep-tiers");
|
keepTiersWhenReroll = MMOItems.plugin.getConfig().getBoolean("item-revision.keep-tiers");
|
||||||
gemstonesRevIDWhenUnsocket = MMOItems.plugin.getConfig().getBoolean("item-revision.regenerate-gems-when-unsocketed", false);
|
gemstonesRevIDWhenUnsocket = MMOItems.plugin.getConfig().getBoolean("item-revision.regenerate-gems-when-unsocketed", false);
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,6 @@ import net.Indyuce.mmoitems.api.item.build.MMOItemBuilder;
|
|||||||
import net.Indyuce.mmoitems.stat.data.DoubleData;
|
import net.Indyuce.mmoitems.stat.data.DoubleData;
|
||||||
import net.Indyuce.mmoitems.stat.data.random.RandomStatData;
|
import net.Indyuce.mmoitems.stat.data.random.RandomStatData;
|
||||||
import net.Indyuce.mmoitems.stat.data.random.UpdatableRandomStatData;
|
import net.Indyuce.mmoitems.stat.data.random.UpdatableRandomStatData;
|
||||||
import net.Indyuce.mmoitems.stat.data.type.Mergeable;
|
|
||||||
import net.Indyuce.mmoitems.stat.data.type.StatData;
|
|
||||||
import net.Indyuce.mmoitems.stat.type.ItemStat;
|
import net.Indyuce.mmoitems.stat.type.ItemStat;
|
||||||
import org.apache.commons.lang.Validate;
|
import org.apache.commons.lang.Validate;
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
@ -20,7 +18,7 @@ import java.util.Random;
|
|||||||
*
|
*
|
||||||
* @author indyuce
|
* @author indyuce
|
||||||
*/
|
*/
|
||||||
public class NumericStatFormula implements RandomStatData<DoubleData>, UpdatableRandomStatData {
|
public class NumericStatFormula implements RandomStatData<DoubleData>, UpdatableRandomStatData<DoubleData> {
|
||||||
private final double base, scale, spread, maxSpread;
|
private final double base, scale, spread, maxSpread;
|
||||||
|
|
||||||
private static final Random RANDOM = new Random();
|
private static final Random RANDOM = new Random();
|
||||||
@ -155,34 +153,23 @@ public class NumericStatFormula implements RandomStatData<DoubleData>, Updatable
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param levelScalingFactor Level to scale the scale with
|
* @param levelScalingFactor Level to scale the scale with
|
||||||
* @param random Result of <code>RANDOM.nextGaussian()</code> or whatever other
|
* @param random Result of <code>RANDOM.nextGaussian()</code> or whatever other
|
||||||
* value that you actually want to pass.
|
* value that you actually want to pass.
|
||||||
*
|
|
||||||
* @return The calculated value
|
* @return The calculated value
|
||||||
*/
|
*/
|
||||||
public double calculate(double levelScalingFactor, double random) {
|
public double calculate(double levelScalingFactor, double random) {
|
||||||
|
|
||||||
if (useRelativeSpread) {
|
|
||||||
//SPRD//if (spread > 0) MMOItems.log("\u00a7c༺\u00a77 Using \u00a7eRelative\u00a77 spread formula: \u00a76μ=" + (base + scale * levelScalingFactor) + "\u00a77, \u00a73σ=" + (spread * (base + scale * levelScalingFactor) + "\u00a7b=" + spread + "×" + (base + scale * levelScalingFactor)) + " \u00a7c@" + random + "\u00a7e = " + (base + scale * levelScalingFactor) * (1 + Math.min(Math.max(random * spread, -maxSpread), maxSpread)));
|
|
||||||
return (base + scale * levelScalingFactor) * (1 + Math.min(Math.max(random * spread, -maxSpread), maxSpread));
|
|
||||||
}
|
|
||||||
|
|
||||||
// The mean, the center of the distribution
|
// The mean, the center of the distribution
|
||||||
double actualBase = base + (scale * levelScalingFactor);
|
final double actualBase = base + (scale * levelScalingFactor);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is one pick from a gaussian distribution
|
* This is one pick from a gaussian distribution at mean 0, and
|
||||||
* at mean 0, and standard deviation 1, multiplied
|
* standard deviation 1, multiplied by the spread chosen.
|
||||||
* by the spread chosen.
|
* Does it exceed the max spread (positive or negative)? Not anymore!
|
||||||
*/
|
*/
|
||||||
double flatSpread = random * spread;
|
final double spreadCoef = Math.min(Math.max(random * spread, -maxSpread), maxSpread);
|
||||||
|
|
||||||
// Does it exceed the max spread (positive or negative)? Not anymore!
|
return useRelativeSpread ? actualBase * (1 + spreadCoef) : actualBase + spreadCoef;
|
||||||
flatSpread = Math.min(Math.max(flatSpread, -maxSpread), maxSpread);
|
|
||||||
|
|
||||||
// That's it
|
|
||||||
//SPRD//if (spread > 0) MMOItems.log("\u00a7c༺\u00a77 Using \u00a7aAdditive\u00a77 spread formula, \u00a76μ=" + (base + scale * levelScalingFactor) + "\u00a77, \u00a73σ=" + (spread) + " \u00a7c@" + random + "\u00a7e = " + (actualBase + gaussSpread));
|
|
||||||
return actualBase + flatSpread;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -235,43 +222,27 @@ public class NumericStatFormula implements RandomStatData<DoubleData>, Updatable
|
|||||||
@NotNull
|
@NotNull
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public <T extends StatData> T reroll(@NotNull ItemStat stat, @NotNull T original, int determinedItemLevel) {
|
public DoubleData reroll(@NotNull ItemStat stat, @NotNull DoubleData original, int determinedItemLevel) {
|
||||||
//UPGRD//MMOItems.log("\u00a7a +\u00a77 Valid for Double Data procedure\u00a78 {Original:\u00a77 " + ((DoubleData) original).getValue() + "\u00a78}");
|
|
||||||
|
|
||||||
// Very well, chance checking is only available for NumericStatFormula class so
|
// Very well, chance checking is only available for NumericStatFormula class
|
||||||
double scaledBase = getBase() + (getScale() * determinedItemLevel);
|
final double expectedValue = getBase() + (getScale() * determinedItemLevel);
|
||||||
|
final double previousValue = original.getValue();
|
||||||
// Determine current
|
final double shift = previousValue - expectedValue;
|
||||||
double current = ((DoubleData) original).getValue();
|
final double shiftSD = useRelativeSpread ? Math.abs(shift / (getSpread() * expectedValue)) : Math.abs(shift / getSpread());
|
||||||
|
final double maxSD = getMaxSpread() / getSpread();
|
||||||
// What was the shift?
|
|
||||||
double shift = current - scaledBase;
|
|
||||||
|
|
||||||
// How many standard deviations away?
|
|
||||||
double sD = Math.abs(shift / getSpread());
|
|
||||||
if (useRelativeSpread) { sD = Math.abs(shift / (getSpread() * scaledBase)); }
|
|
||||||
//UPGRD//MMOItems.log("\u00a7b *\u00a77 Base: \u00a73" + base);
|
|
||||||
//UPGRD//MMOItems.log("\u00a7b *\u00a77 Curr: \u00a73" + current);
|
|
||||||
//UPGRD//MMOItems.log("\u00a7b *\u00a77 Shft: \u00a73" + shift);
|
|
||||||
//UPGRD//MMOItems.log("\u00a7b *\u00a77 SDev: \u00a73" + sD);
|
|
||||||
|
|
||||||
// Greater than max spread? Or heck, 0.1% Chance or less wth
|
// Greater than max spread? Or heck, 0.1% Chance or less wth
|
||||||
if (sD > getMaxSpread() || sD > 3.5) {
|
if (shiftSD > maxSD || shiftSD > 3.5) {
|
||||||
//UPGRD//MMOItems.log("\u00a7c -\u00a77 Ridiculous Range --- reroll");
|
|
||||||
|
|
||||||
// Adapt within reason
|
// Just fully reroll value
|
||||||
double reasonableShift = getSpread() * Math.min(2, getMaxSpread());
|
return new DoubleData(calculate(determinedItemLevel));
|
||||||
if (shift < 0) { reasonableShift *= -1;}
|
|
||||||
|
|
||||||
// That's the data we'll use
|
|
||||||
return (T) new DoubleData(reasonableShift + scaledBase);
|
|
||||||
|
|
||||||
// Data arguably fine tbh, just use previous
|
// Data arguably fine tbh, just use previous
|
||||||
} else {
|
} else {
|
||||||
//UPGRD//MMOItems.log("\u00a7a +\u00a77 Acceptable Range --- kept");
|
//UPGRD//MMOItems.log("\u00a7a +\u00a77 Acceptable Range --- kept");
|
||||||
|
|
||||||
// Just clone I guess
|
// Just clone I guess
|
||||||
return (T) ((Mergeable) original).cloneData(); }
|
return original.cloneData(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum FormulaSaveOption {
|
public enum FormulaSaveOption {
|
||||||
|
@ -13,7 +13,7 @@ public class GenerateCommandHandler {
|
|||||||
|
|
||||||
public boolean hasArgument(String key) {
|
public boolean hasArgument(String key) {
|
||||||
for (String argument : arguments)
|
for (String argument : arguments)
|
||||||
if (argument.startsWith("-" + key + ":"))
|
if (argument.startsWith("-" + key))
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -49,29 +49,29 @@ public class GenerateCommandTreeNode extends CommandTreeNode {
|
|||||||
Validate.notNull(give, "You cannot use -gimme");
|
Validate.notNull(give, "You cannot use -gimme");
|
||||||
|
|
||||||
final RPGPlayer rpgPlayer = PlayerData.get(target).getRPG();
|
final RPGPlayer rpgPlayer = PlayerData.get(target).getRPG();
|
||||||
final int itemLevel = handler.hasArgument("level") ? Integer.parseInt(handler.getValue("level"))
|
final int itemLevel = handler.hasArgument("level:") ? Integer.parseInt(handler.getValue("level"))
|
||||||
: (handler.hasArgument("matchlevel") ? MMOItems.plugin.getTemplates().rollLevel(rpgPlayer.getLevel()) : 1 + random.nextInt(100));
|
: (handler.hasArgument("matchlevel") ? MMOItems.plugin.getTemplates().rollLevel(rpgPlayer.getLevel()) : 1 + random.nextInt(100));
|
||||||
final @Nullable ItemTier itemTier = handler.hasArgument("tierset") ? null : handler.hasArgument("tier")
|
final @Nullable ItemTier itemTier = handler.hasArgument("tierset") ? null : handler.hasArgument("tier:")
|
||||||
? MMOItems.plugin.getTiers().getOrThrow(handler.getValue("tier").toUpperCase().replace("-", "_"))
|
? MMOItems.plugin.getTiers().getOrThrow(handler.getValue("tier").toUpperCase().replace("-", "_"))
|
||||||
: MMOItems.plugin.getTemplates().rollTier();
|
: MMOItems.plugin.getTemplates().rollTier();
|
||||||
|
|
||||||
final TemplateExplorer builder = new TemplateExplorer();
|
final TemplateExplorer builder = new TemplateExplorer();
|
||||||
if (handler.hasArgument("matchclass"))
|
if (handler.hasArgument("matchclass"))
|
||||||
builder.applyFilter(new ClassFilter(rpgPlayer));
|
builder.applyFilter(new ClassFilter(rpgPlayer));
|
||||||
if (handler.hasArgument("class"))
|
if (handler.hasArgument("class:"))
|
||||||
builder.applyFilter(new ClassFilter(handler.getValue("class").replace("-", " ").replace("_", " ")));
|
builder.applyFilter(new ClassFilter(handler.getValue("class").replace("-", " ").replace("_", " ")));
|
||||||
String type = null;
|
String type = null;
|
||||||
if (handler.hasArgument("tierset")) {
|
if (handler.hasArgument("tierset:")) {
|
||||||
String format = UtilityMethods.enumName(handler.getValue("tierset"));
|
String format = UtilityMethods.enumName(handler.getValue("tierset"));
|
||||||
Validate.isTrue(MMOItems.plugin.getTiers().has(format), "Could not find tier with ID '" + format + "'");
|
Validate.isTrue(MMOItems.plugin.getTiers().has(format), "Could not find tier with ID '" + format + "'");
|
||||||
builder.applyFilter(new TierFilter(format));
|
builder.applyFilter(new TierFilter(format));
|
||||||
}
|
}
|
||||||
if (handler.hasArgument("type")) {
|
if (handler.hasArgument("type:")) {
|
||||||
type = handler.getValue("type");
|
type = handler.getValue("type");
|
||||||
Validate.isTrue(Type.isValid(type), "Could not find type with ID '" + type + "'");
|
Validate.isTrue(Type.isValid(type), "Could not find type with ID '" + type + "'");
|
||||||
builder.applyFilter(new TypeFilter(Type.get(type)));
|
builder.applyFilter(new TypeFilter(Type.get(type)));
|
||||||
}
|
}
|
||||||
if (handler.hasArgument("id")) {
|
if (handler.hasArgument("id:")) {
|
||||||
Validate.isTrue(type != null, "You have to specify a type if using the id option!");
|
Validate.isTrue(type != null, "You have to specify a type if using the id option!");
|
||||||
builder.applyFilter(new IDFilter(handler.getValue("id")));
|
builder.applyFilter(new IDFilter(handler.getValue("id")));
|
||||||
}
|
}
|
||||||
|
@ -80,7 +80,7 @@ public class ArrowParticlesEdition extends EditionInventory {
|
|||||||
|
|
||||||
if (particle != null) {
|
if (particle != null) {
|
||||||
ConfigurationSection section = getEditedSection().getConfigurationSection("arrow-particles");
|
ConfigurationSection section = getEditedSection().getConfigurationSection("arrow-particles");
|
||||||
if (ParticleData.isColorable(particle)) {
|
if (MMOUtils.isColorable(particle)) {
|
||||||
int red = section.getInt("color.red");
|
int red = section.getInt("color.red");
|
||||||
int green = section.getInt("color.green");
|
int green = section.getInt("color.green");
|
||||||
int blue = section.getInt("color.blue");
|
int blue = section.getInt("color.blue");
|
||||||
|
@ -6,7 +6,6 @@ import net.Indyuce.mmoitems.util.MMOUtils;
|
|||||||
import net.Indyuce.mmoitems.api.edition.StatEdition;
|
import net.Indyuce.mmoitems.api.edition.StatEdition;
|
||||||
import net.Indyuce.mmoitems.api.item.template.MMOItemTemplate;
|
import net.Indyuce.mmoitems.api.item.template.MMOItemTemplate;
|
||||||
import net.Indyuce.mmoitems.particle.api.ParticleType;
|
import net.Indyuce.mmoitems.particle.api.ParticleType;
|
||||||
import net.Indyuce.mmoitems.stat.data.ParticleData;
|
|
||||||
import io.lumine.mythic.lib.api.item.ItemTag;
|
import io.lumine.mythic.lib.api.item.ItemTag;
|
||||||
import io.lumine.mythic.lib.api.item.NBTItem;
|
import io.lumine.mythic.lib.api.item.NBTItem;
|
||||||
import io.lumine.mythic.lib.api.util.AltChar;
|
import io.lumine.mythic.lib.api.util.AltChar;
|
||||||
@ -103,7 +102,7 @@ public class ParticlesEdition extends EditionInventory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ParticleData.isColorable(particle)) {
|
if (MMOUtils.isColorable(particle)) {
|
||||||
int red = getEditedSection().getInt("item-particles.color.red");
|
int red = getEditedSection().getInt("item-particles.color.red");
|
||||||
int green = getEditedSection().getInt("item-particles.color.green");
|
int green = getEditedSection().getInt("item-particles.color.green");
|
||||||
int blue = getEditedSection().getInt("item-particles.color.blue");
|
int blue = getEditedSection().getInt("item-particles.color.blue");
|
||||||
|
@ -42,7 +42,7 @@ public class ConfigManager implements Reloadable {
|
|||||||
private final Map<PotionEffectType, String> potionNames = new HashMap<>();
|
private final Map<PotionEffectType, String> potionNames = new HashMap<>();
|
||||||
|
|
||||||
// Cached config options
|
// Cached config options
|
||||||
public boolean replaceMushroomDrops, worldGenEnabled, upgradeRequirementsCheck, keepSoulboundOnDeath, rerollOnItemUpdate, opStatsEnabled;
|
public boolean replaceMushroomDrops, worldGenEnabled, upgradeRequirementsCheck, keepSoulboundOnDeath, rerollOnItemUpdate, opStatsEnabled, disableRemovedItems;
|
||||||
public String abilitySplitter;
|
public String abilitySplitter;
|
||||||
public double soulboundBaseDamage, soulboundPerLvlDamage, levelSpread;
|
public double soulboundBaseDamage, soulboundPerLvlDamage, levelSpread;
|
||||||
public NumericStatFormula defaultItemCapacity;
|
public NumericStatFormula defaultItemCapacity;
|
||||||
@ -174,6 +174,7 @@ public class ConfigManager implements Reloadable {
|
|||||||
keepSoulboundOnDeath = MMOItems.plugin.getConfig().getBoolean("soulbound.keep-on-death");
|
keepSoulboundOnDeath = MMOItems.plugin.getConfig().getBoolean("soulbound.keep-on-death");
|
||||||
rerollOnItemUpdate = MMOItems.plugin.getConfig().getBoolean("item-revision.reroll-when-updated");
|
rerollOnItemUpdate = MMOItems.plugin.getConfig().getBoolean("item-revision.reroll-when-updated");
|
||||||
levelSpread = MMOItems.plugin.getConfig().getDouble("item-level-spread");
|
levelSpread = MMOItems.plugin.getConfig().getDouble("item-level-spread");
|
||||||
|
disableRemovedItems = MMOItems.plugin.getConfig().getBoolean("disable-removed-items");
|
||||||
|
|
||||||
opStatsEnabled = MMOItems.plugin.getConfig().getBoolean("op-item-stats.enabled");
|
opStatsEnabled = MMOItems.plugin.getConfig().getBoolean("op-item-stats.enabled");
|
||||||
opStats.clear();
|
opStats.clear();
|
||||||
|
@ -64,9 +64,9 @@ public class Abilities extends ItemStat<RandomAbilityListData, AbilityListData>
|
|||||||
|
|
||||||
for (String modifier : ability.getModifiers()) {
|
for (String modifier : ability.getModifiers()) {
|
||||||
item.getLore().registerPlaceholder("ability_" + ability.getAbility().getHandler().getId().toLowerCase() + "_" + modifier,
|
item.getLore().registerPlaceholder("ability_" + ability.getAbility().getHandler().getId().toLowerCase() + "_" + modifier,
|
||||||
MythicLib.plugin.getMMOConfig().decimal.format(ability.getModifier(modifier)));
|
MythicLib.plugin.getMMOConfig().decimals.format(ability.getModifier(modifier)));
|
||||||
abilityLore.add(modifierFormat.replace("{modifier}", ability.getAbility().getModifierName(modifier)).replace("{value}",
|
abilityLore.add(modifierFormat.replace("{modifier}", ability.getAbility().getModifierName(modifier)).replace("{value}",
|
||||||
MythicLib.plugin.getMMOConfig().decimal.format(ability.getModifier(modifier))));
|
MythicLib.plugin.getMMOConfig().decimals.format(ability.getModifier(modifier))));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (splitter)
|
if (splitter)
|
||||||
|
@ -48,7 +48,7 @@ public class ArrowParticles extends ItemStat<ArrowParticlesData, ArrowParticlesD
|
|||||||
int amount = config.getInt("amount");
|
int amount = config.getInt("amount");
|
||||||
double offset = config.getDouble("offset");
|
double offset = config.getDouble("offset");
|
||||||
|
|
||||||
return ParticleData.isColorable(particle)
|
return MMOUtils.isColorable(particle)
|
||||||
? new ArrowParticlesData(particle, amount, offset, config.getInt("color.red"), config.getInt("color.green"),
|
? new ArrowParticlesData(particle, amount, offset, config.getInt("color.red"), config.getInt("color.green"),
|
||||||
config.getInt("color.blue"))
|
config.getInt("color.blue"))
|
||||||
: new ArrowParticlesData(particle, amount, offset, config.getDouble("speed"));
|
: new ArrowParticlesData(particle, amount, offset, config.getDouble("speed"));
|
||||||
@ -105,7 +105,7 @@ public class ArrowParticles extends ItemStat<ArrowParticlesData, ArrowParticlesD
|
|||||||
double offset = json.get("Offset").getAsDouble();
|
double offset = json.get("Offset").getAsDouble();
|
||||||
|
|
||||||
// Ist it colorable'
|
// Ist it colorable'
|
||||||
if (ParticleData.isColorable(particle)) {
|
if (MMOUtils.isColorable(particle)) {
|
||||||
|
|
||||||
// Return as colourable
|
// Return as colourable
|
||||||
return new ArrowParticlesData(particle, amount, offset, json.get("Red").getAsInt(), json.get("Green").getAsInt(), json.get("Blue").getAsInt());
|
return new ArrowParticlesData(particle, amount, offset, json.get("Red").getAsInt(), json.get("Green").getAsInt(), json.get("Blue").getAsInt());
|
||||||
@ -187,7 +187,7 @@ public class ArrowParticles extends ItemStat<ArrowParticlesData, ArrowParticlesD
|
|||||||
lore.add(ChatColor.GRAY + "* Offset: " + ChatColor.WHITE + cast.getOffset());
|
lore.add(ChatColor.GRAY + "* Offset: " + ChatColor.WHITE + cast.getOffset());
|
||||||
lore.add("");
|
lore.add("");
|
||||||
|
|
||||||
if (ParticleData.isColorable(cast.getParticle()))
|
if (MMOUtils.isColorable(cast.getParticle()))
|
||||||
lore.add(ChatColor.translateAlternateColorCodes('&',
|
lore.add(ChatColor.translateAlternateColorCodes('&',
|
||||||
"&7* Color: &c&l" + cast.getRed() + "&7 - &a&l" + cast.getGreen() + "&7 - &9&l" + cast.getBlue()));
|
"&7* Color: &c&l" + cast.getRed() + "&7 - &a&l" + cast.getGreen() + "&7 - &9&l" + cast.getBlue()));
|
||||||
else
|
else
|
||||||
|
@ -7,6 +7,7 @@ import io.lumine.mythic.lib.api.util.SmartGive;
|
|||||||
import io.lumine.mythic.lib.version.VersionMaterial;
|
import io.lumine.mythic.lib.version.VersionMaterial;
|
||||||
import net.Indyuce.mmoitems.ItemStats;
|
import net.Indyuce.mmoitems.ItemStats;
|
||||||
import net.Indyuce.mmoitems.MMOItems;
|
import net.Indyuce.mmoitems.MMOItems;
|
||||||
|
import net.Indyuce.mmoitems.api.interaction.ItemSkin;
|
||||||
import net.Indyuce.mmoitems.util.MMOUtils;
|
import net.Indyuce.mmoitems.util.MMOUtils;
|
||||||
import net.Indyuce.mmoitems.api.Type;
|
import net.Indyuce.mmoitems.api.Type;
|
||||||
import net.Indyuce.mmoitems.api.interaction.Consumable;
|
import net.Indyuce.mmoitems.api.interaction.Consumable;
|
||||||
@ -38,15 +39,14 @@ public class CanDeskin extends BooleanStat implements ConsumableItemInteraction
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean handleConsumableEffect(@NotNull InventoryClickEvent event, @NotNull PlayerData playerData, @NotNull Consumable consumable, @NotNull NBTItem target, Type targetType) {
|
public boolean handleConsumableEffect(@NotNull InventoryClickEvent event, @NotNull PlayerData playerData, @NotNull Consumable consumable, @NotNull NBTItem target, Type targetType) {
|
||||||
final String skinId = target.getString("MMOITEMS_SKIN_ID");
|
final String skinId = target.getString(ItemSkin.SKIN_ID_TAG);
|
||||||
Player player = playerData.getPlayer();
|
Player player = playerData.getPlayer();
|
||||||
|
|
||||||
if (consumable.getNBTItem().getBoolean("MMOITEMS_CAN_DESKIN") && !skinId.isEmpty()) {
|
if (consumable.getNBTItem().getBoolean("MMOITEMS_CAN_DESKIN") && !skinId.isEmpty()) {
|
||||||
|
|
||||||
// Set target item to default skin
|
// Set target item to default skin
|
||||||
String targetItemId = target.getString("MMOITEMS_ITEM_ID");
|
String targetItemId = target.getString("MMOITEMS_ITEM_ID");
|
||||||
target.removeTag("MMOITEMS_HAS_SKIN");
|
target.removeTag(ItemSkin.SKIN_ID_TAG);
|
||||||
target.removeTag("MMOITEMS_SKIN_ID");
|
|
||||||
|
|
||||||
MMOItemTemplate targetTemplate = MMOItems.plugin.getTemplates().getTemplateOrThrow(targetType, targetItemId);
|
MMOItemTemplate targetTemplate = MMOItems.plugin.getTemplates().getTemplateOrThrow(targetType, targetItemId);
|
||||||
MMOItem originalMmoitem = targetTemplate.newBuilder(playerData.getRPG()).build();
|
MMOItem originalMmoitem = targetTemplate.newBuilder(playerData.getRPG()).build();
|
||||||
|
@ -6,12 +6,12 @@ import net.Indyuce.mmoitems.api.item.mmoitem.ReadMMOItem;
|
|||||||
import net.Indyuce.mmoitems.api.util.NumericStatFormula;
|
import net.Indyuce.mmoitems.api.util.NumericStatFormula;
|
||||||
import net.Indyuce.mmoitems.gui.edition.EditionInventory;
|
import net.Indyuce.mmoitems.gui.edition.EditionInventory;
|
||||||
import net.Indyuce.mmoitems.stat.data.DoubleData;
|
import net.Indyuce.mmoitems.stat.data.DoubleData;
|
||||||
import net.Indyuce.mmoitems.stat.data.random.RandomStatData;
|
|
||||||
import net.Indyuce.mmoitems.stat.data.type.StatData;
|
import net.Indyuce.mmoitems.stat.data.type.StatData;
|
||||||
import net.Indyuce.mmoitems.stat.type.InternalStat;
|
import net.Indyuce.mmoitems.stat.type.InternalStat;
|
||||||
import io.lumine.mythic.lib.api.item.ItemTag;
|
import io.lumine.mythic.lib.api.item.ItemTag;
|
||||||
import io.lumine.mythic.lib.version.VersionMaterial;
|
import io.lumine.mythic.lib.version.VersionMaterial;
|
||||||
import net.Indyuce.mmoitems.stat.type.ItemStat;
|
import net.Indyuce.mmoitems.stat.type.ItemStat;
|
||||||
|
import org.apache.commons.lang.NotImplementedException;
|
||||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@ -31,23 +31,22 @@ public class ItemLevel extends ItemStat<NumericStatFormula, DoubleData> implemen
|
|||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public NumericStatFormula whenInitialized(Object object) {
|
public NumericStatFormula whenInitialized(Object object) {
|
||||||
// not supported
|
throw new NotImplementedException();
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void whenClicked(@NotNull EditionInventory inv, @NotNull InventoryClickEvent event) {
|
public void whenClicked(@NotNull EditionInventory inv, @NotNull InventoryClickEvent event) {
|
||||||
// not supported
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void whenInput(@NotNull EditionInventory inv, @NotNull String message, Object... info) {
|
public void whenInput(@NotNull EditionInventory inv, @NotNull String message, Object... info) {
|
||||||
// not supported
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void whenDisplayed(List<String> lore, Optional<NumericStatFormula> statData) {
|
public void whenDisplayed(List<String> lore, Optional<NumericStatFormula> statData) {
|
||||||
// not supported
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
@ -4,10 +4,8 @@ import net.Indyuce.mmoitems.ItemStats;
|
|||||||
import net.Indyuce.mmoitems.api.item.build.ItemStackBuilder;
|
import net.Indyuce.mmoitems.api.item.build.ItemStackBuilder;
|
||||||
import net.Indyuce.mmoitems.api.item.mmoitem.ReadMMOItem;
|
import net.Indyuce.mmoitems.api.item.mmoitem.ReadMMOItem;
|
||||||
import net.Indyuce.mmoitems.gui.edition.EditionInventory;
|
import net.Indyuce.mmoitems.gui.edition.EditionInventory;
|
||||||
import net.Indyuce.mmoitems.stat.data.SoulboundData;
|
|
||||||
import net.Indyuce.mmoitems.stat.data.StoredTagsData;
|
import net.Indyuce.mmoitems.stat.data.StoredTagsData;
|
||||||
import net.Indyuce.mmoitems.stat.data.random.RandomStatData;
|
import net.Indyuce.mmoitems.stat.data.random.RandomStatData;
|
||||||
import net.Indyuce.mmoitems.stat.data.type.StatData;
|
|
||||||
import net.Indyuce.mmoitems.stat.type.GemStoneStat;
|
import net.Indyuce.mmoitems.stat.type.GemStoneStat;
|
||||||
import net.Indyuce.mmoitems.stat.type.InternalStat;
|
import net.Indyuce.mmoitems.stat.type.InternalStat;
|
||||||
import io.lumine.mythic.lib.api.item.ItemTag;
|
import io.lumine.mythic.lib.api.item.ItemTag;
|
||||||
@ -22,6 +20,11 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is another fictive item stat that makes sure that all
|
||||||
|
* the NBT tags from the previous item are transferred towards
|
||||||
|
* the new item.
|
||||||
|
*/
|
||||||
public class StoredTags extends ItemStat<RandomStatData<StoredTagsData>, StoredTagsData> implements InternalStat, GemStoneStat {
|
public class StoredTags extends ItemStat<RandomStatData<StoredTagsData>, StoredTagsData> implements InternalStat, GemStoneStat {
|
||||||
public StoredTags() {
|
public StoredTags() {
|
||||||
super("STORED_TAGS", VersionMaterial.OAK_SIGN.toMaterial(), "Stored Tags",
|
super("STORED_TAGS", VersionMaterial.OAK_SIGN.toMaterial(), "Stored Tags",
|
||||||
|
@ -25,150 +25,151 @@ import java.util.Map;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is not really a stat data since abilities are always
|
||||||
|
* stored as lists inside of items. This is more of a commonly
|
||||||
|
* used utility class which defines the castable implementation
|
||||||
|
* of the {@link Skill} interface for MMOItems.
|
||||||
|
*/
|
||||||
public class AbilityData extends Skill {
|
public class AbilityData extends Skill {
|
||||||
private final RegisteredSkill ability;
|
private final RegisteredSkill ability;
|
||||||
@NotNull private final Map<String, Double> modifiers = new HashMap<>();
|
@NotNull
|
||||||
|
private final Map<String, Double> modifiers = new HashMap<>();
|
||||||
|
|
||||||
public AbilityData(@NotNull JsonObject object) {
|
public AbilityData(@NotNull JsonObject object) {
|
||||||
super(MMOUtils.backwardsCompatibleTriggerType(object.get("CastMode").getAsString()));
|
super(MMOUtils.backwardsCompatibleTriggerType(object.get("CastMode").getAsString()));
|
||||||
|
|
||||||
ability = MMOItems.plugin.getSkills().getSkill(object.get("Id").getAsString());
|
ability = MMOItems.plugin.getSkills().getSkill(object.get("Id").getAsString());
|
||||||
|
|
||||||
JsonObject modifiers = object.getAsJsonObject("Modifiers");
|
JsonObject modifiers = object.getAsJsonObject("Modifiers");
|
||||||
modifiers.entrySet().forEach(entry -> setModifier(entry.getKey(), entry.getValue().getAsDouble()));
|
modifiers.entrySet().forEach(entry -> setModifier(entry.getKey(), entry.getValue().getAsDouble()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public AbilityData(@NotNull ConfigurationSection config) {
|
public AbilityData(@NotNull ConfigurationSection config) {
|
||||||
super(MMOUtils.backwardsCompatibleTriggerType(UtilityMethods.enumName(Objects.requireNonNull(config.getString("mode"), "Ability is missing mode"))));
|
super(MMOUtils.backwardsCompatibleTriggerType(UtilityMethods.enumName(Objects.requireNonNull(config.getString("mode"), "Ability is missing mode"))));
|
||||||
|
|
||||||
Validate.isTrue(config.contains("type"), "Ability is missing type");
|
Validate.isTrue(config.contains("type"), "Ability is missing type");
|
||||||
|
|
||||||
String abilityFormat = UtilityMethods.enumName(config.getString("type"));
|
String abilityFormat = UtilityMethods.enumName(config.getString("type"));
|
||||||
Validate.isTrue(MMOItems.plugin.getSkills().hasSkill(abilityFormat), "Could not find ability called '" + abilityFormat + "'");
|
Validate.isTrue(MMOItems.plugin.getSkills().hasSkill(abilityFormat), "Could not find ability called '" + abilityFormat + "'");
|
||||||
ability = MMOItems.plugin.getSkills().getSkill(abilityFormat);
|
ability = MMOItems.plugin.getSkills().getSkill(abilityFormat);
|
||||||
|
|
||||||
for (String key : config.getKeys(false))
|
for (String key : config.getKeys(false))
|
||||||
if (!key.equalsIgnoreCase("mode") && !key.equalsIgnoreCase("type") && ability.getHandler().getModifiers().contains(key))
|
if (!key.equalsIgnoreCase("mode") && !key.equalsIgnoreCase("type") && ability.getHandler().getModifiers().contains(key))
|
||||||
modifiers.put(key, config.getDouble(key));
|
modifiers.put(key, config.getDouble(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
public AbilityData(RegisteredSkill ability, TriggerType triggerType) {
|
public AbilityData(RegisteredSkill ability, TriggerType triggerType) {
|
||||||
super(triggerType);
|
super(triggerType);
|
||||||
|
|
||||||
this.ability = ability;
|
this.ability = ability;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RegisteredSkill getAbility() {
|
public RegisteredSkill getAbility() {
|
||||||
return ability;
|
return ability;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<String> getModifiers() {
|
public Set<String> getModifiers() {
|
||||||
return modifiers.keySet();
|
return modifiers.keySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setModifier(String path, double value) {
|
public void setModifier(String path, double value) {
|
||||||
// Validate.isTrue(getHandler().getModifiers().contains(path), "Could not find modifier called '" + path + "'");
|
// Validate.isTrue(getHandler().getModifiers().contains(path), "Could not find modifier called '" + path + "'");
|
||||||
modifiers.put(path, value);
|
modifiers.put(path, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasModifier(String path) {
|
public boolean hasModifier(String path) {
|
||||||
return modifiers.containsKey(path);
|
return modifiers.containsKey(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean getResult(SkillMetadata meta) {
|
public boolean getResult(SkillMetadata meta) {
|
||||||
|
|
||||||
PlayerData playerData = PlayerData.get(meta.getCaster().getData().getUniqueId());
|
PlayerData playerData = PlayerData.get(meta.getCaster().getData().getUniqueId());
|
||||||
RPGPlayer rpgPlayer = playerData.getRPG();
|
RPGPlayer rpgPlayer = playerData.getRPG();
|
||||||
Player player = meta.getCaster().getPlayer();
|
Player player = meta.getCaster().getPlayer();
|
||||||
|
|
||||||
// Check for cooldown
|
// Check for cooldown
|
||||||
if (meta.getCaster().getData().getCooldownMap().isOnCooldown(this)) {
|
if (meta.getCaster().getData().getCooldownMap().isOnCooldown(this)) {
|
||||||
CooldownInfo info = playerData.getMMOPlayerData().getCooldownMap().getInfo(this);
|
CooldownInfo info = playerData.getMMOPlayerData().getCooldownMap().getInfo(this);
|
||||||
if (!getTrigger().isSilent()) {
|
if (!getTrigger().isSilent()) {
|
||||||
StringBuilder progressBar = new StringBuilder(ChatColor.YELLOW + "");
|
StringBuilder progressBar = new StringBuilder(ChatColor.YELLOW + "");
|
||||||
double progress = (double) (info.getInitialCooldown() - info.getRemaining()) / info.getInitialCooldown() * 10;
|
double progress = (double) (info.getInitialCooldown() - info.getRemaining()) / info.getInitialCooldown() * 10;
|
||||||
String barChar = MMOItems.plugin.getConfig().getString("cooldown-progress-bar-char");
|
String barChar = MMOItems.plugin.getConfig().getString("cooldown-progress-bar-char");
|
||||||
for (int j = 0; j < 10; j++)
|
for (int j = 0; j < 10; j++)
|
||||||
progressBar.append(progress >= j ? ChatColor.GREEN : ChatColor.WHITE).append(barChar);
|
progressBar.append(progress >= j ? ChatColor.GREEN : ChatColor.WHITE).append(barChar);
|
||||||
Message.SPELL_ON_COOLDOWN.format(ChatColor.RED, "#left#", MythicLib.plugin.getMMOConfig().decimal.format(info.getRemaining() / 1000d), "#progress#",
|
Message.SPELL_ON_COOLDOWN.format(ChatColor.RED, "#left#", MythicLib.plugin.getMMOConfig().decimal.format(info.getRemaining() / 1000d), "#progress#", progressBar.toString(), "#s#", (info.getRemaining() > 1999 ? "s" : "")).send(player);
|
||||||
progressBar.toString(), "#s#", (info.getRemaining() > 1999 ? "s" : "")).send(player);
|
}
|
||||||
}
|
return false;
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Check for permission
|
// Check for permission
|
||||||
if (MMOItems.plugin.getConfig().getBoolean("permissions.abilities")
|
if (MMOItems.plugin.getConfig().getBoolean("permissions.abilities") && !player.hasPermission("mmoitems.ability." + getHandler().getLowerCaseId()) && !player.hasPermission("mmoitems.bypass.ability"))
|
||||||
&& !player.hasPermission("mmoitems.ability." + getHandler().getLowerCaseId())
|
return false;
|
||||||
&& !player.hasPermission("mmoitems.bypass.ability"))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Check for mana cost
|
// Check for mana cost
|
||||||
if (hasModifier("mana") && rpgPlayer.getMana() < getModifier("mana")) {
|
if (hasModifier("mana") && rpgPlayer.getMana() < getModifier("mana")) {
|
||||||
Message.NOT_ENOUGH_MANA.format(ChatColor.RED).send(player);
|
Message.NOT_ENOUGH_MANA.format(ChatColor.RED).send(player);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for stamina cost
|
// Check for stamina cost
|
||||||
if (hasModifier("stamina") && rpgPlayer.getStamina() < getModifier("stamina")) {
|
if (hasModifier("stamina") && rpgPlayer.getStamina() < getModifier("stamina")) {
|
||||||
Message.NOT_ENOUGH_STAMINA.format(ChatColor.RED).send(player);
|
Message.NOT_ENOUGH_STAMINA.format(ChatColor.RED).send(player);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void whenCast(SkillMetadata meta) {
|
public void whenCast(SkillMetadata meta) {
|
||||||
PlayerData playerData = PlayerData.get(meta.getCaster().getData().getUniqueId());
|
PlayerData playerData = PlayerData.get(meta.getCaster().getData().getUniqueId());
|
||||||
RPGPlayer rpgPlayer = playerData.getRPG();
|
RPGPlayer rpgPlayer = playerData.getRPG();
|
||||||
|
|
||||||
// Apply mana cost
|
// Apply mana cost
|
||||||
if (hasModifier("mana"))
|
if (hasModifier("mana")) rpgPlayer.giveMana(-meta.getModifier("mana"));
|
||||||
rpgPlayer.giveMana(-meta.getModifier("mana"));
|
|
||||||
|
|
||||||
// Apply stamina cost
|
// Apply stamina cost
|
||||||
if (hasModifier("stamina"))
|
if (hasModifier("stamina")) rpgPlayer.giveStamina(-meta.getModifier("stamina"));
|
||||||
rpgPlayer.giveStamina(-meta.getModifier("stamina"));
|
|
||||||
|
|
||||||
// Apply cooldown
|
// Apply cooldown
|
||||||
double cooldown = meta.getModifier("cooldown") * (1 - Math.min(.8, meta.getCaster().getStat("COOLDOWN_REDUCTION") / 100));
|
double cooldown = meta.getModifier("cooldown") * (1 - Math.min(.8, meta.getCaster().getStat("COOLDOWN_REDUCTION") / 100));
|
||||||
if (cooldown > 0)
|
if (cooldown > 0) meta.getCaster().getData().getCooldownMap().applyCooldown(this, cooldown);
|
||||||
meta.getCaster().getData().getCooldownMap().applyCooldown(this, cooldown);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SkillHandler getHandler() {
|
public SkillHandler getHandler() {
|
||||||
return ability.getHandler();
|
return ability.getHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double getModifier(String path) {
|
public double getModifier(String path) {
|
||||||
return modifiers.getOrDefault(path, ability.getDefaultModifier(path));
|
return modifiers.getOrDefault(path, ability.getDefaultModifier(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
public JsonObject toJson() {
|
public JsonObject toJson() {
|
||||||
JsonObject object = new JsonObject();
|
JsonObject object = new JsonObject();
|
||||||
object.addProperty("Id", ability.getHandler().getId());
|
object.addProperty("Id", ability.getHandler().getId());
|
||||||
object.addProperty("CastMode", getTrigger().name());
|
object.addProperty("CastMode", getTrigger().name());
|
||||||
|
|
||||||
JsonObject modifiers = new JsonObject();
|
JsonObject modifiers = new JsonObject();
|
||||||
this.modifiers.keySet().forEach(modifier -> modifiers.addProperty(modifier, getModifier(modifier)));
|
this.modifiers.keySet().forEach(modifier -> modifiers.addProperty(modifier, getModifier(modifier)));
|
||||||
object.add("Modifiers", modifiers);
|
object.add("Modifiers", modifiers);
|
||||||
|
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
AbilityData that = (AbilityData) o;
|
AbilityData that = (AbilityData) o;
|
||||||
return ability.equals(that.ability) && getTrigger().equals(that.getTrigger()) && modifiers.equals(that.modifiers);
|
return ability.equals(that.ability) && getTrigger().equals(that.getTrigger()) && modifiers.equals(that.modifiers);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(ability, modifiers);
|
return Objects.hash(ability, modifiers);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -72,6 +72,11 @@ public class ArrowParticlesData implements StatData, RandomStatData<ArrowParticl
|
|||||||
return blue;
|
return blue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
JsonObject object = new JsonObject();
|
JsonObject object = new JsonObject();
|
||||||
|
@ -45,6 +45,11 @@ public class ColorData implements StatData, RandomStatData<ColorData> {
|
|||||||
return Color.fromRGB(red, green, blue);
|
return Color.fromRGB(red, green, blue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "{Red=" + red + ",Green=" + green + ",Blue=" + blue + "}";
|
return "{Red=" + red + ",Green=" + green + ",Blue=" + blue + "}";
|
||||||
|
@ -11,53 +11,55 @@ import net.Indyuce.mmoitems.stat.data.type.StatData;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public class CommandListData implements StatData, Mergeable, RandomStatData<CommandListData> {
|
public class CommandListData implements StatData, Mergeable, RandomStatData<CommandListData> {
|
||||||
@NotNull private final List<CommandData> commands;
|
@NotNull
|
||||||
|
private final List<CommandData> commands;
|
||||||
|
|
||||||
public CommandListData(@NotNull List<CommandData> commands) {
|
public CommandListData(@NotNull List<CommandData> commands) {
|
||||||
this.commands = commands;
|
this.commands = commands;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommandListData(CommandData... commands) {
|
public CommandListData(CommandData... commands) {
|
||||||
this(new ArrayList<>());
|
this(new ArrayList<>());
|
||||||
|
|
||||||
add(commands);
|
add(commands);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add(CommandData... commands) {
|
public void add(CommandData... commands) {
|
||||||
for (CommandData data : commands)
|
for (CommandData data : commands)
|
||||||
this.commands.add(data);
|
this.commands.add(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull public List<CommandData> getCommands() {
|
@NotNull
|
||||||
return commands;
|
public List<CommandData> getCommands() {
|
||||||
}
|
return commands;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
CommandListData that = (CommandListData) o;
|
CommandListData that = (CommandListData) o;
|
||||||
return commands.equals(that.commands);
|
return commands.equals(that.commands);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void merge(StatData data) {
|
public void merge(StatData data) {
|
||||||
Validate.isTrue(data instanceof CommandListData, "Cannot merge two different stat data types");
|
Validate.isTrue(data instanceof CommandListData, "Cannot merge two different stat data types");
|
||||||
commands.addAll(((CommandListData) data).commands);
|
commands.addAll(((CommandListData) data).commands);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull StatData cloneData() {
|
public @NotNull StatData cloneData() {
|
||||||
return new CommandListData(commands);
|
return new CommandListData(commands);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
return commands.isEmpty();
|
return commands.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommandListData randomize(MMOItemBuilder builder) {
|
public CommandListData randomize(MMOItemBuilder builder) {
|
||||||
return new CommandListData(new ArrayList<>(commands));
|
return new CommandListData(new ArrayList<>(commands));
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -129,8 +129,8 @@ public class GemSocketsData implements StatData, Mergeable<GemSocketsData>, Rand
|
|||||||
public void merge(GemSocketsData data) {
|
public void merge(GemSocketsData data) {
|
||||||
|
|
||||||
// Combine both actual gems, and empty slots
|
// Combine both actual gems, and empty slots
|
||||||
emptySlots.addAll(((GemSocketsData) data).emptySlots);
|
emptySlots.addAll(data.emptySlots);
|
||||||
gems.addAll(((GemSocketsData) data).getGemstones());
|
gems.addAll(data.gems);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -28,6 +28,11 @@ public class MaterialData implements StatData, RandomStatData<MaterialData> {
|
|||||||
return material;
|
return material;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MaterialData randomize(MMOItemBuilder builder) {
|
public MaterialData randomize(MMOItemBuilder builder) {
|
||||||
return this;
|
return this;
|
||||||
|
@ -4,6 +4,7 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import net.Indyuce.mmoitems.util.MMOUtils;
|
||||||
import org.apache.commons.lang.Validate;
|
import org.apache.commons.lang.Validate;
|
||||||
import org.bukkit.Color;
|
import org.bukkit.Color;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
@ -119,7 +120,7 @@ public class ParticleData implements StatData, RandomStatData<ParticleData> {
|
|||||||
object.addProperty("Particle", getParticle().name());
|
object.addProperty("Particle", getParticle().name());
|
||||||
object.addProperty("Type", getType().name());
|
object.addProperty("Type", getType().name());
|
||||||
|
|
||||||
if (isColorable(particle)) {
|
if (MMOUtils.isColorable(particle)) {
|
||||||
JsonObject color = new JsonObject();
|
JsonObject color = new JsonObject();
|
||||||
color.addProperty("Red", getColor().getRed());
|
color.addProperty("Red", getColor().getRed());
|
||||||
color.addProperty("Green", getColor().getGreen());
|
color.addProperty("Green", getColor().getGreen());
|
||||||
@ -133,11 +134,10 @@ public class ParticleData implements StatData, RandomStatData<ParticleData> {
|
|||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Allow Note to be colored and allow BLOCK_DUST/ITEM_DUST to pick a block/item.
|
@Override
|
||||||
public static boolean isColorable(Particle particle) {
|
public boolean isEmpty() {
|
||||||
// || particle == Particle.NOTE
|
return false;
|
||||||
return particle == Particle.REDSTONE || particle == Particle.SPELL_MOB || particle == Particle.SPELL_MOB_AMBIENT;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ParticleData randomize(MMOItemBuilder builder) {
|
public ParticleData randomize(MMOItemBuilder builder) {
|
||||||
|
@ -2,13 +2,10 @@ package net.Indyuce.mmoitems.stat.data;
|
|||||||
|
|
||||||
import io.lumine.mythic.lib.api.item.ItemTag;
|
import io.lumine.mythic.lib.api.item.ItemTag;
|
||||||
import io.lumine.mythic.lib.api.item.NBTItem;
|
import io.lumine.mythic.lib.api.item.NBTItem;
|
||||||
import net.Indyuce.mmoitems.api.interaction.ItemSkin;
|
|
||||||
import net.Indyuce.mmoitems.api.item.build.ItemStackBuilder;
|
import net.Indyuce.mmoitems.api.item.build.ItemStackBuilder;
|
||||||
import net.Indyuce.mmoitems.stat.data.type.Mergeable;
|
import net.Indyuce.mmoitems.stat.data.type.Mergeable;
|
||||||
import net.Indyuce.mmoitems.stat.data.type.StatData;
|
import net.Indyuce.mmoitems.stat.data.type.StatData;
|
||||||
import org.apache.commons.lang.Validate;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -17,50 +14,33 @@ import java.util.List;
|
|||||||
public class StoredTagsData implements StatData, Mergeable<StoredTagsData> {
|
public class StoredTagsData implements StatData, Mergeable<StoredTagsData> {
|
||||||
private final List<ItemTag> tags = new ArrayList<>();
|
private final List<ItemTag> tags = new ArrayList<>();
|
||||||
|
|
||||||
private static final List<String> ignoreList = Arrays.asList("Unbreakable", "BlockEntityTag", "display", "Enchantments", "HideFlags", "Damage",
|
private static final List<String> IGNORED_TAGS = Arrays.asList(
|
||||||
|
"Unbreakable", "BlockEntityTag", "display", "Enchantments", "HideFlags", "Damage",
|
||||||
"AttributeModifiers", "SkullOwner", "CanDestroy", "PickupDelay", "Age");
|
"AttributeModifiers", "SkullOwner", "CanDestroy", "PickupDelay", "Age");
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
private static final List<String> SAVED_MMOITEMS_TAGS = Arrays.asList(
|
||||||
|
"MMOITEMS_SKIN_ID");
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public StoredTagsData(ItemStack stack) {
|
public StoredTagsData(ItemStack stack) {
|
||||||
this(NBTItem.get(stack));
|
this(NBTItem.get(stack));
|
||||||
}
|
}
|
||||||
|
|
||||||
public StoredTagsData(List<ItemTag> tgs) { tags.addAll(tgs); }
|
public StoredTagsData(List<ItemTag> tgs) { tags.addAll(tgs); }
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (!(obj instanceof StoredTagsData)) { return false; }
|
|
||||||
|
|
||||||
if (((StoredTagsData) obj).getTags().size() != getTags().size()) { return false; }
|
|
||||||
|
|
||||||
for (ItemTag tag : ((StoredTagsData) obj).getTags()) {
|
|
||||||
|
|
||||||
if (tag == null) { continue; }
|
|
||||||
|
|
||||||
boolean unmatched = true;
|
|
||||||
for (ItemTag tg : getTags()) {
|
|
||||||
if (tag.equals(tg)) { unmatched = false; break; } }
|
|
||||||
if (unmatched) { return false; } }
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StoredTagsData(NBTItem nbt) {
|
public StoredTagsData(NBTItem nbt) {
|
||||||
for (String tag : nbt.getTags()) {
|
for (String tag : nbt.getTags()) {
|
||||||
|
|
||||||
// Usually ignore mmoitems
|
// Usually ignore mmoitems
|
||||||
if (tag.startsWith("MMOITEMS_")) {
|
if (tag.startsWith("MMOITEMS_") && !SAVED_MMOITEMS_TAGS.contains(tag))
|
||||||
|
|
||||||
// Do not delete the skin tags (save them here)
|
// Must be handled by its respective stat.
|
||||||
if (!ItemSkin.HAS_SKIN_TAG.equals(tag) && !ItemSkin.SKIN_ID_TAG.equals(tag)) {
|
continue;
|
||||||
|
|
||||||
// Not either of the skin tags, skip this.
|
|
||||||
// Must be handled by its respective stat.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Any vanilla or MMOItem tag should be ignored as those are
|
// Any vanilla or MMOItem tag should be ignored as those are
|
||||||
// automatically handled. Same for the History stat ones.
|
// automatically handled. Same for the History stat ones.
|
||||||
if (ignoreList.contains(tag) || tag.startsWith(ItemStackBuilder.history_keyword))
|
if (IGNORED_TAGS.contains(tag) || tag.startsWith(ItemStackBuilder.history_keyword))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// As more methods are added we can add more types here
|
// As more methods are added we can add more types here
|
||||||
@ -134,4 +114,21 @@ public class StoredTagsData implements StatData, Mergeable<StoredTagsData> {
|
|||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
return tags.isEmpty();
|
return tags.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (!(obj instanceof StoredTagsData)) { return false; }
|
||||||
|
|
||||||
|
if (((StoredTagsData) obj).getTags().size() != getTags().size()) { return false; }
|
||||||
|
|
||||||
|
for (ItemTag tag : ((StoredTagsData) obj).getTags()) {
|
||||||
|
|
||||||
|
if (tag == null) { continue; }
|
||||||
|
|
||||||
|
boolean unmatched = true;
|
||||||
|
for (ItemTag tg : getTags()) {
|
||||||
|
if (tag.equals(tg)) { unmatched = false; break; } }
|
||||||
|
if (unmatched) { return false; } }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
@ -5,7 +5,6 @@ import java.util.Arrays;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import io.lumine.mythic.lib.api.util.ui.SilentNumbers;
|
import io.lumine.mythic.lib.api.util.ui.SilentNumbers;
|
||||||
import org.apache.commons.lang.Validate;
|
|
||||||
|
|
||||||
import com.google.gson.JsonArray;
|
import com.google.gson.JsonArray;
|
||||||
|
|
||||||
@ -13,12 +12,11 @@ import net.Indyuce.mmoitems.api.item.build.MMOItemBuilder;
|
|||||||
import net.Indyuce.mmoitems.stat.data.random.RandomStatData;
|
import net.Indyuce.mmoitems.stat.data.random.RandomStatData;
|
||||||
import net.Indyuce.mmoitems.stat.data.type.Mergeable;
|
import net.Indyuce.mmoitems.stat.data.type.Mergeable;
|
||||||
import net.Indyuce.mmoitems.stat.data.type.StatData;
|
import net.Indyuce.mmoitems.stat.data.type.StatData;
|
||||||
import org.bouncycastle.util.StringList;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
public class StringListData implements StatData, RandomStatData<StringListData>, Mergeable<StringListData> {
|
public class StringListData implements StatData, RandomStatData<StringListData>, Mergeable<StringListData> {
|
||||||
@NotNull private List<String> list;
|
@NotNull private final List<String> list;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
@ -80,34 +78,12 @@ public class StringListData implements StatData, RandomStatData<StringListData>,
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param str Entry to remove
|
* @param str Entry to remove
|
||||||
*
|
|
||||||
* @return If the value was actually removed. If it wasn't there
|
* @return If the value was actually removed. If it wasn't there
|
||||||
* in the first place, this will return false.
|
* in the first place, this will return false.
|
||||||
*
|
|
||||||
* @deprecated Deprecated
|
* @deprecated Deprecated
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public boolean remove(@Nullable String str) {
|
public boolean remove(@Nullable String str) {
|
||||||
|
return list.remove(str);
|
||||||
if (!list.contains(str)) { return false; }
|
|
||||||
|
|
||||||
if (removeGuarantee) {
|
|
||||||
|
|
||||||
// Remove that sh
|
|
||||||
return list.remove(str);
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// OK
|
|
||||||
try {
|
|
||||||
return list.remove(str);
|
|
||||||
|
|
||||||
} catch (UnsupportedOperationException ignored) {
|
|
||||||
|
|
||||||
list = new ArrayList<>(list);
|
|
||||||
removeGuarantee = true;
|
|
||||||
return list.remove(str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
boolean removeGuarantee = false;
|
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ import java.util.LinkedHashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class RandomElementListData implements RandomStatData<ElementListData>, UpdatableRandomStatData {
|
public class RandomElementListData implements RandomStatData<ElementListData>, UpdatableRandomStatData<ElementListData> {
|
||||||
private final Map<Pair<Element, ElementStatType>, NumericStatFormula> stats = new LinkedHashMap<>();
|
private final Map<Pair<Element, ElementStatType>, NumericStatFormula> stats = new LinkedHashMap<>();
|
||||||
|
|
||||||
public RandomElementListData(ConfigurationSection config) {
|
public RandomElementListData(ConfigurationSection config) {
|
||||||
@ -58,7 +58,7 @@ public class RandomElementListData implements RandomStatData<ElementListData>, U
|
|||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <T extends StatData> T reroll(@NotNull ItemStat stat, @NotNull T original, int determinedItemLevel) {
|
public ElementListData reroll(@NotNull ItemStat stat, @NotNull ElementListData original, int determinedItemLevel) {
|
||||||
|
|
||||||
// Start brand new
|
// Start brand new
|
||||||
ElementListData elements = new ElementListData();
|
ElementListData elements = new ElementListData();
|
||||||
@ -80,6 +80,6 @@ public class RandomElementListData implements RandomStatData<ElementListData>, U
|
|||||||
}
|
}
|
||||||
|
|
||||||
// THats it
|
// THats it
|
||||||
return (T) elements;
|
return elements;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -10,33 +10,30 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
* looking into Random Stat Data, because one wouldn't want to reroll a good
|
* looking into Random Stat Data, because one wouldn't want to reroll a good
|
||||||
* roll in a player's item... unless this roll was unobtainable now, perhaps
|
* roll in a player's item... unless this roll was unobtainable now, perhaps
|
||||||
* the reason the item is getting updated is to fix that roll being too good...
|
* the reason the item is getting updated is to fix that roll being too good...
|
||||||
*
|
* <p>
|
||||||
* Example of unobtainable data: the current numeric stat value is now out
|
* Example of unobtainable data: the current numeric stat value is now out
|
||||||
* of the numeric formula bounds (defined by max-spread).
|
* of the numeric formula bounds (defined by max-spread).
|
||||||
*
|
* <p>
|
||||||
* This interface will tell the {@link net.Indyuce.mmoitems.api.util.MMOItemReforger}
|
* This interface will tell the {@link net.Indyuce.mmoitems.api.util.MMOItemReforger}
|
||||||
* if the current roll may be kept, or it is too extreme (under the updated metrics)
|
* if the current roll may be kept, or it is too extreme (under the updated metrics)
|
||||||
* to be considered 'obtainable' and thus must be removed.
|
* to be considered 'obtainable' and thus must be removed.
|
||||||
*
|
* <p>
|
||||||
* If a RandomStatData does not implement this, it will never be kept when
|
* If a RandomStatData does not implement this, it will never be kept when
|
||||||
* updating items (always be rerolled with latest settings).
|
* updating items (always be rerolled with latest settings).
|
||||||
*
|
*
|
||||||
* @author Gunging
|
* @author Gunging
|
||||||
*/
|
*/
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface UpdatableRandomStatData {
|
public interface UpdatableRandomStatData<S extends StatData> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @param stat In case its relevant, the stat this Stat Data is linked to
|
||||||
* @param stat In case its relevant, the stat this Stat Data is linked to
|
* @param original The StatData currently in the item being reforged.
|
||||||
*
|
|
||||||
* @param original The StatData currently in the item being reforged.
|
|
||||||
*
|
|
||||||
* @param determinedItemLevel The level of the item
|
* @param determinedItemLevel The level of the item
|
||||||
*
|
|
||||||
* @return The rerolled StatData if the original is unreasonable.
|
* @return The rerolled StatData if the original is unreasonable.
|
||||||
* <br><br>
|
* <br><br>
|
||||||
* If the original is reasonable, a clone of it, probably using {@link Mergeable#cloneData()}
|
* If the original is reasonable, a clone of it, probably using {@link Mergeable#cloneData()}
|
||||||
*/
|
*/
|
||||||
@NotNull <T extends StatData> T reroll(@NotNull ItemStat stat, @NotNull T original, int determinedItemLevel);
|
@NotNull
|
||||||
|
S reroll(@NotNull ItemStat stat, @NotNull S original, int determinedItemLevel);
|
||||||
}
|
}
|
||||||
|
@ -11,10 +11,7 @@ import io.lumine.mythic.lib.skill.trigger.TriggerType;
|
|||||||
import net.Indyuce.mmoitems.MMOItems;
|
import net.Indyuce.mmoitems.MMOItems;
|
||||||
import net.Indyuce.mmoitems.api.Type;
|
import net.Indyuce.mmoitems.api.Type;
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
import org.bukkit.ChatColor;
|
import org.bukkit.*;
|
||||||
import org.bukkit.Color;
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.attribute.Attribute;
|
import org.bukkit.attribute.Attribute;
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.entity.LivingEntity;
|
import org.bukkit.entity.LivingEntity;
|
||||||
@ -33,11 +30,33 @@ import java.util.*;
|
|||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class MMOUtils {
|
public class MMOUtils {
|
||||||
|
|
||||||
public MMOUtils() {
|
public MMOUtils() {
|
||||||
throw new IllegalArgumentException("This class cannot be instantiated.");
|
throw new IllegalArgumentException("This class cannot be instantiated.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isColorable(Particle particle) {
|
||||||
|
return particle.getDataType() == Particle.DustOptions.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should cancel interaction if one of the two cases:
|
||||||
|
* - the item type no longer exists
|
||||||
|
* - no template with the given (type, id) pair can be found
|
||||||
|
*
|
||||||
|
* @param item Target item
|
||||||
|
* @return If the item USED to exist, but no longer does
|
||||||
|
*/
|
||||||
|
public static boolean hasBeenRemoved(@NotNull NBTItem item) {
|
||||||
|
if (!item.hasType()) return false;
|
||||||
|
|
||||||
|
final @Nullable String type = item.getType();
|
||||||
|
return MMOUtils.isNonEmpty(type) && (!Type.isValid(type) || !MMOItems.plugin.getTemplates().hasTemplate(Type.get(type), item.getString("MMOITEMS_ITEM_ID")));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isNonEmpty(@Nullable String str) {
|
||||||
|
return str != null && !str.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The skull texture URL from a given player head
|
* @return The skull texture URL from a given player head
|
||||||
*/
|
*/
|
||||||
|
@ -28,7 +28,8 @@ public class MMOItemsBukkit {
|
|||||||
|
|
||||||
if (plugin.getConfig().getBoolean("dropped-items.tier-glow") || plugin.getConfig().getBoolean("dropped-items.hints"))
|
if (plugin.getConfig().getBoolean("dropped-items.tier-glow") || plugin.getConfig().getBoolean("dropped-items.hints"))
|
||||||
Bukkit.getPluginManager().registerEvents(new DroppedItems(plugin.getConfig().getConfigurationSection("dropped-items")), plugin);
|
Bukkit.getPluginManager().registerEvents(new DroppedItems(plugin.getConfig().getConfigurationSection("dropped-items")), plugin);
|
||||||
Bukkit.getPluginManager().registerEvents(new DisabledItemsListener(plugin), plugin);
|
if (plugin.getLanguage().disableRemovedItems)
|
||||||
|
Bukkit.getPluginManager().registerEvents(new DisabledItemsListener(plugin), plugin);
|
||||||
|
|
||||||
Bukkit.getScheduler().runTaskTimer(plugin, () -> Bukkit.getOnlinePlayers().forEach(player -> PlayerData.get(player).updateStats()), 100, 20);
|
Bukkit.getScheduler().runTaskTimer(plugin, () -> Bukkit.getOnlinePlayers().forEach(player -> PlayerData.get(player).updateStats()), 100, 20);
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import io.lumine.mythic.lib.api.item.NBTItem;
|
|||||||
import io.lumine.mythic.lib.damage.MeleeAttackMetadata;
|
import io.lumine.mythic.lib.damage.MeleeAttackMetadata;
|
||||||
import net.Indyuce.mmoitems.MMOItems;
|
import net.Indyuce.mmoitems.MMOItems;
|
||||||
import net.Indyuce.mmoitems.api.Type;
|
import net.Indyuce.mmoitems.api.Type;
|
||||||
|
import net.Indyuce.mmoitems.util.MMOUtils;
|
||||||
import org.bukkit.GameMode;
|
import org.bukkit.GameMode;
|
||||||
import org.bukkit.entity.Arrow;
|
import org.bukkit.entity.Arrow;
|
||||||
import org.bukkit.entity.LivingEntity;
|
import org.bukkit.entity.LivingEntity;
|
||||||
@ -21,6 +22,8 @@ import org.bukkit.event.player.PlayerInteractEntityEvent;
|
|||||||
import org.bukkit.event.player.PlayerInteractEvent;
|
import org.bukkit.event.player.PlayerInteractEvent;
|
||||||
import org.bukkit.event.player.PlayerItemConsumeEvent;
|
import org.bukkit.event.player.PlayerItemConsumeEvent;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* mmoitems
|
* mmoitems
|
||||||
@ -41,7 +44,7 @@ public class DisabledItemsListener implements Listener {
|
|||||||
if (!event.hasItem())
|
if (!event.hasItem())
|
||||||
return;
|
return;
|
||||||
NBTItem item = MythicLib.plugin.getVersion().getWrapper().getNBTItem(event.getItem());
|
NBTItem item = MythicLib.plugin.getVersion().getWrapper().getNBTItem(event.getItem());
|
||||||
if (this.shouldCancel(item))
|
if (MMOUtils.hasBeenRemoved(item))
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,7 +54,7 @@ public class DisabledItemsListener implements Listener {
|
|||||||
return;
|
return;
|
||||||
ItemStack weaponUsed = event.getPlayer().getInventory().getItem(((MeleeAttackMetadata) event.getAttack()).getHand().toBukkit());
|
ItemStack weaponUsed = event.getPlayer().getInventory().getItem(((MeleeAttackMetadata) event.getAttack()).getHand().toBukkit());
|
||||||
NBTItem item = MythicLib.plugin.getVersion().getWrapper().getNBTItem(weaponUsed);
|
NBTItem item = MythicLib.plugin.getVersion().getWrapper().getNBTItem(weaponUsed);
|
||||||
if (this.shouldCancel(item))
|
if (MMOUtils.hasBeenRemoved(item))
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,7 +65,7 @@ public class DisabledItemsListener implements Listener {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
final NBTItem item = MythicLib.plugin.getVersion().getWrapper().getNBTItem(player.getInventory().getItemInMainHand());
|
final NBTItem item = MythicLib.plugin.getVersion().getWrapper().getNBTItem(player.getInventory().getItemInMainHand());
|
||||||
if (this.shouldCancel(item))
|
if (MMOUtils.hasBeenRemoved(item))
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,7 +76,7 @@ public class DisabledItemsListener implements Listener {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
NBTItem item = MythicLib.plugin.getVersion().getWrapper().getNBTItem(player.getInventory().getItemInMainHand());
|
NBTItem item = MythicLib.plugin.getVersion().getWrapper().getNBTItem(player.getInventory().getItemInMainHand());
|
||||||
if (this.shouldCancel(item))
|
if (MMOUtils.hasBeenRemoved(item))
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +87,7 @@ public class DisabledItemsListener implements Listener {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
NBTItem item = MythicLib.plugin.getVersion().getWrapper().getNBTItem(event.getCursor());
|
NBTItem item = MythicLib.plugin.getVersion().getWrapper().getNBTItem(event.getCursor());
|
||||||
if (this.shouldCancel(item))
|
if (MMOUtils.hasBeenRemoved(item))
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,21 +97,14 @@ public class DisabledItemsListener implements Listener {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
final NBTItem item = NBTItem.get(event.getBow());
|
final NBTItem item = NBTItem.get(event.getBow());
|
||||||
if (shouldCancel(item))
|
if (MMOUtils.hasBeenRemoved(item))
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.LOWEST)
|
@EventHandler(priority = EventPriority.LOWEST)
|
||||||
public void handleVanillaEatenConsumables(PlayerItemConsumeEvent event) {
|
public void handleVanillaEatenConsumables(PlayerItemConsumeEvent event) {
|
||||||
NBTItem item = MythicLib.plugin.getVersion().getWrapper().getNBTItem(event.getItem());
|
NBTItem item = MythicLib.plugin.getVersion().getWrapper().getNBTItem(event.getItem());
|
||||||
if (shouldCancel(item))
|
if (MMOUtils.hasBeenRemoved(item))
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean shouldCancel(NBTItem item) {
|
|
||||||
if (!item.hasType() || !plugin.getConfig().getBoolean("disable-removed-items", true))
|
|
||||||
return false;
|
|
||||||
return !Type.isValid(item.getType());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -98,9 +98,10 @@ public class PlayerListener implements Listener {
|
|||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onArmorEquip(ArmorEquipEvent event) {
|
public void onArmorEquip(ArmorEquipEvent event) {
|
||||||
Player player = event.getPlayer();
|
if (event.getNewArmorPiece() == null)
|
||||||
NBTItem item = NBTItem.get(event.getNewArmorPiece());
|
return;
|
||||||
if (!PlayerData.get(player).getRPG().canUse(item, true))
|
|
||||||
|
if (!PlayerData.get(event.getPlayer()).getRPG().canUse(NBTItem.get(event.getNewArmorPiece()), true))
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,13 +3,15 @@ package net.Indyuce.mmoitems.listener.reforging;
|
|||||||
import io.lumine.mythic.lib.api.item.NBTItem;
|
import io.lumine.mythic.lib.api.item.NBTItem;
|
||||||
import net.Indyuce.mmoitems.api.event.MMOItemReforgeFinishEvent;
|
import net.Indyuce.mmoitems.api.event.MMOItemReforgeFinishEvent;
|
||||||
import net.Indyuce.mmoitems.api.interaction.ItemSkin;
|
import net.Indyuce.mmoitems.api.interaction.ItemSkin;
|
||||||
|
import net.Indyuce.mmoitems.api.item.mmoitem.VolatileMMOItem;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transfers the lore from the old MMOItem to the new one.
|
* Transfers the lore from the old MMOItem to the new one.
|
||||||
*
|
* <p>
|
||||||
* This operation is intended to allow refreshing the lore,
|
* This operation is intended to allow refreshing the lore,
|
||||||
* but keeping external things too.
|
* but keeping external things too.
|
||||||
*
|
*
|
||||||
@ -19,22 +21,15 @@ public class RFFKeepSkins implements Listener {
|
|||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onReforge(MMOItemReforgeFinishEvent event) {
|
public void onReforge(MMOItemReforgeFinishEvent event) {
|
||||||
if (!event.getOptions().shouldKeepSkins()) { return; }
|
if (!event.getOptions().shouldKeepSkins()) return;
|
||||||
//RFG// MMOItems.log("§8Reforge §4EFG§7 Keeping Skins");
|
//RFG// MMOItems.log("§8Reforge §4EFG§7 Keeping Skins");
|
||||||
|
|
||||||
// Got skin?
|
|
||||||
if (!event.getReforger().getNBTItem().getBoolean(ItemSkin.HAS_SKIN_TAG)) { return; }
|
|
||||||
//RFG// MMOItems.log("§8Reforge §4EFG§7 Item has skin");
|
|
||||||
|
|
||||||
// Apply skin to result
|
// Apply skin to result
|
||||||
NBTItem resultAsNBT = NBTItem.get(event.getFinishedItem());
|
final @Nullable String tagValue = event.getReforger().getNBTItem().getString(ItemSkin.SKIN_ID_TAG);
|
||||||
|
if (tagValue != null && !tagValue.isEmpty()) {
|
||||||
// Apply skin
|
NBTItem resultAsNBT = NBTItem.get(event.getFinishedItem());
|
||||||
ItemStack ret = ItemSkin.applySkin(resultAsNBT, event.getReforger().getNBTItem());
|
ItemStack ret = ItemSkin.applySkin(resultAsNBT, new VolatileMMOItem(event.getReforger().getNBTItem()));
|
||||||
|
event.setFinishedItem(ret);
|
||||||
// Success?
|
}
|
||||||
if (ret != null) {
|
|
||||||
//RFG// MMOItems.log("§8Reforge §4EFG§7 Success");
|
|
||||||
event.setFinishedItem(ret); }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,12 @@
|
|||||||
package net.Indyuce.mmoitems.listener.reforging;
|
package net.Indyuce.mmoitems.listener.reforging;
|
||||||
|
|
||||||
import net.Indyuce.mmoitems.ItemStats;
|
|
||||||
import net.Indyuce.mmoitems.api.event.MMOItemReforgeEvent;
|
import net.Indyuce.mmoitems.api.event.MMOItemReforgeEvent;
|
||||||
import net.Indyuce.mmoitems.stat.data.random.RandomStatData;
|
import net.Indyuce.mmoitems.stat.data.random.RandomStatData;
|
||||||
import net.Indyuce.mmoitems.stat.data.random.UpdatableRandomStatData;
|
import net.Indyuce.mmoitems.stat.data.random.UpdatableRandomStatData;
|
||||||
import net.Indyuce.mmoitems.stat.data.type.Mergeable;
|
|
||||||
import net.Indyuce.mmoitems.stat.data.type.StatData;
|
import net.Indyuce.mmoitems.stat.data.type.StatData;
|
||||||
import net.Indyuce.mmoitems.stat.type.ItemStat;
|
|
||||||
import net.Indyuce.mmoitems.stat.type.StatHistory;
|
import net.Indyuce.mmoitems.stat.type.StatHistory;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prevent previous RNG rolls of base stats
|
* Prevent previous RNG rolls of base stats
|
||||||
@ -21,64 +16,9 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
*/
|
*/
|
||||||
public class RFGKeepRNG implements Listener {
|
public class RFGKeepRNG implements Listener {
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onReforge(MMOItemReforgeEvent event) {
|
|
||||||
// Rerolling stats? Nevermind
|
|
||||||
if (event.getOptions().shouldReRoll()) {
|
|
||||||
// event.setCancelled(true);
|
|
||||||
//RFG// MMOItems.log("§8Reforge §4EFG§7 Keeping new item (Complete RNG Reroll)");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//RFG// MMOItems.log("§8Reforge §4EFG§7 Keeping old RNG Rolls");
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Proceed to go through all stats
|
|
||||||
*/
|
|
||||||
event.getOldMMOItem()
|
|
||||||
.getStats()
|
|
||||||
.stream()
|
|
||||||
// Skip if it cant merge
|
|
||||||
.filter(stat -> stat.getClearStatData() instanceof Mergeable)
|
|
||||||
/*
|
|
||||||
* These stats are exempt from this 'keeping' operation.
|
|
||||||
* Probably because there is a ReforgeOption specifically
|
|
||||||
* designed for them that keeps them separately
|
|
||||||
*/
|
|
||||||
.filter(stat -> !(ItemStats.LORE.equals(stat) ||
|
|
||||||
ItemStats.NAME.equals(stat) ||
|
|
||||||
ItemStats.UPGRADE.equals(stat) ||
|
|
||||||
ItemStats.ENCHANTS.equals(stat) ||
|
|
||||||
ItemStats.SOULBOUND.equals(stat) ||
|
|
||||||
ItemStats.GEM_SOCKETS.equals(stat)))
|
|
||||||
.forEach(stat -> {
|
|
||||||
// Stat history in the old item
|
|
||||||
StatHistory hist = StatHistory.from(event.getOldMMOItem(), stat);
|
|
||||||
|
|
||||||
// Alr what the template say, this roll too rare to be kept?
|
|
||||||
RandomStatData source = event.getReforger().getTemplate().getBaseItemData().get(stat);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Decide if this data is too far from RNG to
|
|
||||||
* preserve its rolls, even if it should be
|
|
||||||
* preserving the rolls.
|
|
||||||
*/
|
|
||||||
StatData keptData = shouldReRollRegardless(stat, source, hist.getOriginalData(), event.getReforger().getGenerationItemLevel());
|
|
||||||
|
|
||||||
// Old roll is ridiculously low probability under the new parameters. Forget.
|
|
||||||
if (keptData == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Fetch History from the new item
|
|
||||||
StatHistory clear = StatHistory.from(event.getNewMMOItem(), stat);
|
|
||||||
|
|
||||||
// Replace original data of the new one with the roll from the old one
|
|
||||||
clear.setOriginalData(keptData);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The item is supposedly being updated, but that doesnt mean all its stats must remain the same.
|
* The item is supposedly being updated, but that doesnt mean all its stats must remain the same.
|
||||||
* <p>
|
* <p>
|
||||||
* In contrast to reforging, in which it is expected its RNG to be rerolled, updating should not do it
|
* In contrast to reforging, in which it is expected its RNG to be rerolled, updating should not do it
|
||||||
* except in the most dire scenarios:
|
* except in the most dire scenarios:
|
||||||
@ -91,14 +31,41 @@ public class RFGKeepRNG implements Listener {
|
|||||||
* + There is a new stat: The original data is null so this method cannot be called, will roll the
|
* + There is a new stat: The original data is null so this method cannot be called, will roll the
|
||||||
* new stat to actually add it for the first time.
|
* new stat to actually add it for the first time.
|
||||||
*/
|
*/
|
||||||
@Nullable StatData shouldReRollRegardless(@NotNull ItemStat stat, @NotNull RandomStatData source, @NotNull StatData original, int determinedItemLevel) {
|
@EventHandler
|
||||||
// Not Mergeable, impossible to keep
|
public void onReforge(MMOItemReforgeEvent event) {
|
||||||
if (!(source instanceof UpdatableRandomStatData))
|
// Rerolling stats? Nevermind
|
||||||
//RFG// MMOItems.log("§8Reforge §3RNG§7 Stat\u00a7f " + stat.getId() + "\u00a77 is not updatable!");
|
if (event.getOptions().shouldReRoll())
|
||||||
return null;
|
// event.setCancelled(true);
|
||||||
|
//RFG// MMOItems.log("§8Reforge §4EFG§7 Keeping new item (Complete RNG Reroll)");
|
||||||
|
return;
|
||||||
|
|
||||||
// Just pass on
|
//RFG// MMOItems.log("§8Reforge §4EFG§7 Keeping old RNG Rolls");
|
||||||
return ((UpdatableRandomStatData) source).reroll(stat, original, determinedItemLevel);
|
|
||||||
|
event.getOldMMOItem().getStats()
|
||||||
|
.forEach(stat -> {
|
||||||
|
|
||||||
|
// Check if stat can be transferred over new item
|
||||||
|
final RandomStatData source = event.getReforger().getTemplate().getBaseItemData().get(stat);
|
||||||
|
if (source == null || !(source instanceof UpdatableRandomStatData))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decide if this data is too far from RNG to
|
||||||
|
* preserve its rolls, even if it should be
|
||||||
|
* preserving the rolls.
|
||||||
|
*/
|
||||||
|
final StatHistory hist = StatHistory.from(event.getOldMMOItem(), stat);
|
||||||
|
final StatData keptData = ((UpdatableRandomStatData) source).reroll(stat, hist.getOriginalData(), event.getReforger().getGenerationItemLevel());
|
||||||
|
|
||||||
|
// Old roll is ridiculously low probability under the new parameters. Forget.
|
||||||
|
if (keptData == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Fetch History from the new item
|
||||||
|
final StatHistory clear = StatHistory.from(event.getNewMMOItem(), stat);
|
||||||
|
|
||||||
|
// Replace original data of the new one with the roll from the old one
|
||||||
|
clear.setOriginalData(keptData);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -269,13 +269,6 @@ disable-vanilla-recipes: []
|
|||||||
# Options for the Item Revision System
|
# Options for the Item Revision System
|
||||||
item-revision:
|
item-revision:
|
||||||
|
|
||||||
# This is the value to set the Item Level to when
|
|
||||||
# items are updated by the revision system.
|
|
||||||
# This can be set to -1 to use the items previous level.
|
|
||||||
# Please note, that this value has no effect if
|
|
||||||
# ´reroll-when-updated´ is set to true.
|
|
||||||
default-item-level: -1
|
|
||||||
|
|
||||||
# Unsocketing gems picks them up with the stats they had
|
# Unsocketing gems picks them up with the stats they had
|
||||||
# when first put into the item, disable this option to
|
# when first put into the item, disable this option to
|
||||||
# force them to be regenerated.
|
# force them to be regenerated.
|
||||||
|
Loading…
Reference in New Issue
Block a user