Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/main/java/com/hfstudio/guidenh/ClientProxy.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import com.hfstudio.guidenh.bridge.GuideNhRuntimeBridge;
import com.hfstudio.guidenh.bridge.GuideNhRuntimeBridgeSettings;
import com.hfstudio.guidenh.client.GuideNhClientTaskScheduler;
import com.hfstudio.guidenh.client.RegionWandRenderer;
import com.hfstudio.guidenh.client.command.GuideNhClientBridgeController;
import com.hfstudio.guidenh.client.command.GuideNhClientCommand;
Expand Down Expand Up @@ -111,6 +112,7 @@ public static CompileWorker getWorker() {
@Override
public void preInit(FMLPreInitializationEvent event) {
super.preInit(event);
GuideNhClientTaskScheduler.initialize();
GuidebookLevel.setPreviewWorldFactory(GuidebookFakeWorld::new);
GuideNhClientIntegrationBootstrap.preInitClient();
GuideME.initClientProxy();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.lwjgl.opengl.GL11;

import com.hfstudio.guidenh.bridge.protocol.BridgeProtocolLimits;
import com.hfstudio.guidenh.client.GuideNhClientTaskScheduler;
import com.hfstudio.guidenh.guide.compiler.IdUtils;
import com.hfstudio.guidenh.guide.document.interaction.ItemTooltip;
import com.hfstudio.guidenh.guide.internal.tooltip.GuideItemTooltipLines;
Expand Down Expand Up @@ -98,7 +99,7 @@ private ItemPreviewPayload renderOnClientThread(ItemPreviewCacheKey cacheKey, It
}

CompletableFuture<ItemPreviewPayload> future = new CompletableFuture<>();
minecraft.func_152344_a(() -> {
GuideNhClientTaskScheduler.execute(() -> {
try {
future.complete(createPayload(cacheKey, stack, Minecraft.getMinecraft()));
} catch (Throwable error) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package com.hfstudio.guidenh.client;

import java.util.Objects;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

import net.minecraft.client.Minecraft;

import com.hfstudio.guidenh.guide.scene.support.GuideDebugLog;

import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.common.gameevent.TickEvent;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;

@SideOnly(Side.CLIENT)
public class GuideNhClientTaskScheduler {

private static final Queue<Runnable> PENDING_TASKS = new ConcurrentLinkedQueue<>();
private static final Runnable TICK_BOUNDARY = () -> {};
private static boolean initialized;

public static void initialize() {
if (initialized) {
return;
}
FMLCommonHandler.instance()
.bus()
.register(new GuideNhClientTaskScheduler());
initialized = true;
}

public static boolean isOnClientThread() {
Minecraft minecraft = Minecraft.getMinecraft();
return minecraft != null && minecraft.func_152345_ab();
}

public static void execute(Runnable task) {
Objects.requireNonNull(task, "task");
if (isOnClientThread()) {
runTask(task);
return;
}
PENDING_TASKS.add(task);
}

@SubscribeEvent
public void onClientTick(TickEvent.ClientTickEvent event) {
if (event.phase != TickEvent.Phase.END) {
return;
}
PENDING_TASKS.add(TICK_BOUNDARY);
Runnable task;
while ((task = PENDING_TASKS.poll()) != null && task != TICK_BOUNDARY) {
runTask(task);
}
}

private static void runTask(Runnable task) {
try {
task.run();
} catch (Throwable error) {
GuideDebugLog.error("Client task execution failed", error);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -104,19 +104,23 @@ public static ItemStack resolveOreDictionaryStack(@Nullable String oreName) {
}

List<ItemStack> oreStacks = OreDictionary.getOres(trimmedOreName);
if (oreStacks == null || oreStacks.isEmpty()) {
if (oreStacks.isEmpty()) {
return null;
}

ItemStack firstMatch = oreStacks.getFirst();
if (firstMatch == null || firstMatch.getItem() == null) {
return null;
for (ItemStack stack : oreStacks) {
if (stack == null || stack.getItem() == null) {
continue;
}

ItemStack copiedStack = stack.copy();
ItemStack normalizedStack = GuideNhIntegrationRegistry.global()
.normalizeItemStack(copiedStack);

return normalizedStack != null && normalizedStack.getItem() != null ? normalizedStack : copiedStack;
}

ItemStack copiedStack = firstMatch.copy();
ItemStack normalizedStack = GuideNhIntegrationRegistry.global()
.normalizeItemStack(copiedStack);
return normalizedStack != null && normalizedStack.getItem() != null ? normalizedStack : copiedStack;
return null;
}

@Nullable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ public static ParsedItemRef parseItemRef(String idText, String defaultNamespace)
nbt = tc;
}
} catch (Throwable t) {
GuideDebugLog.warnAlways(
GuideDebugLog.warn(
"[GuideNH] [IdUtils] Failed to parse SNBT tail '{}' for id '{}'; ignoring NBT",
snbt,
idText,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -993,9 +993,9 @@ public LytFlowContent createErrorFlowContent(String text, UnistNode child) {
span.appendText(tildes + "^");
span.appendBreak();

GuideDebugLog.warnAlways("[GuideNH] [PageCompiler] {}\n{}\n{}\n", text, line, tildes + "^");
GuideDebugLog.warn("[GuideNH] [PageCompiler] {}\n{}\n{}\n", text, line, tildes + "^");
} else {
GuideDebugLog.warnAlways("[GuideNH] [PageCompiler] {}\n", text);
GuideDebugLog.warn("[GuideNH] [PageCompiler] {}\n", text);
}

return span;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,19 +72,21 @@ protected void compile(PageCompiler compiler, LytBlockContainer parent, MdxJsxEl
}

private void compileDirectiveBody(PageCompiler compiler, BlockquoteDirective directive, LytBlockContainer parent) {
MdxJsxFlowElement firstParagraph = directive.firstParagraph() instanceof MdxJsxFlowElement paragraph ? paragraph
: null;
// When there's a remainingText override and the first paragraph is still present
// at the head of the children list, replace its leading text.
// Otherwise — just compile children normally.
if (!directive.children()
.isEmpty() && directive.firstParagraph() != null
.isEmpty() && firstParagraph != null
&& directive.children()
.getFirst() == directive.firstParagraph()
.getFirst() == firstParagraph
&& directive.remainingText() != null
&& !directive.remainingText()
.isEmpty()) {
// Strip directive prefix from the first paragraph's leading text
stripLeadingText(directive.firstParagraph(), directive.remainingText());
compiler.compileBlockContext(Collections.singletonList(directive.firstParagraph()), parent);
stripLeadingText(firstParagraph, directive.remainingText());
compiler.compileBlockContext(Collections.singletonList(firstParagraph), parent);
for (int i = 1; i < directive.children()
.size(); i++) {
compiler.compileBlockContext(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,22 @@

public class LytCodeBlockToolbar extends LytBox implements InteractiveElement {

static final GuiSprite COPY_SPRITE = new GuiSprite(
public static final GuiSprite COPY_SPRITE = new GuiSprite(
GuideIconButton.TEX,
0,
48,
16,
16,
GuideIconButton.TEXTURE_SIZE,
GuideIconButton.TEXTURE_SIZE);
public static final GuiSprite RESET_VIEW_SPRITE = new GuiSprite(
GuideIconButton.TEX,
0,
32,
16,
16,
GuideIconButton.TEXTURE_SIZE,
GuideIconButton.TEXTURE_SIZE);
private static final long COPY_TOOLTIP_RESET_DELAY_MILLIS = 1500L;
private static final int TEXT_CENTERING_OFFSET_Y = 1;
private static final CodeHighlightTheme CODE_THEME = CodeHighlightTheme.GITHUB_DARK_DEFAULT;
Expand Down Expand Up @@ -89,6 +97,7 @@ public void setCopyText(String copyText) {
}

public void addButton(LytButton button) {
button.setColor(toolbarText);
extraButtons.add(button);
append(button);
if (getDocument() != null) getDocument().invalidateLayout();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
import com.hfstudio.guidenh.guide.document.interaction.FlowInteractionPath;
import com.hfstudio.guidenh.guide.document.interaction.GuideTooltip;
import com.hfstudio.guidenh.guide.document.interaction.InteractiveElement;
import com.hfstudio.guidenh.guide.internal.debug.DebugComponent;
import com.hfstudio.guidenh.guide.internal.debug.DebugFlowContainer;
import com.hfstudio.guidenh.guide.internal.recipe.LytNeiRecipeBox;
import com.hfstudio.guidenh.guide.internal.util.SmoothFloatState;
import com.hfstudio.guidenh.guide.render.GuiSprite;
Expand Down Expand Up @@ -55,6 +57,14 @@ public abstract class LytMermaidCanvas<T extends LytMermaidCanvas<T>> extends Ly

private final Map<ResolvedTextStyle, ResolvedTextStyle> scaledStyleCache = new IdentityHashMap<>();
private float lastScaledStyleZoom = Float.NaN;
@Nullable
private Object debugComponentLayout;
@Nullable
private LytRect debugComponentViewport;
private int debugComponentOffsetX;
private int debugComponentOffsetY;
private float debugComponentZoom;
private List<DebugComponent.ComponentEntry> cachedDebugComponents = List.of();

// Common interaction state
protected Map<String, LytBlock> nodeContentBlocks;
Expand Down Expand Up @@ -256,6 +266,12 @@ public void centerDiagram(int viewportWidth, int viewportHeight, int diagramWidt
zoom);
}

public void resetView() {
zoom = 1f;
centerDiagram(contentWidth(), contentHeight());
clampOffsets();
}

@Override
public boolean beginDrag(int documentX, int documentY, int button) {
if (!diagramReady()) return false;
Expand Down Expand Up @@ -360,11 +376,37 @@ protected ResolvedTextStyle getOrScaleStyle(ResolvedTextStyle base, float zoom)
return MermaidNodeRenderer.getOrScaleStyle(scaledStyleCache, base, zoom);
}

public static int clampAxis(int offset, int viewportSize, int contentSize) {
if (contentSize <= viewportSize) {
return (viewportSize - contentSize) / 2;
@Nullable
protected List<DebugComponent.ComponentEntry> getCachedDebugComponents(Object layout) {
LytRect viewport = getInnerViewport();
int offsetX = getVisualOffsetX();
int offsetY = getVisualOffsetY();
float activeZoom = getActiveZoom();
if (layout != debugComponentLayout || !viewport.equals(debugComponentViewport)
|| offsetX != debugComponentOffsetX
|| offsetY != debugComponentOffsetY
|| Float.compare(activeZoom, debugComponentZoom) != 0) {
return null;
}
return Math.clamp(offset, viewportSize - contentSize, 0);
return cachedDebugComponents;
}

protected List<DebugComponent.ComponentEntry> cacheDebugComponents(Object layout,
List<DebugComponent.ComponentEntry> components) {
debugComponentLayout = layout;
debugComponentViewport = getInnerViewport();
debugComponentOffsetX = getVisualOffsetX();
debugComponentOffsetY = getVisualOffsetY();
debugComponentZoom = getActiveZoom();
cachedDebugComponents = List.copyOf(components);
return cachedDebugComponents;
}

public static int clampAxis(int offset, int viewportSize, int contentSize) {
int minimumVisible = Math.max(1, Math.min(contentSize, viewportSize) / 2);
int minOffset = minimumVisible - contentSize;
int maxOffset = viewportSize - minimumVisible;
return Math.clamp(offset, minOffset, maxOffset);
}

public static int scaled(int base, int value, float activeZoom) {
Expand Down Expand Up @@ -519,6 +561,81 @@ protected static LytRect resolveNodeContentRect(NodeContentLayout contentLayout,
.height() * activeZoom)));
}

protected void collectNodeContentDebugComponents(NodeContentLayout contentLayout, LytRect contentViewport,
float activeZoom, String nodeName, int priority, List<DebugComponent.ComponentEntry> components) {
if (contentLayout == null || contentViewport == null
|| contentLayout.visualBounds()
.isEmpty()) {
return;
}
int originX = contentViewport.x() - Math.round(
contentLayout.visualBounds()
.x() * activeZoom);
int originY = contentViewport.y() - Math.round(
contentLayout.visualBounds()
.y() * activeZoom);
collectNodeContentDebugComponents(
contentLayout.block(),
originX,
originY,
activeZoom,
nodeName,
priority,
components,
0);
}

private void collectNodeContentDebugComponents(LytNode node, int originX, int originY, float activeZoom,
String nodeName, int priority, List<DebugComponent.ComponentEntry> components, int depth) {
LytRect localBounds = node.getBounds();
if (localBounds != null && !localBounds.isEmpty()) {
LytRect screenBounds = new LytRect(
originX + Math.round(localBounds.x() * activeZoom),
originY + Math.round(localBounds.y() * activeZoom),
Math.max(1, Math.round(localBounds.width() * activeZoom)),
Math.max(1, Math.round(localBounds.height() * activeZoom)));
components.add(
new DebugComponent.SimpleComponentEntry(
"NodeContent:" + nodeName
+ ":"
+ node.getClass()
.getSimpleName(),
screenBounds,
null,
priority + depth));
if (node instanceof DebugFlowContainer flowContainer) {
for (DebugFlowContainer.FlowContentEntry entry : flowContainer.getAllFlowContent()) {
LytRect flowBounds = entry.bounds();
components.add(
new DebugComponent.SimpleComponentEntry(
"NodeContent:" + nodeName
+ ":"
+ entry.content()
.getClass()
.getSimpleName(),
new LytRect(
originX + Math.round(flowBounds.x() * activeZoom),
originY + Math.round(flowBounds.y() * activeZoom),
Math.max(1, Math.round(flowBounds.width() * activeZoom)),
Math.max(1, Math.round(flowBounds.height() * activeZoom))),
null,
priority + depth + 10));
}
}
}
for (LytNode child : node.getChildren()) {
collectNodeContentDebugComponents(
child,
originX,
originY,
activeZoom,
nodeName,
priority,
components,
depth + 1);
}
}

public record NodeHit(LytNode node, FlowInteractionPath flowPath, int localX, int localY) {

public NodeHit(LytNode node, @Nullable FlowInteractionPath flowPath, int localX, int localY) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,20 @@ public LytMermaidFlowchart(FlowchartDocument flowchart, String sourceText, Map<S
btn.setHoverColor(SymbolicColor.ICON_BUTTON_HOVER);
toolbar.addButton(btn);
}
toolbar.addButton(createResetViewButton());

append(toolbar);
append(canvas);
}

private LytButton createResetViewButton() {
LytButton button = new LytButton(LytCodeBlockToolbar.RESET_VIEW_SPRITE, new LytSize(16, 16));
button.setOnClick(screen -> canvas.resetView());
button.setTooltipText(GuidebookText.ResetView.text());
button.setHoverColor(SymbolicColor.ICON_BUTTON_HOVER);
return button;
}

public void setPreferredSize(int width, int height) {
canvas.setPreferredSize(width, height);
toolbar.setPreferredWidth(width);
Expand Down
Loading