Smithing Crafting Recipes now supported.

**Update MythicLib**

Pro tip: Its not implemented in-game but you can write it in the config files directly:

```
    crafting:
      smithing:
        '1':
          input1: SWORD.HEARTSWORD
          input2: SWORD.ORACLE_SWORD

          # Makes extra gems drop instead of getting lost
          drop-gems: true

          # If both inputs have upgrades, how to treat them?
      #   upgrades: ADDITIVE  # Sum them
          upgrades: MAXIMUM   # Largest of them (Default)
      #   upgrades: EVEN      # Average
      #   upgrades: MINIMUM   # Minimum of them
      #   upgrades: NONE      # Actually just dont keep upgrades
```
This commit is contained in:
Gunging 2021-03-29 23:22:28 -05:00
parent e30a0f9e8f
commit 1f88c15f28
9 changed files with 591 additions and 35 deletions

View File

@ -0,0 +1,392 @@
package net.Indyuce.mmoitems.api.crafting.recipe;
import io.lumine.mythic.lib.api.crafting.ingredients.MythicBlueprintInventory;
import io.lumine.mythic.lib.api.crafting.ingredients.MythicRecipeInventory;
import io.lumine.mythic.lib.api.crafting.outputs.MRORecipe;
import io.lumine.mythic.lib.api.crafting.outputs.MythicRecipeOutput;
import io.lumine.mythic.lib.api.crafting.recipes.MythicCachedResult;
import io.lumine.mythic.lib.api.crafting.recipes.vmp.VanillaInventoryMapping;
import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.api.util.Ref;
import io.lumine.mythic.lib.api.util.ui.SilentNumbers;
import net.Indyuce.mmoitems.ItemStats;
import net.Indyuce.mmoitems.api.interaction.GemStone;
import net.Indyuce.mmoitems.api.item.mmoitem.LiveMMOItem;
import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem;
import net.Indyuce.mmoitems.api.item.template.MMOItemTemplate;
import net.Indyuce.mmoitems.stat.data.GemSocketsData;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryAction;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.HashMap;
/**
* Intended for use with Anvil / Smithing station, the combination of
* two MMOItems, or upgrading a MMOItem with an ingot, also combines the
* gems and upgrade level of the components.
*
* @author Gunging
*/
public class CustomSmithingRecipe extends MythicRecipeOutput {
/**
* @param outputItem The MMOItem that results from the completion of these recipes.
* @param dropGemstones Should extra gemstones be dropped? (Otherwise lost)
* @param upgradeTreatment How will upgrades combine?
*/
public CustomSmithingRecipe(@NotNull MMOItemTemplate outputItem, boolean dropGemstones, @NotNull UpgradeCombinationType upgradeTreatment) {
this.outputItem = outputItem;
this.dropGemstones = dropGemstones;
this.upgradeTreatment = upgradeTreatment; }
/**
* The MMOItem that results from the completion of these recipes.
*/
@NotNull final MMOItemTemplate outputItem;
/**
* @return The MMOItem that results from the completion of these recipes.
*/
@NotNull public MMOItemTemplate getOutputItem() { return outputItem; }
/**
* Will the extra gemstones be dropped to the ground?
*/
final boolean dropGemstones;
/**
* @return Will the extra gemstones be dropped to the ground?
*/
public boolean isDropGemstones() { return dropGemstones; }
/**
* @return How to treat upgrade level combinations?
*/
@NotNull
public UpgradeCombinationType getUpgradeTreatment() { return upgradeTreatment; }
/**
* How to treat upgrade level combinations?
*/
@NotNull final UpgradeCombinationType upgradeTreatment;
/**
* Is this a MMOItem? Well fetch
*
* @param item Item Stack to transform
* @return a MMOItem if appropriate.
*/
@Nullable MMOItem fromStack(@Nullable ItemStack item) {
if (item == null) { return null; } else {
NBTItem itemNBT = NBTItem.get(item);
if (itemNBT.hasType()) { return new LiveMMOItem(item); } }
return null; }
/**
* Is there at least one item in the first side inventory? Well git
*
* @param b Blueprint
* @return an ItemStack if any exists
*/
@Nullable ItemStack firstFromFirstSide(@NotNull MythicBlueprintInventory b) {
// No sides?
if (b.getSideInventoryNames().size() == 0) { return null; }
// Get
return b.getSideInventory(b.getSideInventoryNames().get(0)).getFirst(); }
@NotNull
@Override
public MythicRecipeInventory applyDisplay(@NotNull MythicBlueprintInventory mythicRecipeInventory, @NotNull InventoryClickEvent eventTrigger, @NotNull VanillaInventoryMapping mapping) {
// Not supported
if (!(eventTrigger.getWhoClicked() instanceof Player)) { return mythicRecipeInventory.getResultInventory(); }
// Get the two combinant items
MythicBlueprintInventory original = mapping.extractFrom(eventTrigger.getView().getTopInventory());
ItemStack item = original.getMainInventory().getFirst();
ItemStack ingot = firstFromFirstSide(original);
MMOItem itemMMO = fromStack(item);
MMOItem ingotMMO = fromStack(ingot);
// Get the display
MMOItem display = fromCombinationWith(itemMMO, ingotMMO, (Player) eventTrigger.getWhoClicked(), null);
// Result
MythicRecipeInventory result = mythicRecipeInventory.getResultInventory().clone();
result.setItemAt(mapping.getResultWidth(mapping.getResultInventoryStart()), mapping.getResultHeight(mapping.getResultInventoryStart()), display.newBuilder().build());
// Set the display
return result;
}
@Override
public void applyResult(@NotNull MythicRecipeInventory resultInventory, @NotNull MythicBlueprintInventory otherInventories, @NotNull MythicCachedResult cache, @NotNull InventoryClickEvent eventTrigger, @NotNull VanillaInventoryMapping map, int times) {
/*
* Listen, we'll take it from here. Cancel the original event.
*
* Now run Mythic Crafting version of the event.
* Did anyone cancel it? Well I guess we'll touch nothing then, but you also cant craft this item >:I
*/
eventTrigger.setCancelled(true);
if (!(eventTrigger.getWhoClicked() instanceof Player)) { return; }
// Get the two combinant items
ItemStack item = otherInventories.getMainInventory().getFirst();
ItemStack ingot = firstFromFirstSide(otherInventories);
MMOItem itemMMO = fromStack(item);
MMOItem ingotMMO = fromStack(ingot);
// Get the display
Ref<ArrayList<ItemStack>> droppedGemstones = new Ref<>();
MMOItem display = fromCombinationWith(itemMMO, ingotMMO, (Player) eventTrigger.getWhoClicked(), droppedGemstones);
// Result
MythicRecipeInventory result = otherInventories.getResultInventory().clone();
result.setItemAt(map.getResultWidth(map.getResultInventoryStart()), map.getResultHeight(map.getResultInventoryStart()), display.newBuilder().build());
/*
* Crafting the item only once allows to put it in the cursor.
*
* Otherwise, this stuff will have to
* 1 Calculate how many times until it runs out of inventory slots
* 2 Move it to those inventory slots
*/
if (times == 1 && (eventTrigger.getAction() != InventoryAction.MOVE_TO_OTHER_INVENTORY)) {
/*
* When crafting with the cursor, we must make sure that:
*
* 1 The player is holding nothing in the cursor
* or
*
* 2 The item in their cursor is stackable with the result
* and
* 3 The max stacks would not be exceeded
*/
ItemStack currentInCursor = eventTrigger.getCursor();
/*
* Set the result into the result slots.
*/
//RR//for (String str : result.toStrings("\u00a78Result \u00a79RR-")) { MythicCraftingManager.log(str); }
// Apply the result
//RDR//MythicCraftingManager.log("\u00a78RDR \u00a748\u00a77 Processing Result Inventory");
processInventory(resultInventory, result, times);
//RR//for (String str : resultInventory.toStrings("\u00a78Result \u00a79PR-")) { MythicCraftingManager.log(str); }
//RDR//MythicCraftingManager.log("\u00a78RDR \u00a749\u00a77 Finding item to put on cursor");
// Get the zeroth entry, which will be put in the players cursor >:o
ItemStack cursor = resultInventory.getItemAt(map.getResultWidth(eventTrigger.getSlot()), map.getResultHeight(eventTrigger.getSlot()));
if (cursor == null) { cursor = new ItemStack(Material.AIR); }
ItemStack actualCursor = cursor.clone();
/*
* All right, so, can the actual cursor stack with the current?
*/
if (!SilentNumbers.isAir(currentInCursor)) {
// Aye so they could stack
if (currentInCursor.isSimilar(actualCursor)) {
// Exceeds max stacks?
int cAmount = currentInCursor.getAmount();
int aAmount = actualCursor.getAmount();
int maxAmount = actualCursor.getMaxStackSize();
// Cancel if their sum would exceed the max
if (cAmount + aAmount > maxAmount) { return; }
// All right recalculate amount then
actualCursor.setAmount(cAmount + aAmount);
} else {
// Cancel this operation
return;
}
}
//RR//MythicCraftingManager.log("\u00a78Result \u00a74C\u00a77 Found for cursor " + SilentNumbers.getItemName(actualCursor));
// Deleting original item (now its going to be on cursor so)
cursor.setAmount(0);
// Apply result to the inventory
//RDR//MythicCraftingManager.log("\u00a78RDR \u00a7410\u00a77 Actually applying to result inventory through map");
map.applyToResultInventory(eventTrigger.getInventory(), resultInventory, false);
// Apply result to the cursor
eventTrigger.getView().setCursor(actualCursor);
// Player is crafting to completion - move to inventory style.
} else {
/*
* Set the result into the result slots.
*/
//RDR//MythicCraftingManager.log("\u00a78RDR \u00a747\u00a77 Reading/Generating Result");
// Build the result
ArrayList<ItemStack> outputItems = MRORecipe.toItemsList(result);
HashMap<Integer, ItemStack> modifiedInventory = null;
Inventory inven = eventTrigger.getWhoClicked().getInventory();
int trueTimes = 0;
// For every time
for (int t = 1; t <= times; t++) {
//RDR//MythicCraftingManager.log("\u00a78RDR \u00a748\u00a77 Iteration \u00a7c#" + t);
//RR//for (String str : localResult.toStrings("\u00a78Result \u00a79RR-")) { io.lumine.mythic.lib.api.crafting.recipes.MythicCraftingManager.log(str); }
// Send to
HashMap<Integer, ItemStack> localIterationResult = MRORecipe.distributeInInventory(inven, outputItems, modifiedInventory);
// Failed? Break
if (localIterationResult == null) {
// No changes in the modified inventory, just break
//RR//io.lumine.mythic.lib.api.crafting.recipes.MythicCraftingManager.log("\u00a78Result \u00a7cIC\u00a77 Iteration Cancelled: \u00a7cNo Inventory Space");
break;
// Prepare for next iteration
} else {
// Store changes
modifiedInventory = localIterationResult;
trueTimes = t;
//RR//io.lumine.mythic.lib.api.crafting.recipes.MythicCraftingManager.log("\u00a78Result \u00a7aIV\u00a77 Iteration Validated, total times: \u00a7a" + trueTimes);
} }
// True times is 0? Cancel this.
if (trueTimes == 0) { return; }
// All right apply
times = trueTimes;
for (Integer s : modifiedInventory.keySet()) {
// Get Item
ItemStack putt = modifiedInventory.get(s);
//RR//io.lumine.mythic.lib.api.crafting.recipes.MythicCraftingManager.log("\u00a78Result \u00a79IS\u00a77 Putting \u00a7b@" + s + "\u00a77 a " + SilentNumbers.getItemName(putt));
// Set
inven.setItem(s, putt); }
}
// Drop?
if (isDropGemstones() && (droppedGemstones.getValue() != null) && (eventTrigger.getWhoClicked().getLocation().getWorld() != null)) {
Location l = eventTrigger.getWhoClicked().getLocation();
// Drop each yea
for (ItemStack gem : droppedGemstones.getValue()) {
if (SilentNumbers.isAir(gem)) { continue; }
// God damn drop yo
l.getWorld().dropItemNaturally(l, gem);
} }
// Consume ingredients
consumeIngredients(otherInventories, cache, eventTrigger.getInventory(), map, times);
}
/**
* @param item The item you are upgrading
* @param ingot The second item you are upgrading
*
* @return What would the output be if combined with this other MMOItem?
*/
@NotNull MMOItem fromCombinationWith(@Nullable MMOItem item, @Nullable MMOItem ingot, @NotNull Player p, @Nullable Ref<ArrayList<ItemStack>> rem) {
// Generate
MMOItem gen = getOutputItem().newBuilder(0, null).build();
/*
* Two things must be merged:
*
* 1 Gem Stones - Checks which gem stones can still fit
*
* 2 Upgrades - Performs an operation with the combination of them both
*/
// Extract gemstones
ArrayList<MMOItem> compGemstones = new ArrayList<>();
if (item != null) { compGemstones.addAll(item.extractGemstones()); }
if (ingot != null) { compGemstones.addAll(ingot.extractGemstones()); }
// Which stones would not fit
ArrayList<ItemStack> remainingStones = new ArrayList<>();
for (MMOItem m : compGemstones) {
//GEM// MMOItems.log("\u00a76 +\u00a77 Fitting \u00a7e" + m.getType().toString() + " " + m.getId());
// What sockets are available?
GemSocketsData genGemstones = (GemSocketsData) gen.getData(ItemStats.GEM_SOCKETS);
// Abort lol
if (genGemstones == null || (genGemstones.getEmptySlots().size() == 0)) {
//GEM// MMOItems.log("\u00a7c !!\u00a77 Dropping: No more empty slots in target ");
// Just keep as 'remaining'
remainingStones.add(m.newBuilder().build());
continue; }
// Ok proceed
GemStone asGem = new GemStone(p, m.newBuilder().buildNBT());
// Put
GemStone.ApplyResult res = asGem.applyOntoItem(gen, gen.getType(), "", false, true);
// None?
if (res.getType().equals(GemStone.ResultType.SUCCESS) && (res.getResultAsMMOItem() != null)) {
// Success that's nice
gen = res.getResultAsMMOItem();
//GEM// MMOItems.log("\u00a7a W\u00a77 Socketed! ");
// Didn't fit L
} else {
//GEM// MMOItems.log("\u00a7e !!\u00a77 Dropping: Does not fit socket ");
remainingStones.add(m.newBuilder().build()); } }
// Set value
Ref.setValue(rem, remainingStones);
// All right whats the level stuff up now
if (gen.hasUpgradeTemplate() && !(getUpgradeTreatment().equals(UpgradeCombinationType.NONE))) {
// All right get the levels of them both
int itemLevel = 0; if (item != null) { itemLevel = item.getUpgradeLevel(); }
int ingotLevel = 0; if (ingot != null) { ingotLevel = ingot.getUpgradeLevel(); }
int finalLevel;
switch (getUpgradeTreatment()) {
case ADDITIVE: finalLevel = itemLevel + ingotLevel; break;
case MAXIMUM: finalLevel = Math.max(itemLevel, ingotLevel); break;
case MINIMUM: finalLevel = Math.min(itemLevel, ingotLevel); break;
default: finalLevel = SilentNumbers.ceil((itemLevel + ingotLevel) / 2D); break;
}
// Upgrade yes
gen.getUpgradeTemplate().upgradeTo(gen, Math.min(finalLevel, gen.getMaxUpgradeLevel())); }
// That's it
return gen;
}
}

View File

@ -0,0 +1,30 @@
package net.Indyuce.mmoitems.api.crafting.recipe;
public enum UpgradeCombinationType {
/**
* Adds the upgrade levels of both items
*/
ADDITIVE,
/**
* Chooses the upgrade level of the item
* with the greatest upgrade level
*/
MAXIMUM,
/**
* Takes the average of the upgrade levels
*/
EVEN,
/**
* Chooses the least upgrade level
*/
MINIMUM,
/**
* Upgrade levels are lost
*/
NONE
}

View File

@ -7,6 +7,8 @@ import net.Indyuce.mmoitems.api.Type;
import net.Indyuce.mmoitems.api.event.item.ApplyGemStoneEvent;
import net.Indyuce.mmoitems.api.item.mmoitem.LiveMMOItem;
import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem;
import net.Indyuce.mmoitems.api.item.mmoitem.VolatileMMOItem;
import net.Indyuce.mmoitems.api.player.PlayerData;
import net.Indyuce.mmoitems.api.util.message.Message;
import net.Indyuce.mmoitems.stat.GemUpgradeScaling;
import net.Indyuce.mmoitems.stat.data.GemSocketsData;
@ -23,6 +25,8 @@ import org.bukkit.ChatColor;
import org.bukkit.Sound;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class GemStone extends UseItem {
@ -30,13 +34,18 @@ public class GemStone extends UseItem {
super(player, item);
}
public ApplyResult applyOntoItem(NBTItem target, Type targetType) {
@NotNull public ApplyResult applyOntoItem(@NotNull NBTItem target, @NotNull Type targetType) {
/*
* Entirely loads the MMOItem and checks if it has the required empty
* socket for the gem
*/
MMOItem targetMMO = new LiveMMOItem(target);
return applyOntoItem(targetMMO, targetType, MMOUtils.getDisplayName(target.getItem()), true, false);
}
@NotNull public ApplyResult applyOntoItem(@NotNull MMOItem targetMMO, @NotNull Type targetType, @NotNull String itemName, boolean buildStack, boolean silent){
if (!targetMMO.hasData(ItemStats.GEM_SOCKETS))
return new ApplyResult(ResultType.NONE);
@ -59,10 +68,11 @@ public class GemStone extends UseItem {
// check for success rate
double successRate = getNBTItem().getStat(ItemStats.SUCCESS_RATE.getId());
if (successRate != 0 && RANDOM.nextDouble() > successRate / 100) {
player.playSound(player.getLocation(), Sound.ENTITY_ITEM_BREAK, 1, 1);
Message.GEM_STONE_BROKE
.format(ChatColor.RED, "#gem#", MMOUtils.getDisplayName(getItem()), "#item#", MMOUtils.getDisplayName(target.getItem()))
.send(player);
if (!silent) {
player.playSound(player.getLocation(), Sound.ENTITY_ITEM_BREAK, 1, 1);
Message.GEM_STONE_BROKE.format(ChatColor.RED, "#gem#", MMOUtils.getDisplayName(getItem()), "#item#", itemName).send(player); }
return new ApplyResult(ResultType.FAILURE);
}
@ -124,38 +134,46 @@ public class GemStone extends UseItem {
}
}
player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1, 2);
Message.GEM_STONE_APPLIED
.format(ChatColor.YELLOW, "#gem#", MMOUtils.getDisplayName(getItem()), "#item#", MMOUtils.getDisplayName(target.getItem()))
.send(player);
if (!silent) {
player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1, 2);
Message.GEM_STONE_APPLIED.format(ChatColor.YELLOW, "#gem#", MMOUtils.getDisplayName(getItem()), "#item#", itemName).send(player); }
return new ApplyResult(targetMMO.newBuilder().build());
if (buildStack) {
return new ApplyResult(targetMMO.newBuilder().build());
} else { return new ApplyResult(targetMMO, ResultType.SUCCESS); }
}
public static class ApplyResult {
private final ResultType type;
private final ItemStack result;
@NotNull private final ResultType type;
@Nullable private final ItemStack result;
@Nullable private final MMOItem resultAsMMOItem;
public ApplyResult(ResultType type) {
this(null, type);
public ApplyResult(@NotNull ResultType type) {
this((ItemStack) null, type);
}
public ApplyResult(ItemStack result) {
this(result, ResultType.SUCCESS);
}
public ApplyResult(@Nullable ItemStack result) { this(result, ResultType.SUCCESS); }
public ApplyResult(ItemStack result, ResultType type) {
public ApplyResult(@Nullable ItemStack result, @NotNull ResultType type) {
this.type = type;
this.result = result;
this.resultAsMMOItem = null;
}
public ApplyResult(@Nullable MMOItem result, @NotNull ResultType type) {
this.type = type;
this.result = null;
this.resultAsMMOItem = result;
}
public ResultType getType() {
@NotNull public ResultType getType() {
return type;
}
public ItemStack getResult() {
@Nullable public ItemStack getResult() {
return result;
}
@Nullable public MMOItem getResultAsMMOItem() { return resultAsMMOItem; }
}
public enum ResultType {

View File

@ -6,6 +6,7 @@ import net.Indyuce.mmoitems.api.Type;
import net.Indyuce.mmoitems.api.UpgradeTemplate;
import net.Indyuce.mmoitems.api.item.ItemReference;
import net.Indyuce.mmoitems.api.item.build.ItemStackBuilder;
import net.Indyuce.mmoitems.stat.GemSockets;
import net.Indyuce.mmoitems.stat.data.GemSocketsData;
import net.Indyuce.mmoitems.stat.data.GemstoneData;
import net.Indyuce.mmoitems.stat.data.UpgradeData;
@ -243,6 +244,22 @@ public class MMOItem implements ItemReference {
return 0;
}
/**
* @return The upgrade level, or 0 if there is none.
*/
public int getMaxUpgradeLevel() {
// Does it have Upgrade Data?
if (hasData(ItemStats.UPGRADE)) {
// Return the registered level.
return ((UpgradeData) getData(ItemStats.UPGRADE)).getMax();
}
// Nope? Well its level 0 I guess.
return 0;
}
/**
* <b>Make sure to check {@link #hasUpgradeTemplate()} before calling.</b>
* <p></p>
@ -282,4 +299,72 @@ public class MMOItem implements ItemReference {
}
}
//endregion
//region Gem Sockets API
/**
* It is not 100% fool proof, since some GemStones just don't have
* enough information to be extracted (legacy gemstones).
* <p></p>
* Note that this is somewhat an expensive operation, restrain
* from calling it much because it completely loads all the stats
* of every Gem Stone.
*
* @see #getColor()
*
* @return The list of GemStones contained here.
*/
@NotNull public ArrayList<MMOItem> extractGemstones() {
// Found?
GemSocketsData thisSocketsData = (GemSocketsData) getData(ItemStats.GEM_SOCKETS);
if (thisSocketsData == null) { return new ArrayList<>(); }
// All right, whats all yous data
HashMap<UUID, MMOItem> regeneratedGems = new HashMap<>();
for (GemstoneData gem : thisSocketsData.getGemstones()) {
// Can we generate?
MMOItem restored = MMOItems.plugin.getMMOItem(MMOItems.plugin.getType(gem.getMMOItemType()), gem.getMMOItemID());
// Valid? neat-o
if (restored != null) {
restored.color = gem.getSocketColor();
regeneratedGems.put(gem.getHistoricUUID(), restored);
} }
// Identify actual attributes
for (ItemStat stat : getStats()) {
// Mergeable right
if (!(stat.getClearStatData() instanceof Mergeable)) { continue; }
// Any stat affected by gems is sure to have a Stat History
StatHistory hist = getStatHistory(stat);
if (hist == null) { continue; }
// Data associated with any of the gems?
for (Map.Entry<UUID, MMOItem> gem : regeneratedGems.entrySet()) {
// History got gem registered?
StatData historicGemData = hist.getGemstoneData(gem.getKey());
if (historicGemData == null) { continue;}
// This gemstone had this data... Override.
gem.getValue().setData(stat, historicGemData);
} }
// Thats the gemstones we was searching for
return new ArrayList<>(regeneratedGems.values());
}
@Nullable String color;
/**
* @return Supposing this MMOItem is a Gem Stone within an item,
* obtained via {@link #extractGemstones()}, then this
* will be the color of the slot it occupies.
*/
@Nullable public String getColor() { return color; }
//endregion
}

View File

@ -1040,7 +1040,7 @@ public class MMOItemReforger {
} else {
// Get colour
String colour = data.getColour();
String colour = data.getSocketColor();
String remembrance;
// Not null?

View File

@ -11,6 +11,7 @@ import io.lumine.mythic.lib.api.crafting.recipes.MythicRecipeBlueprint;
import io.lumine.mythic.lib.api.crafting.recipes.MythicRecipeStation;
import io.lumine.mythic.lib.api.util.ui.FriendlyFeedbackCategory;
import io.lumine.mythic.lib.api.util.ui.FriendlyFeedbackProvider;
import net.Indyuce.mmoitems.api.crafting.recipe.UpgradeCombinationType;
import net.Indyuce.mmoitems.api.util.message.FFPMMOItems;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
@ -165,13 +166,24 @@ public class RecipeManager implements Reloadable {
loadedLegacyRecipes.add(recipe);
}
public void registerSmithingRecipe(Type type, String id, ConfigurationSection section, String number) {
public void registerSmithingRecipe(@NotNull Type type, @NotNull String id, @NotNull ConfigurationSection section, @NotNull String number) throws IllegalArgumentException {
Validate.isTrue(section.isString("input1") && section.isString("input2"), "Invalid smithing recipe for '" + type.getId() + " . " + id + "'");
WorkbenchIngredient input1 = getWorkbenchIngredient(section.getString("input1"));
WorkbenchIngredient input2 = getWorkbenchIngredient(section.getString("input2"));
SmithingRecipe recipe = new SmithingRecipe(getRecipeKey(type, id, "smithing", number), MMOItems.plugin.getItem(type, id), input1.toBukkit(),
input2.toBukkit());
loadedLegacyRecipes.add(recipe);
String item = section.getString("input1");
String ingot = section.getString("input2");
boolean dropGems = section.getBoolean("drop-gems", false);
String upgrade = section.getString("upgrades" );
if (item == null) { item = ""; }
if (ingot == null) { ingot = ""; }
if (upgrade == null) { upgrade = UpgradeCombinationType.MAXIMUM.toString(); }
MythicRecipeBlueprint blueprint = CustomRecipe.generateSmithing(type, id, item, ingot, dropGems, upgrade);
// Remember it
customRecipes.add(blueprint);
// Enable it
blueprint.deploy(MythicRecipeStation.SMITHING);
}
/**

View File

@ -7,6 +7,7 @@ import java.util.Set;
import io.lumine.mythic.lib.api.util.Ref;
import net.Indyuce.mmoitems.api.interaction.GemStone;
import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem;
import org.apache.commons.lang.Validate;
import com.google.gson.JsonArray;

View File

@ -21,6 +21,24 @@ public class GemstoneData {
@Nullable Integer levelPut = 0;
@NotNull final UUID historicUUID;
@Nullable
public String getMMOItemType() {
return mmoitemType;
}
@Nullable
public String getMMOItemID() {
return mmoitemID;
}
/**
* If known, the socket colour this gem was put into
*/
@Nullable
public String getSocketColor() {
return socketColor;
}
@Nullable final String mmoitemType;
@Nullable final String mmoitemID;
@Nullable
@ -173,11 +191,6 @@ public class GemstoneData {
return name;
}
/**
* If known, the socket colour this gem was put into
*/
@Nullable public String getColour() { return socketColor; }
/**
* If known, the socket colour this gem was put into
*/

View File

@ -26,7 +26,7 @@ import java.util.*;
* <p></p>
* This class will store the different sources of each stat UPON being modified.
*/
@SuppressWarnings({"unused", "unchecked", "SpellCheckingInspection"})
@SuppressWarnings({"unused", "SpellCheckingInspection"})
public class StatHistory {
/*
@ -84,7 +84,7 @@ public class StatHistory {
* The final modifier being provided by each gemstone.
* GemStones may have scaled with upgrades, that will be accounted for.
*/
@NotNull public StatData getGemstoneData(UUID of) { return perGemstoneData.get(of); }
@Nullable public StatData getGemstoneData(UUID of) { return perGemstoneData.get(of); }
/**
* All the Stat Datas provided by GemStones
@ -330,6 +330,7 @@ public class StatHistory {
if (gData.isScaling()) {
// Ok
//noinspection ConstantConditions
level = gData.getLevel();
} else {
@ -346,6 +347,7 @@ public class StatHistory {
//DBL//if (getGemstoneData(d) instanceof DoubleData) MMOItems. Log("\u00a76 \u00a7b|>\u00a77 Gemstone Base: \u00a7e" + ((DoubleData) getGemstoneData(d)).getValue());
// Apply upgrades
//noinspection ConstantConditions
StatData gRet = ((Upgradable) getItemStat()).apply(((Mergeable) getGemstoneData(d)).cloneData(), inf, gLevel);
//DBL//if (gRet instanceof DoubleData) MMOItems.Log("\u00a76 \u00a7b|>\u00a77 Leveled Base: \u00a7e" + ((DoubleData) gRet).getValue());
@ -428,6 +430,7 @@ public class StatHistory {
JsonObject yes = new JsonObject();
// Compress tags
//noinspection ConstantConditions
JsonArray yesCompressed = ItemTag.compressTags(getItemStat().getAppliedNBT(getGemstoneData(gem)));
// Put
@ -640,7 +643,9 @@ public class StatHistory {
//UPDT//MMOItems.Log(" \u00a76:\u00a72: \u00a77Original Externals \u00a7f" + perExternalData.size());
// Register gemstones
for (UUID exUID : other.perGemstoneData.keySet()) { registerGemstoneData(exUID, other.getGemstoneData(exUID)); }
for (UUID exUID : other.perGemstoneData.keySet()) {
//noinspection ConstantConditions
registerGemstoneData(exUID, other.getGemstoneData(exUID)); }
// Register externals
for (StatData ex : other.perExternalData) { registerExternalData((ex)); }