1.9.1
Compatibility
Changes
BackPackSSS v1.9 → v1.9.1
Reported symptoms
- The upgrade recipes for backpacks do not behave correctly in the crafting recipe book.
- Players cannot craft the Good Backpack ("Medium", Tier 2) even with the correct materials.
Both symptoms trace back to a single root cause.
BUG-11 (Critical): ExactChoice NBT-lock on the upgrade recipes
File: BackPackSSS.java → registerRecipes()
Root cause
The Tier 2 and Tier 3 recipes used the center ingredient slot ('B') like this:
ItemStack centerItem = backpackManager.createBackpack(1); // freshly generated, no BP_ID yet
...
recipe.setIngredient('B', new RecipeChoice.ExactChoice(centerItem));
RecipeChoice.ExactChoice requires the item placed in the crafting grid to be byte-for-byte
NBT-identical to centerItem (via ItemStack.isSimilar). At the moment registerRecipes()
runs, centerItem only carries BP_TIER_KEY in its PersistentDataContainer — it has never
been opened, so it has no BP_ID_KEY yet.
The problem is BackpackListener#onInteract:
if (!pdc.has(BackpackManager.BP_ID_KEY, PersistentDataType.STRING)) {
UUID newId = UUID.randomUUID();
pdc.set(BackpackManager.BP_ID_KEY, PersistentDataType.STRING, newId.toString());
item.setItemMeta(meta);
}
The very first time a player right-clicks their Weak Backpack to open it (which is the normal
thing every player does), a random BP_ID_KEY is permanently stamped onto that specific
item's NBT. From that point on, the item can never be isSimilar() to the "clean" centerItem
used to register the recipe — every real, previously-used backpack in the world is now a
different NBT snapshot than the one the recipe was built from.
When that happens, Bukkit's own recipe matcher rejects the shape entirely before
BackpackListener#onPrepareCraft (the plugin's own tier-validation handler, which already only
checks BP_TIER_KEY and is correct) ever gets a chance to run:
- The crafting table shows no output at all → "cannot craft the Medium Backpack".
- The recipe-book auto-fill/highlight can't find any inventory item that satisfies the exact NBT requirement, so the upgrade recipe never lights up as craftable even when the player is holding a valid Weak Backpack → "recipe doesn't show/work in the recipe book".
In short: the plugin already had correct validation logic in onPrepareCraft(), but the
ExactChoice ingredient acted as a stricter gate in front of it that silently blocked
everything as soon as any backpack had been used once.
Fix
Replaced the ingredient with a plain MaterialChoice, matching the fallback branch the code
already used when centerItem was null:
recipe.setIngredient('B', new RecipeChoice.MaterialChoice(Material.BUNDLE));
Now Bukkit's matcher only checks "is this a Bundle in the center slot", and the existing
onPrepareCraft() logic (isBackpackTier(center, 1) / isBackpackTier(center, 2)) — which
correctly reads only BP_TIER_KEY and ignores the per-instance BP_ID_KEY — is what actually
decides whether the craft is valid and sets the result. A used backpack, a freshly crafted one,
or one obtained via /backpack give all now work identically as upgrade material. A plain
vanilla Bundle or wrong-tier backpack placed in the center slot still correctly produces no
result.
Files changed
BackPackSSS.java(registerRecipes()), Tier 2 and Tier 3 blocks.
Verification steps for testing
/backpack give 1 <player>→ craft is not required for this check.- Right-click the Weak Backpack to open it once (this stamps
BP_ID_KEY). - Place it in the center of a crafting table with Iron + Redstone around it.
- Confirm the Good Backpack (Tier 2 / "Medium") now appears as the output and can be taken.
- Confirm the recipe is discoverable and highlights correctly in the recipe book.
- Repeat for Tier 2 → Tier 3 with Shulker Shell + Diamond.
Version bumped: 1.9 → 1.9.1 (pom.xml, plugin.yml, config.yml header).
Projects on Modrinth are automatically available through a Maven repository for use with JVM build tools such as Gradle. To learn more about the Modrinth Maven API, click here.
Note: When available, you should use the creator's maven repo instead as it will have transitive dependency information that the Modrinth Maven API does not. You may also end up with duplicate dependencies if you use a mix of Modrinth and non-Modrinth Maven repositories for your dependencies, because the group identifier will be different when served through the Modrinth Maven API.
Maven coordinates:
Version ID:
build.gradle:
repositories {
exclusiveContent {
forRepository {
maven {
name = "Modrinth"
url = "https://api.modrinth.com/maven"
}
}
// forRepositories(fg.repository) // Uncomment when using ForgeGradle
filter {
includeGroup "maven.modrinth"
}
}
}
// Standard Gradle dependency
dependencies {
implementation "maven.modrinth:T8kyE5QU:Nw3Jcl5T"
}
// Legacy Loom dependency
dependencies {
modImplementation "maven.modrinth:T8kyE5QU:Nw3Jcl5T"
}

