Allow custom items with repairable to be repaired#6505
Conversation
There was a problem hiding this comment.
Pull request overview
This PR updates custom item Bedrock component generation so Java Edition-style “repairable” behavior works (non-zero repair amounts, self-repair with the same base item, and mapped repair materials) instead of currently being effectively non-repairable.
Changes:
- Adds a “base item” tag to custom items intended to enable self-repair behavior parity with Java Edition.
- Switches repairable component sourcing to MCPL
DataComponentTypes.REPAIRABLEand generates Bedrockminecraft:repairableusing Molang formulas. - Refactors item tag storage to use
Stringtags instead ofIdentifier.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| HolderSet repairable = context.components().get(DataComponentTypes.REPAIRABLE); | ||
| if (repairable != null) { | ||
| computeRepairableProperties(repairable, componentBuilder); | ||
| computeRepairableProperties(repairable, componentBuilder, context.vanillaMapping().map(GeyserMappingItem::getBedrockIdentifier).orElse(null)); | ||
| } |
| // Add a base item tag to the item, as in Java Edition they are still the same items and that we can behave the same in Bedrock | ||
| context.vanillaMapping().ifPresent(mapping -> addItemTag(componentBuilder, "geyser:" + mapping.getBedrockIdentifier())); | ||
|
|
| /** | ||
| * This method passes the Java identifiers straight to bedrock - which isn't perfect. Also doesn't work with holder sets that use a tag. | ||
| */ |
| List<NbtMap> repairItems = new ArrayList<>(); | ||
| if (baseItem != null) { | ||
| repairItems.add(NbtMap.builder() | ||
| .putList("items", NbtType.COMPOUND, NbtMap.builder() | ||
| .putString("name", baseItem) | ||
| .build(), NbtMap.builder() | ||
| .putString("tags", "q.all_tags('geyser:" + baseItem + "')") | ||
| .build()) | ||
| .putCompound("repair_amount", NbtMap.builder() | ||
| .putString("expression", "math.min(q.remaining_durability + c.other->q.remaining_durability + math.floor(q.max_durability * 0.05), q.max_durability)") | ||
| .putShort("version", (short) 12) | ||
| .build()) | ||
| .build()); | ||
| } | ||
| List<NbtMap> items = identifiers.stream() | ||
| .map(identifier -> NbtMap.builder() | ||
| .putString("name", identifier.toString()) | ||
| .build()).toList(); | ||
|
|
||
| componentBuilder.putCompound("minecraft:repairable", NbtMap.builder() | ||
| .putList("repair_items", NbtType.COMPOUND, NbtMap.builder() | ||
| if (items != null) { | ||
| repairItems.add(NbtMap.builder() | ||
| .putList("items", NbtType.COMPOUND, items) | ||
| .putFloat("repair_amount", 0.0F) | ||
| .build()) | ||
| .putCompound("repair_amount", NbtMap.builder() | ||
| .putString("expression", "q.max_durability * 0.25") | ||
| .putShort("version", (short) 12) | ||
| .build()) | ||
| .build()); | ||
| } | ||
| componentBuilder.putCompound("minecraft:repairable", NbtMap.builder() | ||
| .putList("repair_items", NbtType.COMPOUND, repairItems) | ||
| .build()); |
| private static void computeRepairableProperties(NbtMapBuilder componentBuilder) { | ||
| componentBuilder.putCompound("minecraft:repairable", NbtMap.builder() | ||
| .putList("repair_items", NbtType.COMPOUND, NbtMap.builder() | ||
| .putList("items", NbtType.COMPOUND, items) | ||
| .putFloat("repair_amount", 0.0F) | ||
| .putList("items", NbtType.COMPOUND, NbtMap.builder() | ||
| .putString("tags", "1") | ||
| .build()) | ||
| .putFloat("repair_amount", 1.0F) | ||
| .build()) | ||
| .build()); |
|
Hey! Thanks for the PR - would this mean that the "red x" would never show up for custom items? Or is the client "smart enough" there to show it when the item is e.g. already fully repaired? |
|
The "red x" would never show up, but I think its better than the "red x" always shows up there is also a proper solution, but I don't really have an overview over the custom items API, this is more of a temporary minimally invasive fix. |
onebeastchris
left a comment
There was a problem hiding this comment.
For a temporary hack, i'm okay with this. Personally, i think it would be ideal if we could allow users to specify the items / bedrock item tags so someone could spend more time to get a more accurate repairable component mapping though
Added a TODO comment to restrict repairs to the same Java item and its repair materials.
Currently repairables don't work at all as repair_amount is 0 which indicates it's not repairable
This PR now allows all items to be used to repair and are just rejected server-side