Skip to content

Commit

Permalink
Do not crash if missing texture file when in production (#63)
Browse files Browse the repository at this point in the history
Still crashes when in dev
  • Loading branch information
Nightenom committed Nov 3, 2023
1 parent 49a6d10 commit 928de6a
Show file tree
Hide file tree
Showing 13 changed files with 203 additions and 60 deletions.
9 changes: 7 additions & 2 deletions src/main/java/com/ldtteam/blockui/BOScreen.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import net.minecraftforge.client.ForgeRenderTypes;
import org.lwjgl.glfw.GLFW;

import java.util.Objects;

/**
* Wraps MineCrafts GuiScreen for BlockOut's Window.
*/
Expand Down Expand Up @@ -102,7 +104,10 @@ public void render(final PoseStack ms, final int mx, final int my, final float f
try
{
window.draw(newMs, calcRelativeX(mx), calcRelativeY(my));
applyCursor();
if (ms.minecraft.screen == this)
{
applyCursor();
}
window.drawLast(newMs, calcRelativeX(mx), calcRelativeY(my));
}
catch (final Exception e)
Expand Down Expand Up @@ -188,7 +193,7 @@ else if (keyCode == GLFW.GLFW_MOUSE_BUTTON_RIGHT)
{
final CrashReport crashReport = CrashReport.forThrowable(e, "MousePressed event for BO screen");
final CrashReportCategory category = crashReport.addCategory("BO screen mouse event details");
category.setDetail("XML res loc", () -> window.getXmlResourceLocation().toString());
category.setDetail("XML res loc", () -> Objects.toString(window.getXmlResourceLocation()));
category.setDetail("GLFW mouse key value", () -> Integer.toString(keyCode));
throw new ReportedException(crashReport);
}
Expand Down
12 changes: 0 additions & 12 deletions src/main/java/com/ldtteam/blockui/UiRenderMacros.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.ldtteam.blockui;

import com.ldtteam.blockui.util.resloc.OutOfJarResourceLocation;
import com.ldtteam.blockui.util.texture.OutOfJarTexture;
import com.mojang.blaze3d.platform.Lighting;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.BufferBuilder;
Expand Down Expand Up @@ -428,7 +426,6 @@ public static void blit(final PoseStack ps,
final float uMax,
final float vMax)
{
checkOutOfJarResLoc(rl);
Minecraft.getInstance().getTextureManager().bindForSetup(rl);
RenderSystem.setShaderTexture(0, rl);
RenderSystem.setShader(GameRenderer::getPositionTexShader);
Expand All @@ -443,14 +440,6 @@ public static void blit(final PoseStack ps,
Tesselator.getInstance().end();
}

private static void checkOutOfJarResLoc(final ResourceLocation rl)
{
if (rl instanceof final OutOfJarResourceLocation outOfJarResLoc)
{
OutOfJarTexture.assertLoaded(outOfJarResLoc, Minecraft.getInstance().getTextureManager());
}
}

/**
* Draws texture without scaling so one texel is one pixel, using repeatable texture center.
* TODO: Nightenom - rework to better algoritm from pgr, also texture extensions?
Expand Down Expand Up @@ -552,7 +541,6 @@ protected static void blitRepeatable(final PoseStack ps,
// bot left corner
populateBlitTriangles(buffer, mat, xEnd, xEnd + uLeft, yEnd, yEnd + vLeft, restMinU, restMaxU, restMinV, restMaxV);

checkOutOfJarResLoc(rl);
Minecraft.getInstance().getTextureManager().bindForSetup(rl);
RenderSystem.setShaderTexture(0, rl);
RenderSystem.setShader(GameRenderer::getPositionTexShader);
Expand Down
25 changes: 22 additions & 3 deletions src/main/java/com/ldtteam/blockui/controls/Image.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,22 @@
import com.ldtteam.blockui.mod.Log;
import com.ldtteam.blockui.util.records.SizeI;
import com.ldtteam.blockui.util.resloc.OutOfJarResourceLocation;
import com.ldtteam.blockui.util.texture.OutOfJarTexture;
import com.ldtteam.blockui.util.texture.SpriteTexture;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.texture.MissingTextureAtlasSprite;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Tuple;
import net.minecraftforge.fml.loading.FMLEnvironment;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.NoSuchFileException;
import java.util.Iterator;
import java.util.Objects;

Expand Down Expand Up @@ -65,8 +70,7 @@ public Image(final PaneParams params)

private void loadMapDimensions(final ResourceLocation rl)
{
final SpriteTexture sprite = SpriteTexture.checkLoaded(rl, Minecraft.getInstance().getTextureManager(), Minecraft.getInstance().getResourceManager());
if (sprite != null)
if (OutOfJarTexture.assertLoadedDefaultManagers(rl) instanceof final SpriteTexture sprite)
{
mapWidth = sprite.width();
mapHeight = sprite.height();
Expand Down Expand Up @@ -119,6 +123,9 @@ public void setMapDimensions(final int height, final int width)
*/
public static SizeI getImageDimensions(final ResourceLocation resourceLocation)
{
// this is called by most of image classes -> parse our textures
OutOfJarTexture.assertLoadedDefaultManagers(resourceLocation);

final int pos = resourceLocation.getPath().lastIndexOf(".");

if (pos == -1)
Expand All @@ -139,6 +146,10 @@ public static SizeI getImageDimensions(final ResourceLocation resourceLocation)

return new SizeI(reader.getWidth(reader.getMinIndex()), reader.getHeight(reader.getMinIndex()));
}
catch (final NoSuchFileException | FileNotFoundException e)
{
// dont log these, texture manager logs it anyway
}
catch (final IOException e)
{
Log.getLogger().warn(e);
Expand Down Expand Up @@ -208,7 +219,15 @@ public void setImage(final ResourceLocation rl, final boolean keepUv)
@Override
public void drawSelf(final PoseStack ms, final double mx, final double my)
{
Objects.requireNonNull(resourceLocation, () -> id + " | " + window.getXmlResourceLocation());
if (!FMLEnvironment.production)
{
Objects.requireNonNull(resourceLocation, () -> id + " | " + window.getXmlResourceLocation());
}
else if (resourceLocation == null)
{
resourceLocation = MissingTextureAtlasSprite.getLocation();
}

RenderSystem.enableBlend();
RenderSystem.defaultBlendFunc();

Expand Down
12 changes: 6 additions & 6 deletions src/main/java/com/ldtteam/blockui/mod/ClientEventSubscriber.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,12 @@
import com.ldtteam.blockui.BOScreen;
import com.ldtteam.blockui.controls.Button;
import com.ldtteam.blockui.controls.ButtonVanilla;
import com.ldtteam.blockui.Pane;
import com.ldtteam.blockui.controls.Text;
import com.ldtteam.blockui.controls.Image;
import com.ldtteam.blockui.hooks.HookManager;
import com.ldtteam.blockui.hooks.HookRegistries;
import com.ldtteam.blockui.mod.container.ContainerHook;
import com.ldtteam.blockui.util.records.SizeI;
import com.ldtteam.blockui.util.resloc.OutOfJarResourceLocation;
import com.ldtteam.blockui.views.BOWindow;
import com.ldtteam.blockui.views.ScrollingList;
import com.mojang.blaze3d.platform.InputConstants;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft;
Expand All @@ -29,7 +27,6 @@
import net.minecraftforge.eventbus.api.EventPriority;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.lwjgl.glfw.GLFW;

import java.util.function.Consumer;
Expand Down Expand Up @@ -67,7 +64,10 @@ public static void onClientTickEvent(final ClientTickEvent event)
if (InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), GLFW.GLFW_KEY_X))
{
final BOWindow window = new BOWindow();
window.addChild(createTestGuiButton(0, "General All-in-one", new ResourceLocation(BlockUI.MOD_ID, "gui/test.xml")));
window.addChild(createTestGuiButton(0, "General All-in-one", new ResourceLocation(BlockUI.MOD_ID, "gui/test.xml"), parent -> {
parent.findPaneOfTypeByID("missing_out_of_jar", Image.class).setImage(OutOfJarResourceLocation.ofMinecraftFolder(BlockUI.MOD_ID, "missing_out_of_jar.png"), false);
parent.findPaneOfTypeByID("working_out_of_jar", Image.class).setImage(OutOfJarResourceLocation.ofMinecraftFolder(BlockUI.MOD_ID, "../../src/test/resources/button.png"), false);
}));
window.addChild(createTestGuiButton(1, "Tooltip Positioning", new ResourceLocation(BlockUI.MOD_ID, "gui/test2.xml")));
window.addChild(createTestGuiButton(2, "ItemIcon To BlockState", new ResourceLocation(BlockUI.MOD_ID, "gui/test3.xml"), BlockStateTestGui::setup));
window.addChild(createTestGuiButton(3, "Dynamic ScrollingLists", new ResourceLocation(BlockUI.MOD_ID, "gui/test4.xml"), DynamicScrollingListGui::setup));
Expand Down
37 changes: 28 additions & 9 deletions src/main/java/com/ldtteam/blockui/util/cursor/Cursor.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,41 @@
public interface Cursor
{
/** Probably arrow, but OS dependend */
public static final Cursor DEFAULT = () -> CursorUtils.setStandardCursor(StandardCursor.DEFAULT);
public static final Cursor ARROW = () -> CursorUtils.setStandardCursor(StandardCursor.ARROW);
public static final Cursor TEXT_CURSOR = () -> CursorUtils.setStandardCursor(StandardCursor.TEXT_CURSOR);
public static final Cursor CROSSHAIR = () -> CursorUtils.setStandardCursor(StandardCursor.CROSSHAIR);
public static final Cursor HAND = () -> CursorUtils.setStandardCursor(StandardCursor.HAND);
public static final Cursor HORIZONTAL_RESIZE = () -> CursorUtils.setStandardCursor(StandardCursor.HORIZONTAL_RESIZE);
public static final Cursor VERTICAL_RESIZE = () -> CursorUtils.setStandardCursor(StandardCursor.VERTICAL_RESIZE);
public static final Cursor RESIZE = () -> CursorUtils.setStandardCursor(StandardCursor.RESIZE);
public static final Cursor DEFAULT = named(() -> CursorUtils.setStandardCursor(StandardCursor.DEFAULT), StandardCursor.DEFAULT);
public static final Cursor ARROW = named(() -> CursorUtils.setStandardCursor(StandardCursor.ARROW), StandardCursor.ARROW);
public static final Cursor TEXT_CURSOR = named(() -> CursorUtils.setStandardCursor(StandardCursor.TEXT_CURSOR), StandardCursor.TEXT_CURSOR);
public static final Cursor CROSSHAIR = named(() -> CursorUtils.setStandardCursor(StandardCursor.CROSSHAIR), StandardCursor.CROSSHAIR);
public static final Cursor HAND = named(() -> CursorUtils.setStandardCursor(StandardCursor.HAND), StandardCursor.HAND);
public static final Cursor HORIZONTAL_RESIZE = named(() -> CursorUtils.setStandardCursor(StandardCursor.HORIZONTAL_RESIZE), StandardCursor.HORIZONTAL_RESIZE);
public static final Cursor VERTICAL_RESIZE = named(() -> CursorUtils.setStandardCursor(StandardCursor.VERTICAL_RESIZE), StandardCursor.VERTICAL_RESIZE);
public static final Cursor RESIZE = named(() -> CursorUtils.setStandardCursor(StandardCursor.RESIZE), StandardCursor.RESIZE);

public static Cursor of(final ResourceLocation resLoc)
{
return () -> CursorUtils.setCursorImage(resLoc);
CursorUtils.loadCursorTexture(resLoc);
return named(() -> CursorUtils.setCursorImage(resLoc), resLoc);
}

/**
* Apply cursor to main window
*/
void apply();

static Cursor named(final Runnable applier, final Object name)
{
return new Cursor()
{
@Override
public void apply()
{
applier.run();
}

@Override
public String toString()
{
return "Cursor: " + name;
}
};
}
}
44 changes: 37 additions & 7 deletions src/main/java/com/ldtteam/blockui/util/cursor/CursorUtils.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
package com.ldtteam.blockui.util.cursor;

import com.ldtteam.blockui.mod.BlockUI;
import com.ldtteam.blockui.util.texture.CursorTexture;
import com.ldtteam.blockui.util.texture.IsOurTexture;
import com.ldtteam.blockui.util.texture.MissingCursorTexture;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.texture.AbstractTexture;
import net.minecraft.client.renderer.texture.MissingTextureAtlasSprite;
import net.minecraft.client.renderer.texture.TextureManager;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.fml.loading.FMLEnvironment;
import org.lwjgl.glfw.GLFW;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -21,27 +26,52 @@ public class CursorUtils

/**
* Sets cursor image using given resource location.
* Do not forget to load given resLoc as CursorTexture first
*
* @param rl image resource location
* @return cursor texture reference
* @see #loadCursorTexture(ResourceLocation)
*/
public static CursorTexture setCursorImage(final ResourceLocation rl)
{
AbstractTexture texture = Minecraft.getInstance().getTextureManager().getTexture(rl);
if (texture == MissingTextureAtlasSprite.getTexture())
{
texture = MissingCursorTexture.INSTANCE;
}

if (!(texture instanceof final CursorTexture cursorTexture))
{
throw new IllegalArgumentException("Did you forget to load CursorTexture for: " + rl);
}

cursorTexture.setCursor();
return cursorTexture;
}

/**
* Makes sure client global texture manager has CursorTexture assigned to given resLoc
*
* @param resLoc cursor file location
*/
public static void loadCursorTexture(final ResourceLocation resLoc)
{
final TextureManager texManager = Minecraft.getInstance().getTextureManager();
final AbstractTexture texture = texManager.getTexture(resLoc, null);
if (!(texture instanceof CursorTexture))
{
if (IsOurTexture.isOur(texture))
{
LOGGER.warn("Trying to use special BlockUI texture as cursor? Things may not work well: " + rl.toString());
LOGGER.warn("Trying to use special BlockUI texture as cursor? Things may not work well: " + resLoc.toString());
}

texture = new CursorTexture(rl);
Minecraft.getInstance().getTextureManager().register(rl, texture);
}
texManager.register(resLoc, new CursorTexture(resLoc));

final CursorTexture cursorTexture = (CursorTexture) texture;
cursorTexture.setCursor();
return cursorTexture;
if (!FMLEnvironment.production && texManager.getTexture(resLoc) == MissingTextureAtlasSprite.getTexture() && !resLoc.getNamespace().equals(BlockUI.MOD_ID))
{
throw new IllegalArgumentException("Missing texture: " + resLoc);
}
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import net.minecraft.server.packs.resources.ResourceMetadata;
import org.jetbrains.annotations.Nullable;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
Expand Down Expand Up @@ -54,7 +55,7 @@ public static boolean fileExists(final ResourceLocation resLoc, final ResourceMa
return fallbackManager.getResource(resLoc).isPresent();
}

public static Resource getResourceHandle(final ResourceLocation resLoc, final ResourceManager fallbackManager)
public static Resource getResourceHandle(final ResourceLocation resLoc, final ResourceManager fallbackManager) throws IOException
{
if (resLoc instanceof final OutOfJarResourceLocation nioResLoc)
{
Expand All @@ -63,7 +64,7 @@ public static Resource getResourceHandle(final ResourceLocation resLoc, final Re
new OutOfJarResource(nioResLoc, parseMetadata(mcmeta)) :
new OutOfJarResource(nioResLoc);
}
return fallbackManager.getResource(resLoc).orElseThrow(() -> new RuntimeException("File not found: " + resLoc));
return fallbackManager.getResource(resLoc).orElseThrow(() -> new FileNotFoundException("File not found: " + resLoc));
}

private static IoSupplier<ResourceMetadata> parseMetadata(final OutOfJarResourceLocation path)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public class CursorTexture extends AbstractTexture
private int hotspotY = 0;
private long glfwCursorAddress = 0;
@Nullable
private NativeImage nativeImage = null;
protected NativeImage nativeImage = null;

public CursorTexture(final ResourceLocation resLoc)
{
Expand Down Expand Up @@ -87,7 +87,7 @@ private void onDataChange()
}
}

private void destroyCursorHandle()
protected void destroyCursorHandle()
{
if (glfwCursorAddress != 0)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.ldtteam.blockui.util.texture;

import com.ldtteam.blockui.mod.BlockUI;
import net.minecraft.client.renderer.texture.MissingTextureAtlasSprite;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.ResourceManager;

import java.io.IOException;

/**
* Backed by missing vanilla texture.
*/
public final class MissingCursorTexture extends CursorTexture
{
public static final MissingCursorTexture INSTANCE = new MissingCursorTexture();

private MissingCursorTexture()
{
super(new ResourceLocation(BlockUI.MOD_ID, "missing_cursor_texture"));
super.nativeImage = MissingTextureAtlasSprite.getTexture().getPixels();
}

@Override
public void close()
{
// Noop
}

@Override
protected void destroyCursorHandle()
{
// Noop
}

@Override
public void load(final ResourceManager resourceManager) throws IOException
{
// Noop
}
}
Loading

0 comments on commit 928de6a

Please sign in to comment.