mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2024-11-13 05:19:59 +00:00
Ignore enchantments/attributes on the original item
Turtle tools were not equippable, as we considered the stack enchanted due to the item's base attribute modifiers. We now only check the component patch for enchantments/attribute modifiers. This also removes the craftItem property of tools - this hasn't worked since we added support for enchanted tools! Fixes #1810
This commit is contained in:
parent
2226df7224
commit
94c864759d
@ -58,7 +58,7 @@ public abstract class TurtleUpgradeDataProvider extends UpgradeDataProvider<ITur
|
||||
*/
|
||||
public final class ToolBuilder {
|
||||
private final ResourceLocation id;
|
||||
private final Item toolItem;
|
||||
private final Item item;
|
||||
private Component adjective;
|
||||
private @Nullable Item craftingItem;
|
||||
private float damageMultiplier = TurtleToolSpec.DEFAULT_DAMAGE_MULTIPLIER;
|
||||
@ -66,15 +66,15 @@ public abstract class TurtleUpgradeDataProvider extends UpgradeDataProvider<ITur
|
||||
private boolean allowEnchantments = false;
|
||||
private TurtleToolDurability consumeDurability = TurtleToolDurability.NEVER;
|
||||
|
||||
ToolBuilder(ResourceLocation id, Item toolItem) {
|
||||
ToolBuilder(ResourceLocation id, Item item) {
|
||||
this.id = id;
|
||||
adjective = Component.translatable(UpgradeBase.getDefaultAdjective(id));
|
||||
this.toolItem = toolItem;
|
||||
this.item = item;
|
||||
craftingItem = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a custom adjective for this tool. By default this takes its adjective from the tool item.
|
||||
* Specify a custom adjective for this tool. By default this takes its adjective from the upgrade id.
|
||||
*
|
||||
* @param adjective The new adjective to use.
|
||||
* @return The tool builder, for further use.
|
||||
@ -84,18 +84,6 @@ public abstract class TurtleUpgradeDataProvider extends UpgradeDataProvider<ITur
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a custom item which is used to craft this upgrade. By default this is the same as the provided tool
|
||||
* item, but you may wish to override it.
|
||||
*
|
||||
* @param craftingItem The item used to craft this upgrade.
|
||||
* @return The tool builder, for further use.
|
||||
*/
|
||||
public ToolBuilder craftingItem(Item craftingItem) {
|
||||
this.craftingItem = craftingItem;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The amount of damage a swing of this tool will do. This is multiplied by {@link Attributes#ATTACK_DAMAGE} to
|
||||
* get the final damage.
|
||||
@ -152,8 +140,7 @@ public abstract class TurtleUpgradeDataProvider extends UpgradeDataProvider<ITur
|
||||
public void add(Consumer<Upgrade<ITurtleUpgrade>> add) {
|
||||
upgrade(id, ComputerCraftAPIService.get().createTurtleTool(new TurtleToolSpec(
|
||||
adjective,
|
||||
Optional.ofNullable(craftingItem),
|
||||
toolItem,
|
||||
item,
|
||||
damageMultiplier,
|
||||
allowEnchantments,
|
||||
consumeDurability,
|
||||
|
@ -22,8 +22,7 @@ import java.util.Optional;
|
||||
* The template for a turtle tool.
|
||||
*
|
||||
* @param adjective The adjective for this tool.
|
||||
* @param craftItem The item used to craft this tool.
|
||||
* @param toolItem The actual tool used.
|
||||
* @param item The tool used.
|
||||
* @param damageMultiplier The damage multiplier for this tool.
|
||||
* @param allowEnchantments Whether to allow enchantments.
|
||||
* @param consumeDurability When to consume durability.
|
||||
@ -31,8 +30,7 @@ import java.util.Optional;
|
||||
*/
|
||||
public record TurtleToolSpec(
|
||||
Component adjective,
|
||||
Optional<Item> craftItem,
|
||||
Item toolItem,
|
||||
Item item,
|
||||
float damageMultiplier,
|
||||
boolean allowEnchantments,
|
||||
TurtleToolDurability consumeDurability,
|
||||
@ -42,8 +40,7 @@ public record TurtleToolSpec(
|
||||
|
||||
public static final MapCodec<TurtleToolSpec> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
|
||||
ComponentSerialization.CODEC.fieldOf("adjective").forGetter(TurtleToolSpec::adjective),
|
||||
BuiltInRegistries.ITEM.byNameCodec().optionalFieldOf("craftingItem").forGetter(TurtleToolSpec::craftItem),
|
||||
BuiltInRegistries.ITEM.byNameCodec().fieldOf("item").forGetter(TurtleToolSpec::toolItem),
|
||||
BuiltInRegistries.ITEM.byNameCodec().fieldOf("item").forGetter(TurtleToolSpec::item),
|
||||
Codec.FLOAT.optionalFieldOf("damageMultiplier", DEFAULT_DAMAGE_MULTIPLIER).forGetter(TurtleToolSpec::damageMultiplier),
|
||||
Codec.BOOL.optionalFieldOf("allowEnchantments", false).forGetter(TurtleToolSpec::allowEnchantments),
|
||||
TurtleToolDurability.CODEC.optionalFieldOf("consumeDurability", TurtleToolDurability.NEVER).forGetter(TurtleToolSpec::consumeDurability),
|
||||
|
@ -11,6 +11,7 @@ import dan200.computercraft.api.turtle.ITurtleAccess;
|
||||
import dan200.computercraft.api.turtle.TurtleSide;
|
||||
import dan200.computercraft.shared.ModRegistry;
|
||||
import dan200.computercraft.shared.turtle.upgrades.TurtleModem;
|
||||
import dan200.computercraft.shared.util.DataComponentUtil;
|
||||
import net.minecraft.core.component.DataComponentPatch;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@ -23,8 +24,7 @@ import java.util.stream.Stream;
|
||||
public class TurtleModemModeller implements TurtleUpgradeModeller<TurtleModem> {
|
||||
@Override
|
||||
public TransformedModel getModel(TurtleModem upgrade, @Nullable ITurtleAccess turtle, TurtleSide side, DataComponentPatch data) {
|
||||
var component = data.get(ModRegistry.DataComponents.ON.get());
|
||||
var active = component != null && component.isPresent() && component.get();
|
||||
var active = DataComponentUtil.isPresent(data, ModRegistry.DataComponents.ON.get(), x -> x);
|
||||
|
||||
var models = upgrade.advanced() ? ModemModels.ADVANCED : ModemModels.NORMAL;
|
||||
return side == TurtleSide.LEFT
|
||||
|
@ -14,6 +14,7 @@ import dan200.computercraft.shared.platform.PlatformHelper;
|
||||
import dan200.computercraft.shared.turtle.TurtleUtil;
|
||||
import dan200.computercraft.shared.turtle.core.TurtlePlaceCommand;
|
||||
import dan200.computercraft.shared.turtle.core.TurtlePlayer;
|
||||
import dan200.computercraft.shared.util.DataComponentUtil;
|
||||
import dan200.computercraft.shared.util.DropConsumer;
|
||||
import dan200.computercraft.shared.util.WorldUtil;
|
||||
import net.minecraft.core.BlockPos;
|
||||
@ -49,37 +50,26 @@ public class TurtleTool extends AbstractTurtleUpgrade {
|
||||
private static final TurtleCommandResult INEFFECTIVE = TurtleCommandResult.failure("Cannot break block with this tool");
|
||||
|
||||
final TurtleToolSpec spec;
|
||||
final ItemStack item;
|
||||
final float damageMulitiplier;
|
||||
final boolean allowEnchantments;
|
||||
final TurtleToolDurability consumeDurability;
|
||||
final @Nullable TagKey<Block> breakable;
|
||||
|
||||
public TurtleTool(TurtleToolSpec spec) {
|
||||
super(TurtleUpgradeType.TOOL, spec.adjective(), new ItemStack(spec.craftItem().orElse(spec.toolItem())));
|
||||
super(TurtleUpgradeType.TOOL, spec.adjective(), new ItemStack(spec.item()));
|
||||
this.spec = spec;
|
||||
item = new ItemStack(spec.toolItem());
|
||||
this.damageMulitiplier = spec.damageMultiplier();
|
||||
this.allowEnchantments = spec.allowEnchantments();
|
||||
this.consumeDurability = spec.consumeDurability();
|
||||
this.breakable = spec.breakable().orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isItemSuitable(ItemStack stack) {
|
||||
if (consumeDurability == TurtleToolDurability.NEVER && stack.isDamaged()) return false;
|
||||
if (!allowEnchantments && isEnchanted(stack)) return false;
|
||||
if (spec.consumeDurability() == TurtleToolDurability.NEVER && stack.isDamaged()) return false;
|
||||
if (!spec.allowEnchantments() && isEnchanted(stack)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean isEnchanted(ItemStack stack) {
|
||||
var enchantments = stack.get(DataComponents.ENCHANTMENTS);
|
||||
if (enchantments != null && !enchantments.isEmpty()) return true;
|
||||
|
||||
var modifiers = stack.get(DataComponents.ATTRIBUTE_MODIFIERS);
|
||||
if (modifiers != null && !modifiers.modifiers().isEmpty()) return true;
|
||||
|
||||
return false;
|
||||
// Only check whether the stack has been modified. We ignore components on the original item.
|
||||
var patch = stack.getComponentsPatch();
|
||||
return DataComponentUtil.isPresent(patch, DataComponents.ENCHANTMENTS, x -> !x.isEmpty())
|
||||
|| DataComponentUtil.isPresent(patch, DataComponents.ATTRIBUTE_MODIFIERS, x -> !x.modifiers().isEmpty());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -100,9 +90,7 @@ public class TurtleTool extends AbstractTurtleUpgrade {
|
||||
}
|
||||
|
||||
private void setToolStack(ITurtleAccess turtle, TurtleSide side, ItemStack oldStack, ItemStack stack) {
|
||||
var upgradeData = turtle.getUpgradeData(side);
|
||||
|
||||
var useDurability = switch (consumeDurability) {
|
||||
var useDurability = switch (spec.consumeDurability()) {
|
||||
case NEVER -> false;
|
||||
case WHEN_ENCHANTED -> isEnchanted(oldStack);
|
||||
case ALWAYS -> true;
|
||||
@ -116,7 +104,7 @@ public class TurtleTool extends AbstractTurtleUpgrade {
|
||||
}
|
||||
|
||||
// If the tool has changed, no clue what's going on.
|
||||
if (stack.getItem() != item.getItem()) return;
|
||||
if (stack.getItem() != spec.item()) return;
|
||||
|
||||
turtle.setUpgradeData(side, stack.getComponentsPatch());
|
||||
}
|
||||
@ -218,7 +206,7 @@ public class TurtleTool extends AbstractTurtleUpgrade {
|
||||
* @see Player#attack(Entity)
|
||||
*/
|
||||
private boolean attack(ServerPlayer player, Direction direction, Entity entity) {
|
||||
var baseDamage = (float) player.getAttributeValue(Attributes.ATTACK_DAMAGE) * damageMulitiplier;
|
||||
var baseDamage = (float) player.getAttributeValue(Attributes.ATTACK_DAMAGE) * spec.damageMultiplier();
|
||||
var bonusDamage = EnchantmentHelper.getDamageBonus(player.getItemInHand(InteractionHand.MAIN_HAND), entity.getType());
|
||||
var damage = baseDamage + bonusDamage;
|
||||
if (damage <= 0) return false;
|
||||
|
@ -5,6 +5,7 @@
|
||||
package dan200.computercraft.shared.util;
|
||||
|
||||
import net.minecraft.core.component.DataComponentHolder;
|
||||
import net.minecraft.core.component.DataComponentPatch;
|
||||
import net.minecraft.core.component.DataComponentType;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
import net.minecraft.network.chat.Component;
|
||||
@ -13,6 +14,7 @@ import net.minecraft.world.level.ItemLike;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Utilities for working with {@linkplain DataComponentType data components}.
|
||||
@ -43,4 +45,18 @@ public class DataComponentUtil {
|
||||
public static <T> ItemStack createStack(ItemLike item, DataComponentType<T> type, @Nullable T value) {
|
||||
return set(new ItemStack(item), type, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check a component is present in a {@link DataComponentPatch} and matches the supplied predicate.
|
||||
*
|
||||
* @param patch The current component patch.
|
||||
* @param component The component type.
|
||||
* @param check The predicate to check against.
|
||||
* @param <T> The type of component.
|
||||
* @return Whether the component is present in this patch, and matches the supplied predicate.
|
||||
*/
|
||||
public static <T> boolean isPresent(DataComponentPatch patch, DataComponentType<T> component, Predicate<T> check) {
|
||||
var value = patch.get(component);
|
||||
return value != null && value.isPresent() && check.test(value.get());
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user