mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2024-12-04 23:40:00 +00:00
Render pocket computers in tooltips
This commit is contained in:
parent
c271ed7c7f
commit
94e7d2d03b
@ -56,4 +56,8 @@ public final class ClientPocketComputers {
|
||||
var id = PocketComputerItem.getInstanceID(stack);
|
||||
return id == null ? null : instances.get(id);
|
||||
}
|
||||
|
||||
static @Nullable PocketComputerData get(UUID id) {
|
||||
return instances.get(id);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,101 @@
|
||||
// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers
|
||||
//
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package dan200.computercraft.client.pocket;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import dan200.computercraft.client.gui.GuiSprites;
|
||||
import dan200.computercraft.client.render.ComputerBorderRenderer;
|
||||
import dan200.computercraft.client.render.RenderTypes;
|
||||
import dan200.computercraft.client.render.SpriteRenderer;
|
||||
import dan200.computercraft.client.render.text.FixedWidthFontRenderer;
|
||||
import dan200.computercraft.core.terminal.Terminal;
|
||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||
import dan200.computercraft.shared.computer.terminal.NetworkedTerminal;
|
||||
import dan200.computercraft.shared.pocket.items.PocketTooltipComponent;
|
||||
import net.minecraft.client.gui.Font;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.UUID;
|
||||
|
||||
import static dan200.computercraft.client.render.ComputerBorderRenderer.BORDER;
|
||||
import static dan200.computercraft.client.render.ComputerBorderRenderer.MARGIN;
|
||||
import static dan200.computercraft.client.render.text.FixedWidthFontRenderer.FONT_HEIGHT;
|
||||
import static dan200.computercraft.client.render.text.FixedWidthFontRenderer.FONT_WIDTH;
|
||||
|
||||
/**
|
||||
* Renders the pocket computer's terminal in the item's tooltip.
|
||||
* <p>
|
||||
* The rendered terminal is downscaled by a factor of {@link #SCALE}.
|
||||
*/
|
||||
public class PocketClientTooltipComponent implements ClientTooltipComponent {
|
||||
private static final float SCALE = 0.5f;
|
||||
|
||||
private final UUID id;
|
||||
private final ComputerFamily family;
|
||||
|
||||
public PocketClientTooltipComponent(PocketTooltipComponent component) {
|
||||
this.id = component.id();
|
||||
this.family = component.family();
|
||||
}
|
||||
|
||||
private @Nullable PocketComputerData computer() {
|
||||
return ClientPocketComputers.get(id);
|
||||
}
|
||||
|
||||
private @Nullable NetworkedTerminal terminal() {
|
||||
var computer = computer();
|
||||
return computer == null ? null : computer.getTerminal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight() {
|
||||
var terminal = terminal();
|
||||
if (terminal == null) return 0;
|
||||
|
||||
return (int) Math.ceil(
|
||||
(terminal.getHeight() * FixedWidthFontRenderer.FONT_HEIGHT + ComputerBorderRenderer.BORDER * 2 + ComputerBorderRenderer.MARGIN * 2) * SCALE
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWidth(Font font) {
|
||||
var terminal = terminal();
|
||||
if (terminal == null) return 0;
|
||||
|
||||
return (int) Math.ceil(
|
||||
(terminal.getWidth() * FixedWidthFontRenderer.FONT_WIDTH + ComputerBorderRenderer.BORDER * 2 + ComputerBorderRenderer.MARGIN * 2) * SCALE
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderImage(Font font, int x, int y, GuiGraphics guiGraphics) {
|
||||
var terminal = terminal();
|
||||
if (terminal == null) return;
|
||||
|
||||
var pose = guiGraphics.pose();
|
||||
pose.pushPose();
|
||||
pose.translate(x, y, 0);
|
||||
pose.scale(SCALE, SCALE, 1);
|
||||
|
||||
|
||||
render(pose, guiGraphics.bufferSource(), terminal);
|
||||
|
||||
pose.popPose();
|
||||
}
|
||||
|
||||
private void render(PoseStack stack, MultiBufferSource buffers, Terminal terminal) {
|
||||
var width = terminal.getWidth() * FONT_WIDTH + MARGIN * 2;
|
||||
var height = terminal.getHeight() * FONT_HEIGHT + MARGIN * 2;
|
||||
|
||||
var renderer = SpriteRenderer.createForGui(stack.last().pose(), buffers.getBuffer(RenderTypes.GUI_SPRITES));
|
||||
ComputerBorderRenderer.render(renderer, GuiSprites.getComputerTextures(family), BORDER, BORDER, width, height, false);
|
||||
|
||||
var quadEmitter = FixedWidthFontRenderer.toVertexConsumer(stack, buffers.getBuffer(RenderTypes.TERMINAL));
|
||||
FixedWidthFontRenderer.drawTerminal(quadEmitter, BORDER + MARGIN, BORDER + MARGIN, terminal, MARGIN, MARGIN, MARGIN, MARGIN);
|
||||
}
|
||||
}
|
@ -34,11 +34,12 @@ public class SpriteRenderer {
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
public static SpriteRenderer createForGui(Matrix4f transform, VertexConsumer builder) {
|
||||
return new SpriteRenderer(transform, builder, 0, RenderTypes.FULL_BRIGHT_LIGHTMAP, 255, 255, 255);
|
||||
}
|
||||
|
||||
public static SpriteRenderer createForGui(GuiGraphics graphics, RenderType renderType) {
|
||||
return new SpriteRenderer(
|
||||
graphics.pose().last().pose(), graphics.bufferSource().getBuffer(renderType),
|
||||
0, RenderTypes.FULL_BRIGHT_LIGHTMAP, 255, 255, 255
|
||||
);
|
||||
return createForGui(graphics.pose().last().pose(), graphics.bufferSource().getBuffer(renderType));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -28,7 +28,6 @@ import dan200.computercraft.shared.util.IDAssigner;
|
||||
import dan200.computercraft.shared.util.InventoryUtil;
|
||||
import dan200.computercraft.shared.util.NBTUtil;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
@ -39,6 +38,7 @@ import net.minecraft.world.InteractionResultHolder;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.item.ItemEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.tooltip.TooltipComponent;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.TooltipFlag;
|
||||
@ -47,6 +47,7 @@ import net.minecraft.world.level.Level;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public class PocketComputerItem extends Item implements IComputerItem, IMedia, IColouredItem {
|
||||
@ -196,6 +197,11 @@ public class PocketComputerItem extends Item implements IComputerItem, IMedia, I
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<TooltipComponent> getTooltipImage(ItemStack stack) {
|
||||
var id = getInstanceID(stack);
|
||||
return id == null ? Optional.empty() : Optional.of(new PocketTooltipComponent(id, family));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendHoverText(ItemStack stack, @Nullable Level world, List<Component> list, TooltipFlag flag) {
|
||||
@ -350,8 +356,4 @@ public class PocketComputerItem extends Item implements IComputerItem, IMedia, I
|
||||
compound.put(NBT_UPGRADE_INFO, upgrade.data().copy());
|
||||
}
|
||||
}
|
||||
|
||||
public static CompoundTag getUpgradeInfo(ItemStack stack) {
|
||||
return stack.getOrCreateTagElement(NBT_UPGRADE_INFO);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,25 @@
|
||||
// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers
|
||||
//
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package dan200.computercraft.shared.pocket.items;
|
||||
|
||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||
import net.minecraft.world.inventory.tooltip.TooltipComponent;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* A tooltip computer describing a pocket computer.
|
||||
* <p>
|
||||
* This has no behaviour on its own. When rendering, this is converted to an equivalent client-side component,
|
||||
* that renders the computer's terminal.
|
||||
*
|
||||
* @param id The instance ID of this pocket computer.
|
||||
* @param family The family of this pocket computer.
|
||||
* @see PocketComputerItem#getTooltipImage(ItemStack)
|
||||
* @see dan200.computercraft.client.pocket.PocketClientTooltipComponent
|
||||
*/
|
||||
public record PocketTooltipComponent(UUID id, ComputerFamily family) implements TooltipComponent {
|
||||
}
|
@ -7,6 +7,7 @@ package dan200.computercraft.client;
|
||||
import dan200.computercraft.api.ComputerCraftAPI;
|
||||
import dan200.computercraft.api.client.FabricComputerCraftAPIClient;
|
||||
import dan200.computercraft.client.model.CustomModelLoader;
|
||||
import dan200.computercraft.client.pocket.PocketClientTooltipComponent;
|
||||
import dan200.computercraft.impl.Services;
|
||||
import dan200.computercraft.shared.ModRegistry;
|
||||
import dan200.computercraft.shared.config.ConfigSpec;
|
||||
@ -15,6 +16,7 @@ import dan200.computercraft.shared.network.client.ClientNetworkContext;
|
||||
import dan200.computercraft.shared.peripheral.modem.wired.CableBlock;
|
||||
import dan200.computercraft.shared.platform.FabricConfigFile;
|
||||
import dan200.computercraft.shared.platform.FabricMessageType;
|
||||
import dan200.computercraft.shared.pocket.items.PocketTooltipComponent;
|
||||
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;
|
||||
@ -22,6 +24,7 @@ import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
||||
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;
|
||||
import net.fabricmc.fabric.api.client.rendering.v1.TooltipComponentCallback;
|
||||
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents;
|
||||
import net.fabricmc.fabric.api.event.client.player.ClientPickBlockGatherCallback;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
@ -74,6 +77,11 @@ public class ComputerCraftClient {
|
||||
}
|
||||
});
|
||||
|
||||
TooltipComponentCallback.EVENT.register(c -> {
|
||||
if (c instanceof PocketTooltipComponent p) return new PocketClientTooltipComponent(p);
|
||||
return null;
|
||||
});
|
||||
|
||||
// Easier to hook in as an event than use BlockPickInteractionAware.
|
||||
ClientPickBlockGatherCallback.EVENT.register((player, hit) -> {
|
||||
if (hit.getType() != HitResult.Type.BLOCK) return ItemStack.EMPTY;
|
||||
|
@ -7,13 +7,12 @@ package dan200.computercraft.client;
|
||||
import dan200.computercraft.api.ComputerCraftAPI;
|
||||
import dan200.computercraft.api.client.turtle.RegisterTurtleModellersEvent;
|
||||
import dan200.computercraft.client.model.turtle.TurtleModelLoader;
|
||||
import dan200.computercraft.client.pocket.PocketClientTooltipComponent;
|
||||
import dan200.computercraft.shared.pocket.items.PocketTooltipComponent;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.item.ItemProperties;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.client.event.ModelEvent;
|
||||
import net.minecraftforge.client.event.RegisterClientReloadListenersEvent;
|
||||
import net.minecraftforge.client.event.RegisterColorHandlersEvent;
|
||||
import net.minecraftforge.client.event.RegisterShadersEvent;
|
||||
import net.minecraftforge.client.event.*;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.ModLoader;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
@ -85,4 +84,9 @@ public final class ForgeClientRegistry {
|
||||
ClientRegistry.register();
|
||||
event.enqueueWork(() -> ClientRegistry.registerMainThread(ItemProperties::register));
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onTooltipComponent(RegisterClientTooltipComponentFactoriesEvent event) {
|
||||
event.register(PocketTooltipComponent.class, PocketClientTooltipComponent::new);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user