From c20336286bcd31817d8a3822e5783b64b6ad0057 Mon Sep 17 00:00:00 2001 From: Jonathan Coates Date: Fri, 2 May 2025 19:00:22 +0100 Subject: [PATCH] Update to FAPI 0.122 - Use new tooltip component registry. This means we can move the tooltip appending magic to Neo only. - Use new chunk level change event. I'm not actually sure if we need this on recent versions (I can't reproduce the monitor update bug that we introduced this to fix), but I've no clue what's changed here. --- gradle/libs.versions.toml | 2 +- .../computercraft/shared/CommonHooks.java | 36 ++----------------- .../computercraft/shared/ModRegistry.java | 9 +++++ .../shared/util/TickScheduler.java | 7 +--- .../client/ComputerCraftClient.java | 4 --- .../computercraft/mixin/ChunkMapMixin.java | 30 ---------------- .../computercraft/shared/ComputerCraft.java | 10 ++++++ .../fabric/src/main/resources/fabric.mod.json | 2 +- .../shared/ForgeCommonHooks.java | 31 +++++++++++++++- 9 files changed, 55 insertions(+), 76 deletions(-) delete mode 100644 projects/fabric/src/main/java/dan200/computercraft/mixin/ChunkMapMixin.java diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 72a768c5d..7c47b9a7a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ # Minecraft # MC version is specified in gradle.properties, as we need that in settings.gradle. # Remember to update corresponding versions in fabric.mod.json/neoforge.mods.toml -fabric-api = "0.120.0+1.21.5" +fabric-api = "0.122.0+1.21.5" fabric-loader = "0.16.10" neoForge = "21.5.49-beta" neoMergeTool = "2.0.0" 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 d48989ab3..c92f9453e 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/CommonHooks.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/CommonHooks.java @@ -13,9 +13,7 @@ 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.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; @@ -27,8 +25,9 @@ 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.*; -import net.minecraft.world.item.component.TooltipDisplay; +import net.minecraft.world.item.CreativeModeTab; +import net.minecraft.world.item.CreativeModeTabs; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.LecternBlock; @@ -41,10 +40,8 @@ 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. @@ -166,31 +163,4 @@ 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); - - var display = stack.getOrDefault(DataComponents.TOOLTIP_DISPLAY, TooltipDisplay.DEFAULT); - stack.addToTooltip(ModRegistry.DataComponents.PRINTOUT.get(), context, display, appender, flags); - stack.addToTooltip(ModRegistry.DataComponents.TREASURE_DISK.get(), context, display, appender, flags); - stack.addToTooltip(ModRegistry.DataComponents.COMPUTER_ID.get(), context, display, appender, flags); - stack.addToTooltip(ModRegistry.DataComponents.DISK_ID.get(), context, display, appender, flags); - } - - /** - * 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); - } - } } 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 db010f211..79022143e 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/ModRegistry.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/ModRegistry.java @@ -113,6 +113,7 @@ import net.minecraft.world.flag.FeatureFlags; import net.minecraft.world.inventory.MenuType; import net.minecraft.world.item.*; import net.minecraft.world.item.component.TooltipDisplay; +import net.minecraft.world.item.component.TooltipProvider; import net.minecraft.world.item.crafting.CustomRecipe; import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.item.crafting.RecipeSerializer; @@ -126,6 +127,7 @@ import net.minecraft.world.level.material.MapColor; import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType; import org.jspecify.annotations.Nullable; +import java.util.List; import java.util.Objects; import java.util.Set; import java.util.function.*; @@ -441,6 +443,13 @@ public final class ModRegistry { public static final RegistryEntry> PRINTOUT = register("printout", b -> b .persistent(PrintoutData.CODEC).networkSynchronized(PrintoutData.STREAM_CODEC) ); + + public static final List>> TOOLTIP_COMPONENTS = List.of( + DataComponents.COMPUTER_ID, + DataComponents.DISK_ID, + DataComponents.TREASURE_DISK, + DataComponents.PRINTOUT + ); } public static class TurtleUpgradeTypes { diff --git a/projects/common/src/main/java/dan200/computercraft/shared/util/TickScheduler.java b/projects/common/src/main/java/dan200/computercraft/shared/util/TickScheduler.java index 4f6b9222e..a3ee7fd76 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/util/TickScheduler.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/util/TickScheduler.java @@ -15,7 +15,6 @@ import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraft.world.level.chunk.status.ChunkStatus; import java.util.*; import java.util.concurrent.ConcurrentLinkedDeque; @@ -63,7 +62,7 @@ public final class TickScheduler { } public static void onChunkTicketChanged(ServerLevel level, long chunkPos, int oldLevel, int newLevel) { - boolean oldLoaded = isLoaded(oldLevel), newLoaded = isLoaded(newLevel); + boolean oldLoaded = ChunkLevel.isLoaded(oldLevel), newLoaded = ChunkLevel.isLoaded(newLevel); if (!oldLoaded && newLoaded) { // If our chunk is becoming active, requeue all pending tokens. var delayedTokens = delayed.remove(new ChunkReference(level.dimension(), chunkPos)); @@ -171,8 +170,4 @@ public final class TickScheduler { return "ChunkReference(" + level + " at " + new ChunkPos(position) + ")"; } } - - private static boolean isLoaded(int level) { - return level <= ChunkLevel.byStatus(ChunkStatus.FULL); - } } 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 7b5eeda1f..faf9711b3 100644 --- a/projects/fabric/src/client/java/dan200/computercraft/client/ComputerCraftClient.java +++ b/projects/fabric/src/client/java/dan200/computercraft/client/ComputerCraftClient.java @@ -16,7 +16,6 @@ import dan200.computercraft.client.model.ExtraModels; import dan200.computercraft.client.platform.FabricModelKey; import dan200.computercraft.core.util.Nullability; import dan200.computercraft.impl.Services; -import dan200.computercraft.shared.CommonHooks; import dan200.computercraft.shared.ComputerCraft; import dan200.computercraft.shared.ModRegistry; import dan200.computercraft.shared.config.ConfigSpec; @@ -27,7 +26,6 @@ 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.model.loading.v1.SimpleUnbakedExtraModel; import net.fabricmc.fabric.api.client.model.loading.v1.UnbakedExtraModel; @@ -107,8 +105,6 @@ public class ComputerCraftClient { }) ))); - 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/mixin/ChunkMapMixin.java b/projects/fabric/src/main/java/dan200/computercraft/mixin/ChunkMapMixin.java deleted file mode 100644 index 907a95618..000000000 --- a/projects/fabric/src/main/java/dan200/computercraft/mixin/ChunkMapMixin.java +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-FileCopyrightText: 2022 The CC: Tweaked Developers -// -// SPDX-License-Identifier: MPL-2.0 - -package dan200.computercraft.mixin; - -import dan200.computercraft.shared.CommonHooks; -import net.minecraft.server.level.ChunkHolder; -import net.minecraft.server.level.ChunkMap; -import net.minecraft.server.level.ServerLevel; -import org.jspecify.annotations.Nullable; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -@Mixin(ChunkMap.class) -class ChunkMapMixin { - @Final - @Shadow - ServerLevel level; - - @Inject(method = "updateChunkScheduling", at = @At("HEAD")) - @SuppressWarnings("unused") - private void onUpdateChunkScheduling(long chunkPos, int newLevel, @Nullable ChunkHolder holder, int oldLevel, CallbackInfoReturnable callback) { - CommonHooks.onChunkTicketLevelChanged(level, chunkPos, oldLevel, newLevel); - } -} diff --git a/projects/fabric/src/main/java/dan200/computercraft/shared/ComputerCraft.java b/projects/fabric/src/main/java/dan200/computercraft/shared/ComputerCraft.java index e479d688b..0e9e4c1d4 100644 --- a/projects/fabric/src/main/java/dan200/computercraft/shared/ComputerCraft.java +++ b/projects/fabric/src/main/java/dan200/computercraft/shared/ComputerCraft.java @@ -34,6 +34,7 @@ import net.fabricmc.fabric.api.event.player.UseBlockCallback; import net.fabricmc.fabric.api.event.registry.DynamicRegistries; import net.fabricmc.fabric.api.event.registry.FabricRegistryBuilder; import net.fabricmc.fabric.api.event.registry.RegistryAttribute; +import net.fabricmc.fabric.api.item.v1.ComponentTooltipAppenderRegistry; import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents; import net.fabricmc.fabric.api.lookup.v1.block.BlockApiLookup; import net.fabricmc.fabric.api.lookup.v1.item.ItemApiLookup; @@ -43,10 +44,12 @@ import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener; import net.fabricmc.fabric.api.resource.ResourceManagerHelper; import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.core.component.DataComponents; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ChunkLevel; import net.minecraft.server.packs.PackType; import net.minecraft.server.packs.resources.PreparableReloadListener; import net.minecraft.server.packs.resources.ResourceManager; @@ -94,6 +97,11 @@ public class ComputerCraft { // Register commands CommandRegistrationCallback.EVENT.register((dispatcher, context, environment) -> CommandComputerCraft.register(dispatcher)); + // Register tooltips + for (var tooltip : ModRegistry.DataComponents.TOOLTIP_COMPONENTS) { + ComponentTooltipAppenderRegistry.addAfter(DataComponents.LORE, tooltip.get()); + } + // Register hooks ServerLifecycleEvents.SERVER_STARTING.register(server -> { ((FabricConfigFile) ConfigSpec.serverSpec).load( @@ -111,6 +119,8 @@ public class ComputerCraft { ServerTickEvents.START_SERVER_TICK.register(CommonHooks::onServerTickStart); ServerTickEvents.START_SERVER_TICK.register(s -> CommonHooks.onServerTickEnd()); ServerChunkEvents.CHUNK_UNLOAD.register((l, c) -> CommonHooks.onServerChunkUnload(c)); + ServerChunkEvents.CHUNK_LEVEL_TYPE_CHANGE.register((level, chunk, oldStatus, newStatus) -> + CommonHooks.onChunkTicketLevelChanged(level, chunk.getPos().toLong(), ChunkLevel.byStatus(oldStatus), ChunkLevel.byStatus(newStatus))); PlayerBlockBreakEvents.BEFORE.register(FabricCommonHooks::onBlockDestroy); UseBlockCallback.EVENT.register(CommonHooks::onUseBlock); diff --git a/projects/fabric/src/main/resources/fabric.mod.json b/projects/fabric/src/main/resources/fabric.mod.json index 5900e0306..7a2ae64d1 100644 --- a/projects/fabric/src/main/resources/fabric.mod.json +++ b/projects/fabric/src/main/resources/fabric.mod.json @@ -50,7 +50,7 @@ ], "depends": { "fabricloader": ">=0.16.10", - "fabric-api": ">=0.119.5", + "fabric-api": ">=0.122.0", "minecraft": "=1.21.5" }, "accessWidener": "computercraft.accesswidener" 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 f82c4e2dc..44504aaa0 100644 --- a/projects/forge/src/main/java/dan200/computercraft/shared/ForgeCommonHooks.java +++ b/projects/forge/src/main/java/dan200/computercraft/shared/ForgeCommonHooks.java @@ -6,10 +6,13 @@ package dan200.computercraft.shared; import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.shared.command.CommandComputerCraft; +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.server.level.ServerLevel; import net.minecraft.world.InteractionResult; +import net.minecraft.world.item.component.TooltipDisplay; import net.neoforged.bus.api.EventPriority; import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.fml.common.EventBusSubscriber; @@ -28,6 +31,9 @@ import net.neoforged.neoforge.event.server.ServerStartingEvent; import net.neoforged.neoforge.event.server.ServerStoppedEvent; import net.neoforged.neoforge.event.tick.ServerTickEvent; +import java.util.List; +import java.util.function.Consumer; + /** * Forge-specific dispatch for {@link CommonHooks}. */ @@ -110,6 +116,29 @@ public class ForgeCommonHooks { @SubscribeEvent public static void onItemTooltip(ItemTooltipEvent event) { - CommonHooks.onItemTooltip(event.getItemStack(), event.getContext(), event.getFlags(), event.getToolTip()); + var stack = event.getItemStack(); + var appender = new TooltipAppender(event.getToolTip()); + + var display = stack.getOrDefault(DataComponents.TOOLTIP_DISPLAY, TooltipDisplay.DEFAULT); + for (var component : ModRegistry.DataComponents.TOOLTIP_COMPONENTS) { + stack.addToTooltip(component.get(), event.getContext(), display, appender, event.getFlags()); + } + } + + /** + * 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); + } } }