mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-29 11:59:11 +00:00
anvil repair system
This commit is contained in:
@@ -62,7 +62,7 @@ public class ComponentItemFactory extends BukkitItemFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void displayName(ItemWrapper<ItemStack> item, String json) {
|
||||
protected void customName(ItemWrapper<ItemStack> item, String json) {
|
||||
if (json == null) {
|
||||
item.removeComponent(ComponentKeys.CUSTOM_NAME);
|
||||
} else {
|
||||
@@ -71,7 +71,7 @@ public class ComponentItemFactory extends BukkitItemFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<String> displayName(ItemWrapper<ItemStack> item) {
|
||||
protected Optional<String> customName(ItemWrapper<ItemStack> item) {
|
||||
if (!item.hasComponent(ComponentKeys.CUSTOM_NAME)) return Optional.empty();
|
||||
return Optional.ofNullable(
|
||||
(String) ComponentType.encodeJava(
|
||||
@@ -272,4 +272,19 @@ public class ComponentItemFactory extends BukkitItemFactory {
|
||||
item.setComponent(ComponentKeys.MAX_STACK_SIZE, maxStackSize);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void repairCost(ItemWrapper<ItemStack> item, Integer data) {
|
||||
if (data == null) {
|
||||
item.removeComponent(ComponentKeys.REPAIR_COST);
|
||||
} else {
|
||||
item.setComponent(ComponentKeys.REPAIR_COST, data);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<Integer> repairCost(ItemWrapper<ItemStack> item) {
|
||||
if (!item.hasComponent(ComponentKeys.REPAIR_COST)) return Optional.empty();
|
||||
return Optional.ofNullable((Integer) ComponentType.encodeJava(ComponentKeys.REPAIR_COST, item.getComponent(ComponentKeys.REPAIR_COST)).orElse(null));
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ public class UniversalItemFactory extends BukkitItemFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void displayName(ItemWrapper<ItemStack> item, String json) {
|
||||
protected void customName(ItemWrapper<ItemStack> item, String json) {
|
||||
if (json != null) {
|
||||
item.set(json, "display", "Name");
|
||||
} else {
|
||||
@@ -32,19 +32,19 @@ public class UniversalItemFactory extends BukkitItemFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<String> displayName(ItemWrapper<ItemStack> item) {
|
||||
protected Optional<String> customName(ItemWrapper<ItemStack> item) {
|
||||
if (!item.hasTag("display", "Name")) return Optional.empty();
|
||||
return Optional.of(item.get("display", "Name"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void itemName(ItemWrapper<ItemStack> item, String json) {
|
||||
throw new UnsupportedOperationException("This feature is only available on 1.20.5+");
|
||||
customName(item, json);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<String> itemName(ItemWrapper<ItemStack> item) {
|
||||
throw new UnsupportedOperationException("This feature is only available on 1.20.5+");
|
||||
return customName(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -218,4 +218,15 @@ public class UniversalItemFactory extends BukkitItemFactory {
|
||||
@Override
|
||||
protected void maxStackSize(ItemWrapper<ItemStack> item, Integer maxStackSize) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void repairCost(ItemWrapper<ItemStack> item, Integer data) {
|
||||
item.set(data, "RepairCost");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<Integer> repairCost(ItemWrapper<ItemStack> item) {
|
||||
if (!item.hasTag("RepairCost")) return Optional.empty();
|
||||
return Optional.of(item.get("RepairCost"));
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,13 @@
|
||||
package net.momirealms.craftengine.bukkit.item.recipe;
|
||||
|
||||
import com.destroystokyo.paper.event.inventory.PrepareResultEvent;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.plugin.injector.BukkitInjector;
|
||||
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
import net.momirealms.craftengine.bukkit.util.ComponentUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.ItemUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.LegacyInventoryUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
@@ -15,10 +18,10 @@ import net.momirealms.craftengine.core.item.recipe.Recipe;
|
||||
import net.momirealms.craftengine.core.item.recipe.RecipeTypes;
|
||||
import net.momirealms.craftengine.core.item.recipe.input.CraftingInput;
|
||||
import net.momirealms.craftengine.core.item.recipe.input.SingleItemInput;
|
||||
import net.momirealms.craftengine.core.pack.LoadingSequence;
|
||||
import net.momirealms.craftengine.core.plugin.config.ConfigManager;
|
||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
import net.momirealms.craftengine.core.util.AdventureHelper;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.Pair;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
@@ -459,21 +462,19 @@ public class RecipeEventListener implements Listener {
|
||||
return;
|
||||
}
|
||||
|
||||
// one of them is vanilla item
|
||||
if (!firstCustom || !secondCustom) {
|
||||
// block "vanilla + custom" recipes
|
||||
if (wrappedFirst.vanillaId().equals(wrappedSecond.vanillaId())) {
|
||||
event.setResult(null);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// both of them are custom items
|
||||
// if the second is an enchanted book, then apply it
|
||||
if (wrappedSecond.vanillaId().equals(ItemKeys.ENCHANTED_BOOK)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// one of them is vanilla item
|
||||
if (!firstCustom || !secondCustom) {
|
||||
// block "vanilla + custom" recipes
|
||||
event.setResult(null);
|
||||
return;
|
||||
}
|
||||
|
||||
// not the same item
|
||||
if (!wrappedFirst.customId().equals(wrappedSecond.customId())) {
|
||||
event.setResult(null);
|
||||
@@ -511,10 +512,12 @@ public class RecipeEventListener implements Listener {
|
||||
}
|
||||
|
||||
Item<ItemStack> wrappedFirst = BukkitItemManager.instance().wrap(first);
|
||||
int damage = wrappedFirst.damage().orElse(0);
|
||||
|
||||
int maxDamage = wrappedFirst.maxDamage().orElse(0);
|
||||
// not a repairable item
|
||||
if (maxDamage == 0 || damage == 0) return;
|
||||
if (maxDamage == 0) return;
|
||||
|
||||
int damage = wrappedFirst.damage().orElse(0);
|
||||
|
||||
Key firstId = wrappedFirst.id();
|
||||
Optional<CustomItem<ItemStack>> optionalCustomTool = wrappedFirst.getCustomItem();
|
||||
@@ -548,20 +551,85 @@ public class RecipeEventListener implements Listener {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean hasResult = true;
|
||||
|
||||
int realDurabilityPerItem = (int) (repairItem.amount() + repairItem.percent() * maxDamage);
|
||||
int consumeMaxAmount = damage / realDurabilityPerItem + 1;
|
||||
int consumeMaxAmount = damage == 0 ? 0 : damage / realDurabilityPerItem + 1;
|
||||
int actualConsumedAmount = Math.min(consumeMaxAmount, wrappedSecond.count());
|
||||
int actualRepairAmount = actualConsumedAmount * realDurabilityPerItem;
|
||||
int damageAfter = Math.max(damage - actualRepairAmount, 0);
|
||||
wrappedFirst.damage(damageAfter);
|
||||
event.setResult(wrappedFirst.loadCopy());
|
||||
|
||||
String renameText;
|
||||
int maxRepairCost;
|
||||
if (VersionHelper.isVersionNewerThan1_21_2()) {
|
||||
AnvilView anvilView = event.getView();
|
||||
renameText = anvilView.getRenameText();
|
||||
maxRepairCost = anvilView.getMaximumRepairCost();
|
||||
} else {
|
||||
renameText = LegacyInventoryUtils.getRenameText(inventory);
|
||||
maxRepairCost = LegacyInventoryUtils.getMaxRepairCost(inventory);
|
||||
}
|
||||
|
||||
int repairCost = actualConsumedAmount;
|
||||
int repairPenalty = wrappedFirst.repairCost().orElse(0) + wrappedSecond.repairCost().orElse(0);
|
||||
|
||||
if (renameText != null && !renameText.isBlank()) {
|
||||
try {
|
||||
if (!renameText.equals(Reflections.method$Component$getString.invoke(ComponentUtils.jsonToMinecraft(wrappedFirst.hoverName().orElse(AdventureHelper.EMPTY_COMPONENT))))) {
|
||||
wrappedFirst.customName(AdventureHelper.componentToJson(Component.text(renameText)));
|
||||
repairCost += 1;
|
||||
} else if (repairCost == 0) {
|
||||
hasResult = false;
|
||||
System.out.println("1");
|
||||
}
|
||||
} catch (ReflectiveOperationException e) {
|
||||
plugin.logger().warn("Failed to get hover name", e);
|
||||
}
|
||||
} else if (VersionHelper.isVersionNewerThan1_20_5() && wrappedFirst.hasComponent(ComponentKeys.CUSTOM_NAME)) {
|
||||
repairCost += 1;
|
||||
wrappedFirst.customName(null);
|
||||
} else if (!VersionHelper.isVersionNewerThan1_20_5() && wrappedFirst.hasTag("display", "Name")) {
|
||||
repairCost += 1;
|
||||
wrappedFirst.customName(null);
|
||||
}
|
||||
|
||||
int finalCost = repairCost + repairPenalty;
|
||||
|
||||
if (VersionHelper.isVersionNewerThan1_21()) {
|
||||
AnvilView anvilView = event.getView();
|
||||
anvilView.setRepairCost(10);
|
||||
anvilView.setRepairCost(finalCost);
|
||||
anvilView.setRepairItemCountCost(actualConsumedAmount);
|
||||
} else {
|
||||
LegacyInventoryUtils.setRepairCost(inventory, 10, actualRepairAmount);
|
||||
LegacyInventoryUtils.setRepairCost(inventory, finalCost, actualRepairAmount);
|
||||
}
|
||||
|
||||
Player player;
|
||||
try {
|
||||
player = (Player) Reflections.method$InventoryView$getPlayer.invoke(VersionHelper.isVersionNewerThan1_21() ? event.getView() : LegacyInventoryUtils.getView(event));
|
||||
} catch (ReflectiveOperationException e) {
|
||||
plugin.logger().warn("Failed to get inventory viewer", e);
|
||||
return;
|
||||
}
|
||||
|
||||
if (finalCost >= maxRepairCost && !plugin.adapt(player).canInstabuild()) {
|
||||
hasResult = false;
|
||||
}
|
||||
|
||||
if (hasResult) {
|
||||
int afterPenalty = wrappedFirst.repairCost().orElse(0);
|
||||
int anotherPenalty = wrappedSecond.repairCost().orElse(0);
|
||||
if (afterPenalty < anotherPenalty) {
|
||||
afterPenalty = anotherPenalty;
|
||||
}
|
||||
afterPenalty = calculateIncreasedRepairCost(afterPenalty);
|
||||
wrappedFirst.repairCost(afterPenalty);
|
||||
event.setResult(wrappedFirst.loadCopy());
|
||||
}
|
||||
}
|
||||
|
||||
public static int calculateIncreasedRepairCost(int cost) {
|
||||
return (int) Math.min((long) cost * 2L + 1L, 2147483647L);
|
||||
}
|
||||
|
||||
// only handle repair items for the moment
|
||||
|
||||
@@ -10,6 +10,10 @@ public class ComponentUtils {
|
||||
|
||||
public static Object adventureToMinecraft(Component component) {
|
||||
String json = AdventureHelper.componentToJson(component);
|
||||
return jsonToMinecraft(json);
|
||||
}
|
||||
|
||||
public static Object jsonToMinecraft(String json) {
|
||||
if (VersionHelper.isVersionNewerThan1_20_5()) {
|
||||
try {
|
||||
return Reflections.method$Component$Serializer$fromJson.invoke(null, json, Reflections.instance$MinecraftRegistry);
|
||||
|
||||
@@ -72,6 +72,12 @@ public class Reflections {
|
||||
)
|
||||
);
|
||||
|
||||
public static final Method method$Component$getString = requireNonNull(
|
||||
ReflectionUtils.getMethod(
|
||||
clazz$Component, String.class, new String[]{"getString", "a"}
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$RandomSource = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("util.RandomSource")
|
||||
|
||||
Reference in New Issue
Block a user