From 08dc08b5a3e86f18527cbbdcf3524794822af15a Mon Sep 17 00:00:00 2001 From: Jonathan Coates Date: Sun, 9 Mar 2025 13:39:45 +0000 Subject: [PATCH] Replace appendHoverText with component-based tooltips MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have several items (e.g. ComputerItem), which only exist for their custom tooltip implementation. We remove these, and replace them vanilla-style component-based tooltips (TooltipProvider). The implementation here is a little janky — as the vanilla list of components is hard-coded, and neither mod loader offers a way to extend it. For now we just use the generic mod-loader tooltip hook — this probably would be easier with a mixin, but let's do things Properly. It would be nice to fully remove DiskItem (we only keep this around for doesSneakBypassUse), but that can be a future task. --- .../computercraft/client/ClientRegistry.java | 3 +- .../integration/jei/JEIComputerCraft.java | 4 +- .../computercraft/shared/CommonHooks.java | 48 +++++++++++++++++-- .../computercraft/shared/ModRegistry.java | 29 +++-------- .../computer/blocks/CommandComputerBlock.java | 1 - .../computer/items/CommandComputerItem.java | 29 ----------- .../shared/computer/items/ComputerItem.java | 33 ------------- .../shared/media/MountMedia.java | 6 +-- .../shared/media/items/DiskItem.java | 36 +++----------- .../shared/media/items/PrintoutData.java | 12 ++++- .../shared/media/items/PrintoutItem.java | 9 ---- .../shared/media/items/TreasureDisk.java | 20 ++++++-- .../shared/media/items/TreasureDiskItem.java | 32 ------------- .../shared/media/items/TreasureDiskMedia.java | 2 +- .../diskdrive/DiskDrivePeripheral.java | 6 +-- .../pocket/items/PocketComputerItem.java | 15 ------ .../shared/turtle/items/TurtleItem.java | 4 +- .../shared/util/NonNegativeId.java | 8 ++++ .../client/ComputerCraftClient.java | 4 ++ .../shared/FabricCommonHooks.java | 3 +- .../shared/ForgeCommonHooks.java | 6 +++ 21 files changed, 114 insertions(+), 196 deletions(-) delete mode 100644 projects/common/src/main/java/dan200/computercraft/shared/computer/items/CommandComputerItem.java delete mode 100644 projects/common/src/main/java/dan200/computercraft/shared/computer/items/ComputerItem.java delete mode 100644 projects/common/src/main/java/dan200/computercraft/shared/media/items/TreasureDiskItem.java diff --git a/projects/common/src/client/java/dan200/computercraft/client/ClientRegistry.java b/projects/common/src/client/java/dan200/computercraft/client/ClientRegistry.java index 5f3888823..8997df737 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/ClientRegistry.java +++ b/projects/common/src/client/java/dan200/computercraft/client/ClientRegistry.java @@ -25,7 +25,6 @@ import dan200.computercraft.shared.command.CommandComputerCraft; import dan200.computercraft.shared.computer.core.ComputerState; import dan200.computercraft.shared.computer.core.ServerContext; import dan200.computercraft.shared.computer.inventory.AbstractComputerMenu; -import dan200.computercraft.shared.media.items.DiskItem; import dan200.computercraft.shared.turtle.TurtleOverlay; import net.minecraft.Util; import net.minecraft.client.Minecraft; @@ -164,7 +163,7 @@ public final class ClientRegistry { public static void registerItemColours(BiConsumer register) { register.accept( - (stack, layer) -> layer == 1 ? DiskItem.getColour(stack) : -1, + (stack, layer) -> layer == 1 ? DyedItemColor.getOrDefault(stack, Colour.WHITE.getARGB()) : -1, ModRegistry.Items.DISK.get() ); diff --git a/projects/common/src/client/java/dan200/computercraft/client/integration/jei/JEIComputerCraft.java b/projects/common/src/client/java/dan200/computercraft/client/integration/jei/JEIComputerCraft.java index a0e63f7cb..2f4c2e5b4 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/integration/jei/JEIComputerCraft.java +++ b/projects/common/src/client/java/dan200/computercraft/client/integration/jei/JEIComputerCraft.java @@ -8,7 +8,6 @@ import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.api.turtle.TurtleSide; import dan200.computercraft.shared.ModRegistry; import dan200.computercraft.shared.integration.RecipeModHelpers; -import dan200.computercraft.shared.media.items.DiskItem; import dan200.computercraft.shared.pocket.items.PocketComputerItem; import dan200.computercraft.shared.turtle.items.TurtleItem; import mezz.jei.api.IModPlugin; @@ -23,6 +22,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.core.RegistryAccess; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.component.DyedItemColor; import java.util.List; @@ -100,7 +100,7 @@ public class JEIComputerCraft implements IModPlugin { /** * Distinguishes disks by colour. */ - private static final IIngredientSubtypeInterpreter diskSubtype = (stack, ctx) -> Integer.toString(DiskItem.getColour(stack)); + private static final IIngredientSubtypeInterpreter diskSubtype = (stack, ctx) -> Integer.toString(DyedItemColor.getOrDefault(stack, -1)); private static RegistryAccess getRegistryAccess() { return Minecraft.getInstance().level.registryAccess(); diff --git a/projects/common/src/main/java/dan200/computercraft/shared/CommonHooks.java b/projects/common/src/main/java/dan200/computercraft/shared/CommonHooks.java index 8c4e98aca..9cf00d88c 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/CommonHooks.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/CommonHooks.java @@ -13,7 +13,10 @@ import dan200.computercraft.shared.lectern.CustomLecternBlock; import dan200.computercraft.shared.peripheral.monitor.MonitorWatcher; import dan200.computercraft.shared.util.DropConsumer; import dan200.computercraft.shared.util.TickScheduler; +import net.minecraft.core.component.DataComponentType; +import net.minecraft.core.component.DataComponents; import net.minecraft.core.registries.Registries; +import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; @@ -25,9 +28,8 @@ import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.CreativeModeTab; -import net.minecraft.world.item.CreativeModeTabs; -import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.*; +import net.minecraft.world.item.component.TooltipProvider; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.LecternBlock; @@ -40,8 +42,10 @@ import net.minecraft.world.level.storage.loot.providers.number.ConstantValue; import net.minecraft.world.phys.BlockHitResult; import org.jspecify.annotations.Nullable; +import java.util.List; import java.util.Set; import java.util.function.BiConsumer; +import java.util.function.Consumer; /** * Event listeners for server/common code. @@ -163,4 +167,42 @@ public final class CommonHooks { out.accept(ModRegistry.Items.COMPUTER_COMMAND.get()); } } + + public static void onItemTooltip(ItemStack stack, Item.TooltipContext context, TooltipFlag flags, List out) { + var appender = new TooltipAppender(out); + addToTooltip(stack, ModRegistry.DataComponents.PRINTOUT.get(), context, appender, flags); + addToTooltip(stack, ModRegistry.DataComponents.TREASURE_DISK.get(), context, appender, flags); + + // Disk and computer IDs require some conditional logic, so we don't bother using TooltipProvider. + + var diskId = stack.get(ModRegistry.DataComponents.DISK_ID.get()); + if (diskId != null && flags.isAdvanced()) diskId.addToTooltip("gui.computercraft.tooltip.disk_id", appender); + + var computerId = stack.get(ModRegistry.DataComponents.COMPUTER_ID.get()); + if (computerId != null && (flags.isAdvanced() || !stack.has(DataComponents.CUSTOM_NAME))) { + computerId.addToTooltip("gui.computercraft.tooltip.computer_id", appender); + } + } + + /** + * Inserts additional tooltip items directly after the custom name, rather than at the very end. + */ + private static final class TooltipAppender implements Consumer { + private final List out; + private int index = 1; + + private TooltipAppender(List out) { + this.out = out; + } + + @Override + public void accept(Component component) { + out.add(index++, component); + } + } + + private static void addToTooltip(ItemStack stack, DataComponentType component, Item.TooltipContext context, Consumer out, TooltipFlag flags) { + var provider = stack.get(component); + if (provider != null) provider.addToTooltip(context, out, flags); + } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/ModRegistry.java b/projects/common/src/main/java/dan200/computercraft/shared/ModRegistry.java index 12e48d1c2..e941e8a37 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/ModRegistry.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/ModRegistry.java @@ -35,8 +35,6 @@ import dan200.computercraft.shared.computer.blocks.ComputerBlockEntity; import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.computer.core.ServerComputer; import dan200.computercraft.shared.computer.inventory.ComputerMenuWithoutInventory; -import dan200.computercraft.shared.computer.items.ComputerItem; -import dan200.computercraft.shared.computer.items.CommandComputerItem; import dan200.computercraft.shared.computer.items.ServerComputerReference; import dan200.computercraft.shared.config.Config; import dan200.computercraft.shared.data.BlockNamedEntityLootCondition; @@ -112,10 +110,7 @@ import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; import net.minecraft.world.flag.FeatureFlags; import net.minecraft.world.inventory.MenuType; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.CreativeModeTab; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.*; import net.minecraft.world.item.component.DyedItemColor; import net.minecraft.world.item.crafting.CustomRecipe; import net.minecraft.world.item.crafting.Recipe; @@ -262,9 +257,9 @@ public final class ModRegistry { return REGISTRY.register(parent.id().getPath(), () -> supplier.apply(parent.get(), properties())); } - public static final RegistryEntry COMPUTER_NORMAL = ofBlock(Blocks.COMPUTER_NORMAL, ComputerItem::new); - public static final RegistryEntry COMPUTER_ADVANCED = ofBlock(Blocks.COMPUTER_ADVANCED, ComputerItem::new); - public static final RegistryEntry COMPUTER_COMMAND = ofBlock(Blocks.COMPUTER_COMMAND, CommandComputerItem::new); + public static final RegistryEntry COMPUTER_NORMAL = ofBlock(Blocks.COMPUTER_NORMAL, BlockItem::new); + public static final RegistryEntry COMPUTER_ADVANCED = ofBlock(Blocks.COMPUTER_ADVANCED, BlockItem::new); + public static final RegistryEntry COMPUTER_COMMAND = ofBlock(Blocks.COMPUTER_COMMAND, GameMasterBlockItem::new); public static final RegistryEntry POCKET_COMPUTER_NORMAL = REGISTRY.register("pocket_computer_normal", () -> new PocketComputerItem(properties().stacksTo(1), ComputerFamily.NORMAL)); @@ -276,8 +271,8 @@ public final class ModRegistry { public static final RegistryEntry DISK = REGISTRY.register("disk", () -> new DiskItem(properties().stacksTo(1))); - public static final RegistryEntry TREASURE_DISK = - REGISTRY.register("treasure_disk", () -> new TreasureDiskItem(properties().stacksTo(1))); + public static final RegistryEntry TREASURE_DISK = + REGISTRY.register("treasure_disk", () -> new DiskItem(properties().stacksTo(1))); private static Item.Properties printoutProperties() { return properties().stacksTo(1).component(DataComponents.PRINTOUT.get(), PrintoutData.EMPTY); @@ -315,9 +310,6 @@ public final class ModRegistry { /** * The id of a computer. - * - * @see ComputerItem - * @see PocketComputerItem */ public static final RegistryEntry> COMPUTER_ID = register("computer_id", b -> b .persistent(NonNegativeId.CODEC).networkSynchronized(NonNegativeId.STREAM_CODEC) @@ -325,10 +317,6 @@ public final class ModRegistry { /** * The storage capacity of a computer or disk. - * - * @see ComputerItem - * @see PocketComputerItem - * @see DiskItem */ public static final RegistryEntry> STORAGE_CAPACITY = register("storage_capacity", b -> b .persistent(StorageCapacity.CODEC).networkSynchronized(StorageCapacity.STREAM_CODEC) @@ -397,9 +385,6 @@ public final class ModRegistry { /** * Information about a treasure disk's mount. - * - * @see TreasureDiskItem - * @see TreasureDisk */ public static final RegistryEntry> TREASURE_DISK = register("treasure_disk", b -> b .persistent(TreasureDisk.CODEC).networkSynchronized(TreasureDisk.STREAM_CODEC) @@ -407,8 +392,6 @@ public final class ModRegistry { /** * The id of a disk. - * - * @see DiskItem */ public static final RegistryEntry> DISK_ID = register("disk_id", b -> b .persistent(NonNegativeId.CODEC).networkSynchronized(NonNegativeId.STREAM_CODEC) diff --git a/projects/common/src/main/java/dan200/computercraft/shared/computer/blocks/CommandComputerBlock.java b/projects/common/src/main/java/dan200/computercraft/shared/computer/blocks/CommandComputerBlock.java index fbbaea72e..7e2af55f6 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/computer/blocks/CommandComputerBlock.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/computer/blocks/CommandComputerBlock.java @@ -16,7 +16,6 @@ import net.minecraft.world.level.block.entity.BlockEntityType; * permission. * * @param The type of the computer block entity. - * @see dan200.computercraft.shared.computer.items.CommandComputerItem */ public class CommandComputerBlock extends ComputerBlock implements GameMasterBlock { private static final MapCodec> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( diff --git a/projects/common/src/main/java/dan200/computercraft/shared/computer/items/CommandComputerItem.java b/projects/common/src/main/java/dan200/computercraft/shared/computer/items/CommandComputerItem.java deleted file mode 100644 index c2478a0bb..000000000 --- a/projects/common/src/main/java/dan200/computercraft/shared/computer/items/CommandComputerItem.java +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-FileCopyrightText: 2023 The CC: Tweaked Developers -// -// SPDX-License-Identifier: MPL-2.0 - -package dan200.computercraft.shared.computer.items; - -import dan200.computercraft.shared.computer.blocks.ComputerBlock; -import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.level.block.state.BlockState; -import org.jspecify.annotations.Nullable; - -/** - * A {@link ComputerItem} which prevents players placing it without permission. - * - * @see net.minecraft.world.item.GameMasterBlockItem - * @see dan200.computercraft.shared.computer.blocks.CommandComputerBlock - */ -public class CommandComputerItem extends ComputerItem { - public CommandComputerItem(ComputerBlock block, Properties settings) { - super(block, settings); - } - - @Override - protected @Nullable BlockState getPlacementState(BlockPlaceContext context) { - // Prohibit players placing this block in survival or when not opped. - var player = context.getPlayer(); - return player != null && !player.canUseGameMasterBlocks() ? null : super.getPlacementState(context); - } -} diff --git a/projects/common/src/main/java/dan200/computercraft/shared/computer/items/ComputerItem.java b/projects/common/src/main/java/dan200/computercraft/shared/computer/items/ComputerItem.java deleted file mode 100644 index ecf1a3b27..000000000 --- a/projects/common/src/main/java/dan200/computercraft/shared/computer/items/ComputerItem.java +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission. -// -// SPDX-License-Identifier: LicenseRef-CCPL - -package dan200.computercraft.shared.computer.items; - -import dan200.computercraft.shared.ModRegistry; -import dan200.computercraft.shared.computer.blocks.AbstractComputerBlock; -import net.minecraft.ChatFormatting; -import net.minecraft.core.component.DataComponents; -import net.minecraft.network.chat.Component; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.TooltipFlag; - -import java.util.List; - -public class ComputerItem extends BlockItem { - public ComputerItem(AbstractComputerBlock block, Properties settings) { - super(block, settings); - } - - @Override - public void appendHoverText(ItemStack stack, TooltipContext context, List list, TooltipFlag options) { - if (options.isAdvanced() || !stack.has(DataComponents.CUSTOM_NAME)) { - var id = stack.get(ModRegistry.DataComponents.COMPUTER_ID.get()); - if (id != null) { - list.add(Component.translatable("gui.computercraft.tooltip.computer_id", id.id()) - .withStyle(ChatFormatting.GRAY)); - } - } - } -} diff --git a/projects/common/src/main/java/dan200/computercraft/shared/media/MountMedia.java b/projects/common/src/main/java/dan200/computercraft/shared/media/MountMedia.java index 0e5a6bb58..677d61242 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/media/MountMedia.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/media/MountMedia.java @@ -8,9 +8,7 @@ import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.api.filesystem.Mount; import dan200.computercraft.api.media.IMedia; import dan200.computercraft.shared.ModRegistry; -import dan200.computercraft.shared.computer.items.ComputerItem; import dan200.computercraft.shared.config.ConfigSpec; -import dan200.computercraft.shared.media.items.DiskItem; import dan200.computercraft.shared.util.DataComponentUtil; import dan200.computercraft.shared.util.NonNegativeId; import dan200.computercraft.shared.util.StorageCapacity; @@ -27,12 +25,12 @@ import java.util.function.Supplier; */ public final class MountMedia implements IMedia { /** - * A {@link MountMedia} implementation for {@linkplain ComputerItem computers}. + * A {@link MountMedia} implementation for {@linkplain ModRegistry.DataComponents#COMPUTER_ID computers}. */ public static final IMedia COMPUTER = new MountMedia("computer", ModRegistry.DataComponents.COMPUTER_ID, false, ConfigSpec.computerSpaceLimit); /** - * A {@link MountMedia} implementation for {@linkplain DiskItem disks}. + * A {@link MountMedia} implementation for {@linkplain ModRegistry.Items#DISK disks}. */ public static final IMedia DISK = new MountMedia("disk", ModRegistry.DataComponents.DISK_ID, true, ConfigSpec.floppySpaceLimit); diff --git a/projects/common/src/main/java/dan200/computercraft/shared/media/items/DiskItem.java b/projects/common/src/main/java/dan200/computercraft/shared/media/items/DiskItem.java index aa3bd8735..4097410a2 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/media/items/DiskItem.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/media/items/DiskItem.java @@ -1,51 +1,27 @@ -// Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission. +// SPDX-FileCopyrightText: 2025 The CC: Tweaked Developers // -// SPDX-License-Identifier: LicenseRef-CCPL +// SPDX-License-Identifier: MPL-2.0 package dan200.computercraft.shared.media.items; import dan200.computercraft.annotations.ForgeOverride; -import dan200.computercraft.core.util.Colour; -import dan200.computercraft.shared.ModRegistry; -import dan200.computercraft.shared.util.NonNegativeId; -import net.minecraft.ChatFormatting; +import dan200.computercraft.shared.peripheral.diskdrive.DiskDriveBlock; import net.minecraft.core.BlockPos; -import net.minecraft.network.chat.Component; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.TooltipFlag; -import net.minecraft.world.item.component.DyedItemColor; import net.minecraft.world.level.LevelReader; -import java.util.List; - +/** + * An item that can be shift-right-clicked into a {@link DiskDriveBlock}. + */ public class DiskItem extends Item { public DiskItem(Properties settings) { super(settings); } - @Override - public void appendHoverText(ItemStack stack, TooltipContext context, List list, TooltipFlag options) { - if (options.isAdvanced()) { - var id = stack.get(ModRegistry.DataComponents.DISK_ID.get()); - if (id != null) { - list.add(Component.translatable("gui.computercraft.tooltip.disk_id", id.id()) - .withStyle(ChatFormatting.GRAY)); - } - } - } - @ForgeOverride public boolean doesSneakBypassUse(ItemStack stack, LevelReader world, BlockPos pos, Player player) { return true; } - - public static int getDiskID(ItemStack stack) { - return NonNegativeId.getId(stack.get(ModRegistry.DataComponents.DISK_ID.get())); - } - - public static int getColour(ItemStack stack) { - return DyedItemColor.getOrDefault(stack, Colour.WHITE.getARGB()); - } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/media/items/PrintoutData.java b/projects/common/src/main/java/dan200/computercraft/shared/media/items/PrintoutData.java index 0b93ab63f..bb650af33 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/media/items/PrintoutData.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/media/items/PrintoutData.java @@ -12,11 +12,16 @@ import dan200.computercraft.core.terminal.Terminal; import dan200.computercraft.shared.ModRegistry; import io.netty.buffer.ByteBuf; import net.minecraft.core.component.DataComponentHolder; +import net.minecraft.network.chat.Component; import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.item.component.TooltipProvider; import java.util.Arrays; import java.util.List; +import java.util.function.Consumer; import java.util.stream.Stream; /** @@ -27,7 +32,7 @@ import java.util.stream.Stream; * @see PrintoutItem * @see dan200.computercraft.shared.ModRegistry.DataComponents#PRINTOUT */ -public record PrintoutData(String title, List lines) implements PrintoutContents { +public record PrintoutData(String title, List lines) implements PrintoutContents, TooltipProvider { public static final int LINE_LENGTH = 25; public static final int LINES_PER_PAGE = 21; public static final int MAX_PAGES = 16; @@ -71,6 +76,11 @@ public record PrintoutData(String title, List lines) implements PrintoutCo PrintoutData::new ); + @Override + public void addToTooltip(Item.TooltipContext context, Consumer out, TooltipFlag flag) { + if (!title().isEmpty()) out.accept(Component.literal(title())); + } + /** * A single line on our printed pages. * diff --git a/projects/common/src/main/java/dan200/computercraft/shared/media/items/PrintoutItem.java b/projects/common/src/main/java/dan200/computercraft/shared/media/items/PrintoutItem.java index a5a7e2a79..19ea92a02 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/media/items/PrintoutItem.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/media/items/PrintoutItem.java @@ -14,22 +14,13 @@ import net.minecraft.world.SimpleMenuProvider; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.level.Level; -import java.util.List; - public class PrintoutItem extends Item { public PrintoutItem(Properties settings) { super(settings); } - @Override - public void appendHoverText(ItemStack stack, TooltipContext context, List list, TooltipFlag options) { - var title = PrintoutData.getOrEmpty(stack).title(); - if (!title.isEmpty()) list.add(Component.literal(title)); - } - @Override public InteractionResultHolder use(Level world, Player player, InteractionHand hand) { var stack = player.getItemInHand(hand); diff --git a/projects/common/src/main/java/dan200/computercraft/shared/media/items/TreasureDisk.java b/projects/common/src/main/java/dan200/computercraft/shared/media/items/TreasureDisk.java index 7f91c0f64..40af4d094 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/media/items/TreasureDisk.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/media/items/TreasureDisk.java @@ -9,17 +9,25 @@ import com.mojang.serialization.codecs.RecordCodecBuilder; import dan200.computercraft.shared.ModRegistry; import net.minecraft.core.component.DataComponentHolder; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.chat.Component; import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.item.component.TooltipProvider; + +import java.util.function.Consumer; /** - * Stores information about a {@linkplain TreasureDiskItem treasure disk's} mount. + * Stores information about a {@linkplain ModRegistry.Items#TREASURE_DISK treasure disk's} mount. * * @param name The name/title of the disk. * @param path The subpath to the resource * @see ModRegistry.DataComponents#TREASURE_DISK */ -public record TreasureDisk(String name, String path) { +public record TreasureDisk(String name, String path) implements TooltipProvider { + public static final TreasureDisk UNDEFINED = new TreasureDisk("'missingno' by how did you get this anyway?", "undefined"); + public static final Codec CODEC = RecordCodecBuilder.create(i -> i.group( Codec.STRING.fieldOf("name").forGetter(TreasureDisk::name), Codec.STRING.fieldOf("path").forGetter(TreasureDisk::path) @@ -32,7 +40,11 @@ public record TreasureDisk(String name, String path) { ); public static String getTitle(DataComponentHolder holder) { - var nbt = holder.get(ModRegistry.DataComponents.TREASURE_DISK.get()); - return nbt != null ? nbt.name() : "'missingno' by how did you get this anyway?"; + return holder.getOrDefault(ModRegistry.DataComponents.TREASURE_DISK.get(), UNDEFINED).name(); + } + + @Override + public void addToTooltip(Item.TooltipContext context, Consumer out, TooltipFlag flags) { + out.accept(Component.literal(name())); } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/media/items/TreasureDiskItem.java b/projects/common/src/main/java/dan200/computercraft/shared/media/items/TreasureDiskItem.java deleted file mode 100644 index bfc630921..000000000 --- a/projects/common/src/main/java/dan200/computercraft/shared/media/items/TreasureDiskItem.java +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission. -// -// SPDX-License-Identifier: LicenseRef-CCPL - -package dan200.computercraft.shared.media.items; - -import dan200.computercraft.annotations.ForgeOverride; -import net.minecraft.core.BlockPos; -import net.minecraft.network.chat.Component; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.TooltipFlag; -import net.minecraft.world.level.LevelReader; - -import java.util.List; - -public class TreasureDiskItem extends Item { - public TreasureDiskItem(Properties settings) { - super(settings); - } - - @Override - public void appendHoverText(ItemStack stack, TooltipContext context, List list, TooltipFlag tooltipOptions) { - list.add(Component.literal(TreasureDisk.getTitle(stack))); - } - - @ForgeOverride - public boolean doesSneakBypassUse(ItemStack stack, LevelReader world, BlockPos pos, Player player) { - return true; - } -} diff --git a/projects/common/src/main/java/dan200/computercraft/shared/media/items/TreasureDiskMedia.java b/projects/common/src/main/java/dan200/computercraft/shared/media/items/TreasureDiskMedia.java index 30c3d5e07..6dd8f57af 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/media/items/TreasureDiskMedia.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/media/items/TreasureDiskMedia.java @@ -17,7 +17,7 @@ import org.jspecify.annotations.Nullable; import java.io.IOException; /** - * An {@link IMedia} instance for {@linkplain TreasureDiskItem treasure disks}. + * An {@link IMedia} instance for {@linkplain ModRegistry.Items#TREASURE_DISK treasure disks}. */ public final class TreasureDiskMedia implements IMedia { public static final IMedia INSTANCE = new TreasureDiskMedia(); diff --git a/projects/common/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/DiskDrivePeripheral.java b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/DiskDrivePeripheral.java index 0725fa041..7826c045b 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/DiskDrivePeripheral.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/DiskDrivePeripheral.java @@ -9,7 +9,7 @@ import dan200.computercraft.api.lua.LuaFunction; import dan200.computercraft.api.peripheral.IComputerAccess; import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.core.util.StringUtil; -import dan200.computercraft.shared.media.items.DiskItem; +import dan200.computercraft.shared.ModRegistry; import org.jspecify.annotations.Nullable; import java.util.Optional; @@ -170,8 +170,8 @@ public class DiskDrivePeripheral implements IPeripheral { */ @LuaFunction public final @Nullable Object @Nullable [] getDiskID() { - var disk = diskDrive.getMedia().stack(); - return disk.getItem() instanceof DiskItem ? new Object[]{ DiskItem.getDiskID(disk) } : null; + var id = diskDrive.getMedia().stack().get(ModRegistry.DataComponents.DISK_ID.get()); + return id != null ? new Object[]{ id.id() } : null; } @Override diff --git a/projects/common/src/main/java/dan200/computercraft/shared/pocket/items/PocketComputerItem.java b/projects/common/src/main/java/dan200/computercraft/shared/pocket/items/PocketComputerItem.java index 4e3690182..514c1e1f2 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/pocket/items/PocketComputerItem.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/pocket/items/PocketComputerItem.java @@ -23,7 +23,6 @@ import dan200.computercraft.shared.pocket.core.PocketBrain; import dan200.computercraft.shared.pocket.core.PocketHolder; import dan200.computercraft.shared.pocket.core.PocketServerComputer; import dan200.computercraft.shared.util.*; -import net.minecraft.ChatFormatting; import net.minecraft.network.chat.Component; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; @@ -36,11 +35,9 @@ import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.level.Level; import org.jspecify.annotations.Nullable; -import java.util.List; import java.util.Objects; public class PocketComputerItem extends Item { @@ -184,18 +181,6 @@ public class PocketComputerItem extends Item { } } - - @Override - public void appendHoverText(ItemStack stack, TooltipContext context, List list, TooltipFlag flag) { - if (flag.isAdvanced() || getLabel(stack) == null) { - var id = stack.get(ModRegistry.DataComponents.COMPUTER_ID.get()); - if (id != null) { - list.add(Component.translatable("gui.computercraft.tooltip.computer_id", id.id()) - .withStyle(ChatFormatting.GRAY)); - } - } - } - @Nullable @ForgeOverride public String getCreatorModId(ItemStack stack) { diff --git a/projects/common/src/main/java/dan200/computercraft/shared/turtle/items/TurtleItem.java b/projects/common/src/main/java/dan200/computercraft/shared/turtle/items/TurtleItem.java index 9ba36d168..d8bdae44a 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/turtle/items/TurtleItem.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/turtle/items/TurtleItem.java @@ -11,18 +11,18 @@ import dan200.computercraft.api.turtle.TurtleSide; import dan200.computercraft.api.upgrades.UpgradeData; import dan200.computercraft.impl.TurtleUpgrades; import dan200.computercraft.shared.ModRegistry; -import dan200.computercraft.shared.computer.items.ComputerItem; import dan200.computercraft.shared.turtle.TurtleOverlay; import dan200.computercraft.shared.turtle.blocks.TurtleBlock; import net.minecraft.core.cauldron.CauldronInteraction; import net.minecraft.core.component.DataComponents; import net.minecraft.network.chat.Component; import net.minecraft.world.ItemInteractionResult; +import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.LayeredCauldronBlock; import org.jspecify.annotations.Nullable; -public class TurtleItem extends ComputerItem { +public class TurtleItem extends BlockItem { public TurtleItem(TurtleBlock block, Properties settings) { super(block, settings); } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/util/NonNegativeId.java b/projects/common/src/main/java/dan200/computercraft/shared/util/NonNegativeId.java index 183dd3f92..db8d19746 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/util/NonNegativeId.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/util/NonNegativeId.java @@ -7,7 +7,9 @@ package dan200.computercraft.shared.util; import com.mojang.serialization.Codec; import dan200.computercraft.api.ComputerCraftAPI; import io.netty.buffer.ByteBuf; +import net.minecraft.ChatFormatting; import net.minecraft.core.component.DataComponentType; +import net.minecraft.network.chat.Component; import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; import net.minecraft.server.MinecraftServer; @@ -15,6 +17,8 @@ import net.minecraft.util.ExtraCodecs; import net.minecraft.world.item.ItemStack; import org.jspecify.annotations.Nullable; +import java.util.function.Consumer; + /** * A non-negative integer id, used for computer and disk ids. * @@ -47,4 +51,8 @@ public record NonNegativeId(int id) { stack.set(component, new NonNegativeId(diskID)); return diskID; } + + public void addToTooltip(String translation, Consumer out) { + out.accept(Component.translatable(translation, id()).withStyle(ChatFormatting.GRAY)); + } } diff --git a/projects/fabric/src/client/java/dan200/computercraft/client/ComputerCraftClient.java b/projects/fabric/src/client/java/dan200/computercraft/client/ComputerCraftClient.java index 224ac9bc5..aa6e5940b 100644 --- a/projects/fabric/src/client/java/dan200/computercraft/client/ComputerCraftClient.java +++ b/projects/fabric/src/client/java/dan200/computercraft/client/ComputerCraftClient.java @@ -9,6 +9,7 @@ import dan200.computercraft.api.client.FabricComputerCraftAPIClient; import dan200.computercraft.client.model.CustomModelLoader; import dan200.computercraft.core.util.Nullability; import dan200.computercraft.impl.Services; +import dan200.computercraft.shared.CommonHooks; import dan200.computercraft.shared.ModRegistry; import dan200.computercraft.shared.config.ConfigSpec; import dan200.computercraft.shared.network.NetworkMessages; @@ -19,6 +20,7 @@ import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap; import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.fabricmc.fabric.api.client.item.v1.ItemTooltipCallback; import net.fabricmc.fabric.api.client.model.loading.v1.PreparableModelLoadingPlugin; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; import net.fabricmc.fabric.api.client.rendering.v1.ColorProviderRegistry; @@ -92,6 +94,8 @@ public class ComputerCraftClient { (dispatcher, registryAccess) -> ClientRegistry.registerClientCommands(dispatcher, FabricClientCommandSource::sendError) ); + ItemTooltipCallback.EVENT.register(CommonHooks::onItemTooltip); + ((FabricConfigFile) ConfigSpec.clientSpec).load(FabricLoader.getInstance().getConfigDir().resolve(ComputerCraftAPI.MOD_ID + "-client.toml")); } } diff --git a/projects/fabric/src/main/java/dan200/computercraft/shared/FabricCommonHooks.java b/projects/fabric/src/main/java/dan200/computercraft/shared/FabricCommonHooks.java index 55b457390..ae0b79389 100644 --- a/projects/fabric/src/main/java/dan200/computercraft/shared/FabricCommonHooks.java +++ b/projects/fabric/src/main/java/dan200/computercraft/shared/FabricCommonHooks.java @@ -5,7 +5,6 @@ package dan200.computercraft.shared; import dan200.computercraft.shared.media.items.DiskItem; -import dan200.computercraft.shared.media.items.TreasureDiskItem; import dan200.computercraft.shared.peripheral.modem.wired.CableBlock; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerPlayer; @@ -50,6 +49,6 @@ public class FabricCommonHooks { } private static boolean doesSneakBypassUse(ItemStack stack) { - return stack.isEmpty() || stack.getItem() instanceof DiskItem || stack.getItem() instanceof TreasureDiskItem; + return stack.isEmpty() || stack.getItem() instanceof DiskItem; } } diff --git a/projects/forge/src/main/java/dan200/computercraft/shared/ForgeCommonHooks.java b/projects/forge/src/main/java/dan200/computercraft/shared/ForgeCommonHooks.java index e06541a5c..e80f3239f 100644 --- a/projects/forge/src/main/java/dan200/computercraft/shared/ForgeCommonHooks.java +++ b/projects/forge/src/main/java/dan200/computercraft/shared/ForgeCommonHooks.java @@ -19,6 +19,7 @@ import net.neoforged.neoforge.event.LootTableLoadEvent; import net.neoforged.neoforge.event.RegisterCommandsEvent; import net.neoforged.neoforge.event.entity.EntityJoinLevelEvent; import net.neoforged.neoforge.event.entity.living.LivingDropsEvent; +import net.neoforged.neoforge.event.entity.player.ItemTooltipEvent; import net.neoforged.neoforge.event.entity.player.PlayerInteractEvent; import net.neoforged.neoforge.event.level.ChunkEvent; import net.neoforged.neoforge.event.level.ChunkTicketLevelUpdatedEvent; @@ -109,4 +110,9 @@ public class ForgeCommonHooks { public static void onLivingDrops(LivingDropsEvent event) { event.getDrops().removeIf(itemEntity -> CommonHooks.onLivingDrop(event.getEntity(), itemEntity.getItem())); } + + @SubscribeEvent + public static void onItemTooltip(ItemTooltipEvent event) { + CommonHooks.onItemTooltip(event.getItemStack(), event.getContext(), event.getFlags(), event.getToolTip()); + } }