Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,5 @@ runs when a report was generated.

Coverage proves the exercised Java behavior. It does not replace a live Paper
server integration check with the pinned ItemsAdder/MMOItems/TLibs versions.

Failed alloy forges record consumed ingredient quantities on scrap for Recycler recovery. Older scrap retains only its recorded base; missing catalyst history cannot be recovered.
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ public NamableAlloy forge(Player p, int i) {
ItemManager itemManager = MMOItems.plugin.getItems();
ItemStack template = itemManager.getMMOItem(MMOItems.plugin.getTypes().get(scrapType),scrapId).newBuilder().build();
if(station.getBaseItem() != null) ScrapProvenance.applyTo(template, station.getBaseItem().getId());
var consumed = new java.util.LinkedHashMap<String, Integer>();
for (Ingredient ingredient : station.getIngredients()) {
consumed.merge(ingredient.getId(), 1, Integer::sum);
}
ScrapProvenance.applyInputs(template, consumed);
loc.getWorld().dropItem(loc, template);
return null;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
package net.tfminecraft.advancedcrafting.objects.data;

import java.util.Locale;
import java.util.LinkedHashMap;
import java.util.Map;

import org.bukkit.NamespacedKey;

import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataType;

import net.tfminecraft.advancedcrafting.utils.PDCKeys;
import net.tfminecraft.advancedcrafting.AdvancedCrafting;

/**
* Records which base ingredient a failed alloy forge consumed, so scrap can be recycled into it.
Expand Down Expand Up @@ -34,4 +39,34 @@ public static String readBaseId(ItemStack item) {
}
return item.getItemMeta().getPersistentDataContainer().get(PDCKeys.scrapBase(), PersistentDataType.STRING);
}

/** Records consumed ingredient quantities per scrap, independently of the legacy base tag. */
public static void applyInputs(ItemStack item, Map<String, Integer> amounts) {
ItemMeta meta = item.getItemMeta();
var container = meta.getPersistentDataContainer();
var inputs = container.getAdapterContext().newPersistentDataContainer();
amounts.forEach((id, amount) -> inputs.set(
new NamespacedKey(AdvancedCrafting.plugin, id.toLowerCase(Locale.ROOT)),
PersistentDataType.INTEGER, amount));
container.set(PDCKeys.scrapInputs(), PersistentDataType.TAG_CONTAINER, inputs);
item.setItemMeta(meta);
}

/** Legacy scrap contains only a base tag; its catalysts cannot be reconstructed. */
public static Map<String, Integer> readInputs(ItemStack item) {
if (item == null || !item.hasItemMeta()) return Map.of();
var inputs = item.getItemMeta().getPersistentDataContainer().get(
PDCKeys.scrapInputs(), PersistentDataType.TAG_CONTAINER);
if (inputs == null) {
String base = readBaseId(item);
return base == null || base.isBlank() ? Map.of() : Map.of(base, 1);
}
Map<String, Integer> amounts = new LinkedHashMap<>();
for (var key : inputs.getKeys()) {
if (!inputs.has(key, PersistentDataType.INTEGER)) continue;
int amount = inputs.get(key, PersistentDataType.INTEGER);
if (amount > 0) amounts.put(key.getKey(), amount);
}
return amounts;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ public static NamespacedKey scrapBase() {
return new NamespacedKey(AdvancedCrafting.plugin, "ac_scrap_base");
}

public static NamespacedKey scrapInputs() {
return new NamespacedKey(AdvancedCrafting.plugin, "ac_scrap_inputs");
}

public static NamespacedKey ingredientId() {
return new NamespacedKey(AdvancedCrafting.plugin, "ac_ingredient_id");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ void forgeReturnsScrapKnownAlloysNewDiscoveriesAndRecoversStaleIndexes() throws
try (var dbs = mockConstruction(AlloyDatabase.class)) {
assertNull(forger(station, 0).forge(p));
verify(dbs.constructed().getFirst()).saveRecipe(station, "scrap");
var dropped = loc.getWorld().getEntitiesByClass(org.bukkit.entity.Item.class).iterator().next().getItemStack();
assertEquals(Map.of("iron", 1, "copper", 1), ScrapProvenance.readInputs(dropped));
}
try (var dbs =
mockConstruction(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package net.tfminecraft.advancedcrafting;

import static org.junit.jupiter.api.Assertions.*;
import java.util.Map;
import net.tfminecraft.advancedcrafting.objects.data.ScrapProvenance;
import net.tfminecraft.advancedcrafting.utils.PDCKeys;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.inventory.ItemStack;
import org.bukkit.persistence.PersistentDataType;
import org.junit.jupiter.api.Test;

class ScrapInputsTest extends CoverageSupport {
@Test
void inputsRoundTripQuantitiesAndLegacyScrapReturnsOnlyItsBase() {
var scrap = new ItemStack(Material.IRON_NUGGET);
assertTrue(ScrapProvenance.readInputs(null).isEmpty());
assertTrue(ScrapProvenance.readInputs(org.mockito.Mockito.mock(ItemStack.class)).isEmpty());
assertTrue(ScrapProvenance.readInputs(scrap).isEmpty());
scrap.setItemMeta(scrap.getItemMeta());
var meta = scrap.getItemMeta();
meta.setDisplayName("Scrap");
scrap.setItemMeta(meta);
assertTrue(ScrapProvenance.readInputs(scrap).isEmpty());
ScrapProvenance.applyTo(scrap, "IRON");
assertEquals(Map.of("iron", 1), ScrapProvenance.readInputs(scrap));
ScrapProvenance.applyInputs(scrap, Map.of("IRON", 2, "ruby", 3, "zero", 0));
assertEquals(Map.of("iron", 2, "ruby", 3), ScrapProvenance.readInputs(scrap));
meta = scrap.getItemMeta();
var inputs = meta.getPersistentDataContainer().get(PDCKeys.scrapInputs(), PersistentDataType.TAG_CONTAINER);
inputs.set(new NamespacedKey(plugin, "bad"), PersistentDataType.STRING, "bad");
meta.getPersistentDataContainer().set(PDCKeys.scrapInputs(), PersistentDataType.TAG_CONTAINER, inputs);
scrap.setItemMeta(meta);
assertEquals(Map.of("iron", 2, "ruby", 3), ScrapProvenance.readInputs(scrap));
meta = scrap.getItemMeta();
meta.getPersistentDataContainer().remove(PDCKeys.scrapInputs());
meta.getPersistentDataContainer().set(PDCKeys.scrapBase(), PersistentDataType.STRING, " ");
scrap.setItemMeta(meta);
assertTrue(ScrapProvenance.readInputs(scrap).isEmpty());
}
}
Loading