From 7c371082d3ae1d583c270e7667f18e2b204dea16 Mon Sep 17 00:00:00 2001 From: sisby-folk Date: Mon, 13 Jan 2025 23:49:01 +1100 Subject: [PATCH] add handheld atlas closes #86 partially addresses #254 --- gradle.properties | 2 +- .../sisby/antique_atlas/AntiqueAtlas.java | 7 + .../sisby/antique_atlas/MarkerTexture.java | 39 ++++- .../sisby/antique_atlas/gui/AtlasScreen.java | 126 ++++++++------- .../mixin/MixinHeldItemRenderer.java | 146 ++++++++++++++++++ .../antique_atlas/mixin/MixinItemModels.java | 21 +++ .../antique_atlas/mixin/MixinItemStack.java | 31 ++++ .../antique_atlas/mixin/MixinModelLoader.java | 27 ++++ .../sisby/antique_atlas/util/DrawBatcher.java | 41 +++-- .../sisby/antique_atlas/util/DrawUtil.java | 21 +-- .../sisby/antique_atlas/util/MathUtil.java | 16 ++ src/main/resources/antique_atlas.mixins.json | 15 ++ .../antique_atlas/models/item/atlas.json | 6 + .../antique_atlas/textures/item/atlas.png | Bin 0 -> 3179 bytes src/main/resources/fabric.mod.json | 3 + 15 files changed, 422 insertions(+), 79 deletions(-) create mode 100644 src/main/java/folk/sisby/antique_atlas/mixin/MixinHeldItemRenderer.java create mode 100644 src/main/java/folk/sisby/antique_atlas/mixin/MixinItemModels.java create mode 100644 src/main/java/folk/sisby/antique_atlas/mixin/MixinItemStack.java create mode 100644 src/main/java/folk/sisby/antique_atlas/mixin/MixinModelLoader.java create mode 100644 src/main/resources/antique_atlas.mixins.json create mode 100644 src/main/resources/assets/antique_atlas/models/item/atlas.json create mode 100644 src/main/resources/assets/antique_atlas/textures/item/atlas.png diff --git a/gradle.properties b/gradle.properties index d6067159e..cad1846da 100644 --- a/gradle.properties +++ b/gradle.properties @@ -18,7 +18,7 @@ authors=Hunternif, tyra314, Sisby folk contributors=Kenkron, asiekierka, Haven King, TheCodeWarrior, osipxd, coolAlias, TehNut, lumiscosity, frodolon license=LGPL-3.0-or-later # Mod Version -baseVersion=2.10.1 +baseVersion=2.11.0 # Branch Metadata branch=1.20 tagBranch=1.20 diff --git a/src/main/java/folk/sisby/antique_atlas/AntiqueAtlas.java b/src/main/java/folk/sisby/antique_atlas/AntiqueAtlas.java index 91d56f5da..3e915ae96 100644 --- a/src/main/java/folk/sisby/antique_atlas/AntiqueAtlas.java +++ b/src/main/java/folk/sisby/antique_atlas/AntiqueAtlas.java @@ -14,6 +14,9 @@ import net.fabricmc.fabric.api.event.lifecycle.v1.CommonLifecycleEvents; import net.fabricmc.fabric.api.resource.ResourceManagerHelper; import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.client.item.ModelPredicateProviderRegistry; +import net.minecraft.client.util.ModelIdentifier; +import net.minecraft.item.Items; import net.minecraft.registry.RegistryKeys; import net.minecraft.resource.ResourceType; import net.minecraft.util.Identifier; @@ -29,6 +32,8 @@ public class AntiqueAtlas implements ClientModInitializer { public static final AntiqueAtlasConfig CONFIG = AntiqueAtlasConfig.createToml(FabricLoader.getInstance().getConfigDir(), "", "antique-atlas", AntiqueAtlasConfig.class); public static ScreenState lastState = new ScreenState<>(); + public static final ModelIdentifier ATLAS_MODEL = new ModelIdentifier(AntiqueAtlas.id("atlas"), "inventory"); + public static Identifier id(String path) { return path.contains(":") ? new Identifier(path) : new Identifier(ID, path); } @@ -51,6 +56,8 @@ public void onInitializeClient() { ClientPlayConnectionEvents.DISCONNECT.register(((handler, client) -> BiomeTileProviders.getInstance().clearFallbacks())); ClientPlayConnectionEvents.DISCONNECT.register(((handler, client) -> WorldAtlasData.WORLDS.clear())); + ModelPredicateProviderRegistry.register(Items.BOOK, AntiqueAtlas.id("atlas"), ((stack, world, entity, seed) -> stack.getName().getString().contains("Antique Atlas") ? 1.0F : 0.0F)); + WorldSummary.enableTerrain(); WorldSummary.enableStructures(); WorldSummary.enableLandmarks(); diff --git a/src/main/java/folk/sisby/antique_atlas/MarkerTexture.java b/src/main/java/folk/sisby/antique_atlas/MarkerTexture.java index 805e915c8..d6f1767ce 100644 --- a/src/main/java/folk/sisby/antique_atlas/MarkerTexture.java +++ b/src/main/java/folk/sisby/antique_atlas/MarkerTexture.java @@ -1,8 +1,12 @@ package folk.sisby.antique_atlas; import com.mojang.blaze3d.systems.RenderSystem; +import folk.sisby.antique_atlas.util.DrawBatcher; import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.util.Identifier; +import net.minecraft.util.math.ColorHelper; import net.minecraft.util.math.MathHelper; import org.joml.Vector2d; @@ -67,25 +71,56 @@ public void drawIcon(DrawContext context, int x, int y, float[] accent) { } public void draw(DrawContext context, double markerX, double markerY, float markerScale, int tileChunks, float[] accent, float tint, float alpha) { + if (alpha == 0) return; context.getMatrices().push(); context.getMatrices().translate(markerX, markerY, 0.0); context.getMatrices().scale(markerScale, markerScale, 1.0F); + RenderSystem.setShaderColor(tint, tint, tint, alpha); if (tileChunks > 1 && mipLevels > 0) { int mipLevel = MathHelper.clamp(MathHelper.ceilLog2(tileChunks), 0, mipLevels); context.drawTexture(id, offsetX / (1 << mipLevel), offsetY / (1 << mipLevel), getU(mipLevel), 0, textureWidth / (1 << mipLevel), textureHeight / (1 << mipLevel), fullTextureWidth(), textureHeight); if (accentId != null && accent != null) { RenderSystem.setShaderColor(tint * accent[0], tint * accent[1], tint * accent[2], alpha); context.drawTexture(accentId, offsetX / (1 << mipLevel), offsetY / (1 << mipLevel), getU(mipLevel), 0, textureWidth / (1 << mipLevel), textureHeight / (1 << mipLevel), fullTextureWidth(), textureHeight); - RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); } } else { context.drawTexture(id, offsetX, offsetY, 0, 0, textureWidth, textureHeight, fullTextureWidth(), textureHeight); if (accentId != null && accent != null) { RenderSystem.setShaderColor(tint * accent[0], tint * accent[1], tint * accent[2], alpha); context.drawTexture(accentId, offsetX, offsetY, 0, 0, textureWidth, textureHeight, fullTextureWidth(), textureHeight); - RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); } } + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); context.getMatrices().pop(); } + + public void draw(MatrixStack matrices, VertexConsumerProvider vertexConsumers, double markerX, double markerY, float markerScale, int tileChunks, float[] accent, float tint, float alpha, int light) { + if (alpha == 0) return; + matrices.push(); + matrices.translate(markerX, markerY, 0.0); + matrices.scale(markerScale, markerScale, 1.0F); + int mainArgb = ColorHelper.Argb.getArgb((int) (alpha * 255), (int) (tint * 255), (int) (tint * 255), (int) (tint * 255)); + int accentArgb = accent != null ? ColorHelper.Argb.getArgb((int) (alpha * 255), (int) (tint * accent[0] * 255), (int) (tint * accent[1] * 255), (int) (tint * accent[2] * 255)) : 0; + if (tileChunks > 1 && mipLevels > 0) { + int mipLevel = MathHelper.clamp(MathHelper.ceilLog2(tileChunks), 0, mipLevels); + try (DrawBatcher batcher = new DrawBatcher(matrices, vertexConsumers, id, fullTextureWidth(), textureHeight, light)) { + batcher.add(offsetX / (1 << mipLevel), offsetY / (1 << mipLevel), textureWidth / (1 << mipLevel), textureHeight / (1 << mipLevel), getU(mipLevel), 0, textureWidth / (1 << mipLevel), textureHeight / (1 << mipLevel), mainArgb); + } + if (accentId != null && accent != null) { + try (DrawBatcher batcher = new DrawBatcher(matrices, vertexConsumers, accentId, fullTextureWidth(), textureHeight, light)) { + batcher.add(offsetX / (1 << mipLevel), offsetY / (1 << mipLevel), textureWidth / (1 << mipLevel), textureHeight / (1 << mipLevel), getU(mipLevel), 0, textureWidth / (1 << mipLevel), textureHeight / (1 << mipLevel), accentArgb); + } + } + } else { + try (DrawBatcher batcher = new DrawBatcher(matrices, vertexConsumers, id, fullTextureWidth(), textureHeight, light)) { + batcher.add(offsetX, offsetY, textureWidth, textureHeight, 0, 0, textureWidth, textureHeight, mainArgb); + } + if (accentId != null && accent != null) { + try (DrawBatcher batcher = new DrawBatcher(matrices, vertexConsumers, accentId, fullTextureWidth(), textureHeight, light)) { + batcher.add(offsetX, offsetY, textureWidth, textureHeight, 0, 0, textureWidth, textureHeight, accentArgb); + } + } + } + matrices.pop(); + } } diff --git a/src/main/java/folk/sisby/antique_atlas/gui/AtlasScreen.java b/src/main/java/folk/sisby/antique_atlas/gui/AtlasScreen.java index 98130699b..bfe82e67f 100644 --- a/src/main/java/folk/sisby/antique_atlas/gui/AtlasScreen.java +++ b/src/main/java/folk/sisby/antique_atlas/gui/AtlasScreen.java @@ -28,7 +28,9 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.option.KeyBinding; +import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.sound.PositionedSoundInstance; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.sound.SoundCategory; import net.minecraft.sound.SoundEvents; @@ -38,6 +40,7 @@ import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; +import net.minecraft.util.math.ColorHelper; import net.minecraft.util.math.ColumnPos; import net.minecraft.util.math.MathHelper; import org.joml.Vector2d; @@ -70,11 +73,11 @@ public class AtlasScreen extends Component { private static final Text TEXT_ADD_MARKER = Text.translatable("gui.antique_atlas.addMarker"); private static final Text TEXT_ADD_MARKER_HERE = Text.translatable("gui.antique_atlas.addMarkerHere"); - private static final int MAP_BORDER_WIDTH = 17; - private static final int MAP_BORDER_HEIGHT = 11; - private static final float PLAYER_ROTATION_STEPS = 16; - private static final int PLAYER_ICON_WIDTH = 7; - private static final int PLAYER_ICON_HEIGHT = 8; + public static final int MAP_BORDER_WIDTH = 17; + public static final int MAP_BORDER_HEIGHT = 11; + public static final float PLAYER_ROTATION_STEPS = 16; + public static final int PLAYER_ICON_WIDTH = 7; + public static final int PLAYER_ICON_HEIGHT = 8; private static final int BOOKMARK_SPACING = 2; public static final int MARKER_SIZE = 32; /** @@ -547,22 +550,19 @@ private void resetZoom() { public void render(DrawContext context, int mouseX, int mouseY, float par3) { super.renderBackground(context); mapScale = getMapScale(); - RenderSystem.setShaderColor(1, 1, 1, 1); + if (fullscreen) { int left_width = bookWidth / 2 - 15; context.drawNineSlicedTexture(BOOK_FULLSCREEN, getGuiX(), getGuiY(), left_width, bookHeight, 50, 140, 218, 0, 0); context.drawNineSlicedTexture(BOOK_FULLSCREEN, getGuiX() + left_width, getGuiY(), 29, bookHeight, 50, 29, 218, 140, 0); context.drawNineSlicedTexture(BOOK_FULLSCREEN_R, getGuiX() + left_width + 29, getGuiY(), left_width + 1, bookHeight, 50, 140, 218, 0, 0); } else { - context.drawTexture(BOOK, getGuiX(), getGuiY(), 0, 0, 310, 218, 310, 218); + context.drawTexture(BOOK, getGuiX(), getGuiY(), 0, 0, bookWidth, bookHeight, bookWidth, bookHeight); } if (worldAtlasData == null) return; - if (state.is(DELETING_MARKER)) { - RenderSystem.setShaderColor(1, 1, 1, 0.5f); - } double guiScale = client.getWindow().getScaleFactor(); RenderSystem.enableScissor( (int) (guiScale * (getGuiX() + MAP_BORDER_WIDTH)), @@ -578,44 +578,25 @@ public void render(DrawContext context, int mouseX, int mouseY, float par3) { int mapStartChunkX = MathUtil.roundToBase(screenXToWorldX(getGuiX()) >> 4, tileChunks) - 2 * tileChunks; int mapStartChunkZ = MathUtil.roundToBase(screenYToWorldZ(getGuiY()) >> 4, tileChunks) - 2 * tileChunks; int mapEndChunkX = MathUtil.roundToBase(screenXToWorldX(getGuiX() + bookWidth) >> 4, tileChunks) + 2 * tileChunks; - int mapEndChunkZ = MathUtil.roundToBase(screenYToWorldZ(getGuiY() + bookWidth) >> 4, tileChunks) + 2 * tileChunks; + int mapEndChunkZ = MathUtil.roundToBase(screenYToWorldZ(getGuiY() + bookHeight) >> 4, tileChunks) + 2 * tileChunks; double mapStartScreenX = worldXToScreenX(mapStartChunkX << 4); double mapStartScreenY = worldZToScreenY(mapStartChunkZ << 4); TileRenderIterator tiles = new TileRenderIterator(worldAtlasData); tiles.setScope(new Rect(mapStartChunkX, mapStartChunkZ, mapEndChunkX, mapEndChunkZ)); tiles.setStep(tileChunks); - - context.getMatrices().push(); - context.getMatrices().translate(mapStartScreenX, mapStartScreenY, 0); - context.getMatrices().scale((float) ((double) mapScale / guiScale), (float) ((double) mapScale / guiScale), 1.0F); - - Map> tileTextures = new Reference2ObjectArrayMap<>(); - for (SubTileQuartet subTiles : tiles) { - for (SubTile subtile : subTiles) { - if (subtile == null || subtile.texture == null) continue; - tileTextures.computeIfAbsent(subtile.texture, k -> new ArrayList<>()).add(subtile.copy()); - } - } - int subTilePixels = tilePixels / 2; - tileTextures.forEach((texture, subtiles) -> { - try (DrawBatcher batcher = new DrawBatcher(context, texture.id(), 32, 48)) { - for (SubTile subtile : subtiles) { - batcher.add(subtile.x * subTilePixels, subtile.y * subTilePixels, subTilePixels, subTilePixels, subtile.getTextureU() * 8, subtile.getTextureV() * 8, 8, 8); - } - } - }); - - context.getMatrices().pop(); + + RenderSystem.setShaderColor(1, 1, 1, state.is(DELETING_MARKER) ? 0.5f : 1.0f); + renderTiles(context.getMatrices(), null, getGuiX() + MAP_BORDER_WIDTH, getGuiY() + MAP_BORDER_HEIGHT, mapWidth, mapHeight, mapStartScreenX, mapStartScreenY, mapScale, tilePixels, guiScale, 15728640, tiles); + RenderSystem.setShaderColor(1, 1, 1, 1); // Overlay the frame so that edges of the map are smooth: - RenderSystem.setShaderColor(1, 1, 1, 1); if (fullscreen) { int left_width = bookWidth / 2 - 15; context.drawNineSlicedTexture(BOOK_FRAME_FULLSCREEN, getGuiX(), getGuiY(), left_width, bookHeight, 50, 140, 218, 0, 0); context.drawNineSlicedTexture(BOOK_FRAME_FULLSCREEN, getGuiX() + left_width, getGuiY(), 29, bookHeight, 50, 29, 218, 140, 0); context.drawNineSlicedTexture(BOOK_FRAME_FULLSCREEN_R, getGuiX() + left_width + 29, getGuiY(), left_width + 1, bookHeight, 50, 140, 218, 0, 0); } else { - context.drawTexture(BOOK_FRAME, getGuiX(), getGuiY(), 0, 0, 310, 218, 310, 218); + context.drawTexture(BOOK_FRAME, getGuiX(), getGuiY(), 0, 0, bookWidth, bookHeight, bookWidth, bookHeight); } context.getMatrices().push(); @@ -667,7 +648,7 @@ public void render(DrawContext context, int mouseX, int mouseY, float par3) { context.drawNineSlicedTexture(BOOK_FRAME_NARROW_FULLSCREEN, getGuiX() + left_width, getGuiY(), 29, bookHeight, 50, 29, 218, 140, 0); context.drawNineSlicedTexture(BOOK_FRAME_NARROW_FULLSCREEN_R, getGuiX() + left_width + 29, getGuiY(), left_width + 1, bookHeight, 50, 140, 218, 0, 0); } else { - context.drawTexture(BOOK_FRAME_NARROW, getGuiX(), getGuiY(), 0, 0, 310, 218, 310, 218); + context.drawTexture(BOOK_FRAME_NARROW, getGuiX(), getGuiY(), 0, 0, bookWidth, bookHeight, bookWidth, bookHeight); } markerScrollBox.getViewport().setHidden(state.is(HIDING_MARKERS)); @@ -719,6 +700,34 @@ public void render(DrawContext context, int mouseX, int mouseY, float par3) { } } + public static void renderTiles(MatrixStack matrices, VertexConsumerProvider vertexConsumers, int mapX, int mapY, int mapWidth, int mapHeight, double mapStartScreenX, double mapStartScreenY, double mapScale, int pixelsPerTile, double guiScale, int light, TileRenderIterator tiles) { + matrices.push(); + matrices.translate(mapStartScreenX, mapStartScreenY, 0); + matrices.scale((float) (mapScale / guiScale), (float) (mapScale / guiScale), 1.0F); + + Map> tileTextures = new Reference2ObjectArrayMap<>(); + for (SubTileQuartet subTiles : tiles) { + for (SubTile subtile : subTiles) { + if (subtile == null || subtile.texture == null) continue; + tileTextures.computeIfAbsent(subtile.texture, k -> new ArrayList<>()).add(subtile.copy()); + } + } + int subTilePixels = pixelsPerTile / 2; + tileTextures.forEach((texture, subtiles) -> { + try (DrawBatcher batcher = new DrawBatcher(matrices, vertexConsumers, texture.id(), 32, 48, light)) { + for (SubTile subtile : subtiles) { + int drawX = subtile.x * subTilePixels; + int drawY = subtile.y * subTilePixels; + // a non-scope bounds check allows subtile-level accuracy, and keeps border tiling accurate. + if (drawX * (guiScale / mapScale) > mapX + mapWidth - mapStartScreenX || drawY * (guiScale / mapScale) > mapY + mapHeight - mapStartScreenY || (drawX + subTilePixels) * (guiScale / mapScale) < mapX - mapStartScreenX || (drawY + subTilePixels) * (guiScale / mapScale) < mapY - mapStartScreenY) continue; + batcher.add(drawX, drawY, subTilePixels, subTilePixels, subtile.getTextureU() * 8, subtile.getTextureV() * 8, 8, 8, 0xFFFFFFFF); + } + } + }); + + matrices.pop(); + } + private void renderPlayer(DrawContext context, PlayerSummary player, float iconScale, boolean hovering, boolean self) { double playerOffsetX = worldXToScreenX(player.pos().getX()) - getGuiX(); double playerOffsetY = worldZToScreenY(player.pos().getZ()) - getGuiY(); @@ -729,12 +738,10 @@ private void renderPlayer(DrawContext context, PlayerSummary player, float iconS // Draw the icon: float tint = (player.online() ? 1 : 0.5f) * (hovering ? 0.9f : 1); float greenTint = self ? 1 : 0.7f; - RenderSystem.setShaderColor(tint, tint * greenTint, tint, state.is(PLACING_MARKER) ? 0.5f : 1); + int argb = ColorHelper.Argb.getArgb(state.is(PLACING_MARKER) ? 127 : 255, (int) (tint * 255), (int) (tint * greenTint * 255), (int) (tint * 255)); float playerRotation = ((float) Math.round(player.yaw() / 360f * PLAYER_ROTATION_STEPS) / PLAYER_ROTATION_STEPS) * 360f; - DrawUtil.drawCenteredWithRotation(context, PLAYER, playerOffsetX, playerOffsetY, iconScale, PLAYER_ICON_WIDTH, PLAYER_ICON_HEIGHT, playerRotation); - - RenderSystem.setShaderColor(1, 1, 1, 1); + DrawUtil.drawCenteredWithRotation(context.getMatrices(), null, PLAYER, playerOffsetX, playerOffsetY, iconScale, PLAYER_ICON_WIDTH, PLAYER_ICON_HEIGHT, playerRotation, 15728640, argb); if (hovering && !self) { context.drawTooltip(textRenderer, Text.literal(player.username()).formatted(player.online() ? Formatting.LIGHT_PURPLE : Formatting.GRAY), (int) getMouseX() - getGuiX(), (int) getMouseY() - getGuiY()); @@ -747,7 +754,6 @@ private void renderMarker(DrawContext context, Landmark landmark, MarkerTextu float tint = hovering ? 0.8f : 1.0f; float alpha = state.is(PLACING_MARKER) || (state.is(DELETING_MARKER) && !editable) || (editable && markerX <= MAP_BORDER_WIDTH || markerX >= mapWidth + MAP_BORDER_WIDTH || markerY <= MAP_BORDER_HEIGHT || markerY >= mapHeight + MAP_BORDER_HEIGHT) ? 0.5f : 1.0f; - RenderSystem.setShaderColor(tint, tint, tint, alpha); if (editable) { markerX = MathHelper.clamp(markerX, MAP_BORDER_WIDTH, mapWidth + MAP_BORDER_WIDTH); @@ -757,8 +763,6 @@ private void renderMarker(DrawContext context, Landmark landmark, MarkerTextu DyeColor color = landmark.color(); texture.draw(context, markerX, markerY, markerScale, tileChunks, color == null ? null : color.getColorComponents(), tint, alpha); - RenderSystem.setShaderColor(1, 1, 1, 1); - if (hovering && landmark.name() != null && !landmark.name().getString().isEmpty()) { context.drawTooltip(textRenderer, landmark.name(), (int) getMouseX() - getGuiX(), (int) getMouseY() - getGuiY()); } @@ -776,24 +780,40 @@ public void close() { removeChild(markerCursor); } - private int screenXToWorldX(double mouseX) { - double mapX = (int) Math.round(mouseX - getGuiX() - MAP_BORDER_WIDTH); - return (int) Math.round((mapX - (mapWidth / 2f) - mapOffsetX) / getPixelsPerBlock()); + private int screenXToWorldX(double screenX) { + return screenXToWorldX(screenX, getGuiX(), mapOffsetX, mapWidth, getPixelsPerBlock()); } - private int screenYToWorldZ(double mouseY) { - double mapY = (int) Math.round(mouseY - getGuiY() - MAP_BORDER_HEIGHT); - return (int) Math.round((mapY - (mapHeight / 2f) - mapOffsetY) / getPixelsPerBlock()); + private int screenYToWorldZ(double screenY) { + return screenYToWorldZ(screenY, getGuiY(), mapOffsetY, mapHeight, getPixelsPerBlock()); } private double worldXToScreenX(double x) { - double mapX = x * getPixelsPerBlock() + mapOffsetX + (mapWidth / 2f); - return mapX + getGuiX() + MAP_BORDER_WIDTH; + return worldXToScreenX(x, getGuiX(), mapOffsetX, mapWidth, getPixelsPerBlock()); } private double worldZToScreenY(double z) { - double mapY = z * getPixelsPerBlock() + mapOffsetY + (mapHeight / 2f); - return mapY + getGuiY() + MAP_BORDER_HEIGHT; + return worldZToScreenY(z, getGuiY(), mapOffsetY, mapHeight, getPixelsPerBlock()); + } + + public static int screenXToWorldX(double screenX, int bookX, double mapOffsetX, int mapWidth, double pixelsPerBlock) { + double mapX = (int) Math.round(screenX - bookX - MAP_BORDER_WIDTH); + return (int) Math.round((mapX - (mapWidth / 2f) - mapOffsetX) / pixelsPerBlock); + } + + public static int screenYToWorldZ(double screenY, int bookY, double mapOffsetY, int mapHeight, double pixelsPerBlock) { + double mapY = (int) Math.round(screenY - bookY - MAP_BORDER_HEIGHT); + return (int) Math.round((mapY - (mapHeight / 2f) - mapOffsetY) / pixelsPerBlock); + } + + public static double worldXToScreenX(double x, int bookX, double mapOffsetX, int mapWidth, double pixelsPerBlock) { + double mapX = x * pixelsPerBlock + mapOffsetX + (mapWidth / 2f); + return mapX + bookX + MAP_BORDER_WIDTH; + } + + public static double worldZToScreenY(double z, int bookY, double mapOffsetY, int mapHeight, double pixelsPerBlock) { + double mapY = z * pixelsPerBlock + mapOffsetY + (mapHeight / 2f); + return mapY + bookY + MAP_BORDER_HEIGHT; } @Override diff --git a/src/main/java/folk/sisby/antique_atlas/mixin/MixinHeldItemRenderer.java b/src/main/java/folk/sisby/antique_atlas/mixin/MixinHeldItemRenderer.java new file mode 100644 index 000000000..3562d319d --- /dev/null +++ b/src/main/java/folk/sisby/antique_atlas/mixin/MixinHeldItemRenderer.java @@ -0,0 +1,146 @@ +package folk.sisby.antique_atlas.mixin; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.mojang.blaze3d.systems.RenderSystem; +import folk.sisby.antique_atlas.WorldAtlasData; +import folk.sisby.antique_atlas.gui.AtlasScreen; +import folk.sisby.antique_atlas.gui.tiles.TileRenderIterator; +import folk.sisby.antique_atlas.util.DrawBatcher; +import folk.sisby.antique_atlas.util.DrawUtil; +import folk.sisby.antique_atlas.util.MathUtil; +import folk.sisby.antique_atlas.util.Rect; +import folk.sisby.surveyor.PlayerSummary; +import folk.sisby.surveyor.client.SurveyorClient; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.AbstractClientPlayerEntity; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.item.HeldItemRenderer; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.client.util.math.Rect2i; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.util.DyeColor; +import net.minecraft.util.Hand; +import net.minecraft.util.math.ColorHelper; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.RotationAxis; +import org.joml.Vector2d; +import org.lwjgl.opengl.GL11; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.UUID; + +import static folk.sisby.antique_atlas.gui.AtlasScreen.*; + +@Mixin(HeldItemRenderer.class) +public class MixinHeldItemRenderer { + @Inject(method = "renderFirstPersonMap", at = @At("HEAD"), cancellable = true) + void renderFirstPersonAtlas(MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, ItemStack stack, CallbackInfo ci) { + if (MinecraftClient.getInstance().player == null || MinecraftClient.getInstance().world == null) return; + if (!stack.isOf(Items.BOOK) || !stack.getName().getString().contains("Antique Atlas")) return; + // Refactor to actually abstract AtlasScreen code eventually pls + + matrices.push(); + RenderSystem.enableBlend(); + RenderSystem.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(180.0F)); + matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(180.0F)); + + float scale = 0.38F * 142.0F / 218.0F; + matrices.scale(scale, scale, 0.38F); + matrices.translate(-1.2D, -0.88D, 0D); + matrices.scale(1.0F / 128.0F, 1.0F / 128.0F, 1.0F / 128.0F); + + int bookX = 0; + int bookY = 0; + int bookWidth = 310; + int bookHeight = 218; + int mapWidth = bookWidth - MAP_BORDER_WIDTH * 2; + int mapHeight = bookHeight - MAP_BORDER_HEIGHT * 2; + int tileChunks = 1; + + matrices.push(); + matrices.translate(0, 0, 0.01); + try (DrawBatcher batcher = new DrawBatcher(matrices, vertexConsumers, AtlasScreen.BOOK, bookWidth, bookHeight, light)) { + batcher.add(bookX, bookY, bookWidth, bookHeight, 0, 0, bookWidth, bookHeight, 0xFFFFFFFF); + } + matrices.pop(); + + if (MinecraftClient.getInstance().currentScreen instanceof AtlasScreen) { + matrices.pop(); + ci.cancel(); + return; + } + + int mapOffsetX = -MinecraftClient.getInstance().player.getBlockX(); + int mapOffsetY = -MinecraftClient.getInstance().player.getBlockZ(); + int mapStartChunkX = MathUtil.roundToBase(screenXToWorldX(bookX + MAP_BORDER_WIDTH, bookX, mapOffsetX, mapWidth, 1) / 16.0, tileChunks) - 2 * tileChunks; + int mapStartChunkZ = MathUtil.roundToBase(screenYToWorldZ(bookY + MAP_BORDER_HEIGHT, bookY, mapOffsetY, mapHeight, 1) / 16.0, tileChunks) - 2 * tileChunks; + int mapEndChunkX = MathUtil.roundToBase(screenXToWorldX(bookX + MAP_BORDER_WIDTH + mapWidth, bookX, mapOffsetX, mapWidth, 1) / 16.0, tileChunks) + 2 * tileChunks; + int mapEndChunkZ = MathUtil.roundToBase(screenYToWorldZ(bookY + MAP_BORDER_HEIGHT + mapHeight, bookY, mapOffsetY, mapHeight, 1) / 16.0, tileChunks) + 2 * tileChunks; + double mapStartScreenX = worldXToScreenX(mapStartChunkX << 4, bookX, mapOffsetX, mapWidth, 1); + double mapStartScreenY = worldZToScreenY(mapStartChunkZ << 4, bookY, mapOffsetY, mapHeight, 1); + WorldAtlasData worldAtlasData = WorldAtlasData.getOrCreate(MinecraftClient.getInstance().world); + TileRenderIterator tiles = new TileRenderIterator(worldAtlasData); + tiles.setScope(new Rect(mapStartChunkX, mapStartChunkZ, mapEndChunkX, mapEndChunkZ)); + tiles.setStep(tileChunks); + + matrices.push(); + AtlasScreen.renderTiles(matrices, vertexConsumers, bookX + MAP_BORDER_WIDTH, bookY + MAP_BORDER_HEIGHT, mapWidth, mapHeight, mapStartScreenX, mapStartScreenY, 1, 16, 1, light, tiles); + matrices.pop(); + + matrices.push(); + matrices.translate(0, 0, -0.02); + Rect2i mapArea = new Rect2i(bookX + MAP_BORDER_WIDTH, bookY + MAP_BORDER_HEIGHT, mapWidth, mapHeight); + worldAtlasData.getAllMarkers(tileChunks).forEach((landmark, texture) -> { + double markerX = worldXToScreenX(landmark.pos().getX(), bookX, mapOffsetX, mapWidth, 1) - bookX; + double markerY = worldZToScreenY(landmark.pos().getZ(), bookY, mapOffsetY, mapHeight, 1) - bookY; + DyeColor color = landmark.color(); + Vector2d markerPoint = new Vector2d(markerX, markerY); + float alpha = (float) MathHelper.clamp(MathUtil.innerDistanceToEdge(mapArea, markerPoint) / 32.0, 0, 1); + texture.draw(matrices, vertexConsumers, markerX, markerY, 1, tileChunks, color == null ? null : color.getColorComponents(), 1F, alpha, light); + }); + matrices.pop(); + + matrices.push(); + matrices.translate(0, 0, -0.04); + Map friends = SurveyorClient.getFriends(); + PlayerSummary playerSummary = friends.remove(SurveyorClient.getClientUuid()); + Map orderedFriends = new LinkedHashMap<>(friends); + if (playerSummary != null) orderedFriends.put(SurveyorClient.getClientUuid(), playerSummary); + orderedFriends.forEach((uuid, friend) -> { + float tint = friend.online() ? 1 : 0.5f; + float greenTint = friend == playerSummary ? 1 : 0.7f; + int argb = ColorHelper.Argb.getArgb(255, (int) (tint * 255), (int) (tint * greenTint * 255), (int) (tint * 255)); + double playerOffsetX = worldXToScreenX(MinecraftClient.getInstance().player.getPos().getX(), bookX, mapOffsetX, mapWidth, 1) - bookX; + double playerOffsetY = worldZToScreenY(MinecraftClient.getInstance().player.getPos().getZ(), bookY, mapOffsetY, mapHeight, 1) - bookY; + float playerRotation = ((float) Math.round(MinecraftClient.getInstance().player.getHeadYaw() / 360f * PLAYER_ROTATION_STEPS) / PLAYER_ROTATION_STEPS) * 360f; + DrawUtil.drawCenteredWithRotation(matrices, vertexConsumers, PLAYER, playerOffsetX, playerOffsetY, 1, PLAYER_ICON_WIDTH, PLAYER_ICON_HEIGHT, playerRotation, light, argb); + RenderSystem.setShaderColor(1, 1, 1, 1); + }); + + matrices.pop(); + matrices.push(); + // Overlay the frame so that edges of the map are smooth: + matrices.translate(0, 0, -0.03); + try (DrawBatcher batcher = new DrawBatcher(matrices, vertexConsumers, BOOK_FRAME, bookWidth, bookHeight, light)) { + batcher.add(bookX, bookY, bookWidth, bookHeight, 0, 0, bookWidth, bookHeight, 0xFFFFFFFF); + } + matrices.pop(); + + RenderSystem.disableBlend(); + + matrices.pop(); + ci.cancel(); + } + + @ModifyExpressionValue(method = "renderFirstPersonItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;isOf(Lnet/minecraft/item/Item;)Z", ordinal = 0)) + private boolean enableFirstPersonAtlasRendering(boolean original, AbstractClientPlayerEntity player, float tickDelta, float pitch, Hand hand, float swingProgress, ItemStack stack, float equipProgress, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light) { + return original || (stack.isOf(Items.BOOK) && stack.getName().getString().contains("Antique Atlas")); + } +} diff --git a/src/main/java/folk/sisby/antique_atlas/mixin/MixinItemModels.java b/src/main/java/folk/sisby/antique_atlas/mixin/MixinItemModels.java new file mode 100644 index 000000000..93434a889 --- /dev/null +++ b/src/main/java/folk/sisby/antique_atlas/mixin/MixinItemModels.java @@ -0,0 +1,21 @@ +package folk.sisby.antique_atlas.mixin; + +import com.llamalad7.mixinextras.injector.ModifyReturnValue; +import folk.sisby.antique_atlas.AntiqueAtlas; +import net.minecraft.client.render.item.ItemModels; +import net.minecraft.client.render.model.BakedModel; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(ItemModels.class) +public class MixinItemModels { + @ModifyReturnValue(method = "getModel(Lnet/minecraft/item/ItemStack;)Lnet/minecraft/client/render/model/BakedModel;", at = @At("RETURN")) + private BakedModel useAtlasBookModel(BakedModel original, ItemStack stack) { + if (stack.isOf(Items.BOOK) && stack.getName().getString().contains("Antique Atlas") ) { + return ((ItemModels) (Object) this).getModelManager().getModel(AntiqueAtlas.ATLAS_MODEL); + } + return original; + } +} diff --git a/src/main/java/folk/sisby/antique_atlas/mixin/MixinItemStack.java b/src/main/java/folk/sisby/antique_atlas/mixin/MixinItemStack.java new file mode 100644 index 000000000..04db985f0 --- /dev/null +++ b/src/main/java/folk/sisby/antique_atlas/mixin/MixinItemStack.java @@ -0,0 +1,31 @@ +package folk.sisby.antique_atlas.mixin; + +import com.llamalad7.mixinextras.injector.ModifyReturnValue; +import folk.sisby.antique_atlas.gui.AtlasScreen; +import net.minecraft.client.MinecraftClient; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.util.ActionResult; +import net.minecraft.util.Hand; +import net.minecraft.util.TypedActionResult; +import net.minecraft.world.World; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(ItemStack.class) +public class MixinItemStack { + @ModifyReturnValue(method = "use", at = @At("RETURN")) + private TypedActionResult openAtlasWithItem(TypedActionResult original, World world, PlayerEntity user, Hand hand) { + ItemStack stack = user.getStackInHand(hand); + if (world.isClient() && original.getResult() == ActionResult.PASS && stack.isOf(Items.BOOK) && stack.getName().getString().contains("Antique Atlas") && MinecraftClient.getInstance().currentScreen == null) { + AtlasScreen screen = new AtlasScreen(); + screen.init(); + screen.prepareToOpen(); + screen.tick(); + MinecraftClient.getInstance().setScreen(screen); + return TypedActionResult.success(original.getValue()); + } + return original; + } +} diff --git a/src/main/java/folk/sisby/antique_atlas/mixin/MixinModelLoader.java b/src/main/java/folk/sisby/antique_atlas/mixin/MixinModelLoader.java new file mode 100644 index 000000000..5c09beb8b --- /dev/null +++ b/src/main/java/folk/sisby/antique_atlas/mixin/MixinModelLoader.java @@ -0,0 +1,27 @@ +package folk.sisby.antique_atlas.mixin; + +import folk.sisby.antique_atlas.AntiqueAtlas; +import net.minecraft.client.color.block.BlockColors; +import net.minecraft.client.render.model.ModelLoader; +import net.minecraft.client.render.model.json.JsonUnbakedModel; +import net.minecraft.client.util.ModelIdentifier; +import net.minecraft.util.Identifier; +import net.minecraft.util.profiler.Profiler; +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.CallbackInfo; + +import java.util.List; +import java.util.Map; + +@Mixin(ModelLoader.class) +public abstract class MixinModelLoader { + @Shadow protected abstract void addModel(ModelIdentifier modelId); + + @Inject(method = "", at = @At(value = "INVOKE", target = "Ljava/util/Map;values()Ljava/util/Collection;")) + private void loadAtlasModel(BlockColors blockColors, Profiler profiler, Map jsonUnbakedModels, Map> blockStates, CallbackInfo ci) { + addModel(AntiqueAtlas.ATLAS_MODEL); + } +} diff --git a/src/main/java/folk/sisby/antique_atlas/util/DrawBatcher.java b/src/main/java/folk/sisby/antique_atlas/util/DrawBatcher.java index 095df8874..3e8d7d65e 100644 --- a/src/main/java/folk/sisby/antique_atlas/util/DrawBatcher.java +++ b/src/main/java/folk/sisby/antique_atlas/util/DrawBatcher.java @@ -1,50 +1,63 @@ package folk.sisby.antique_atlas.util; import com.mojang.blaze3d.systems.RenderSystem; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.render.BufferBuilder; import net.minecraft.client.render.BufferRenderer; import net.minecraft.client.render.GameRenderer; +import net.minecraft.client.render.RenderLayer; import net.minecraft.client.render.Tessellator; +import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.VertexFormat; import net.minecraft.client.render.VertexFormats; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.util.Identifier; import org.joml.Matrix4f; public class DrawBatcher implements AutoCloseable { private final Matrix4f matrix4f; private final BufferBuilder bufferBuilder; + private final VertexConsumer vertexConsumer; private final float textureWidth; private final float textureHeight; + private final int light; - public DrawBatcher(DrawContext context, Identifier texture, int textureWidth, int textureHeight) { + public DrawBatcher(MatrixStack matrices, VertexConsumerProvider vertexConsumers, Identifier texture, int textureWidth, int textureHeight, int light) { RenderSystem.setShaderTexture(0, texture); - RenderSystem.setShader(GameRenderer::getPositionTexProgram); - this.matrix4f = context.getMatrices().peek().getPositionMatrix(); - this.bufferBuilder = Tessellator.getInstance().getBuffer(); - bufferBuilder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE); + RenderSystem.setShader(GameRenderer::getPositionColorTexLightmapProgram); + this.matrix4f = matrices.peek().getPositionMatrix(); + if (vertexConsumers == null) { + this.bufferBuilder = Tessellator.getInstance().getBuffer(); + bufferBuilder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR_TEXTURE_LIGHT); + this.vertexConsumer = bufferBuilder; + } else { + this.bufferBuilder = null; + this.vertexConsumer = vertexConsumers.getBuffer(RenderLayer.getText(texture)); + } this.textureWidth = textureWidth; this.textureHeight = textureHeight; + this.light = light; } - public void add(int x, int y, int width, int height, int u, int v, int regionWidth, int regionHeight) { + public void add(int x, int y, int width, int height, int u, int v, int regionWidth, int regionHeight, int argb) { this.innerAdd(x, x + width, y, y + height, 0, (u + 0.0F) / textureWidth, (u + (float) regionWidth) / textureWidth, (v + 0.0F) / textureHeight, - (v + (float) regionHeight) / textureHeight + (v + (float) regionHeight) / textureHeight, + argb ); } - private void innerAdd(int x1, int x2, int y1, int y2, int z, float u1, float u2, float v1, float v2) { - bufferBuilder.vertex(matrix4f, x1, y1, z).texture(u1, v1).next(); - bufferBuilder.vertex(matrix4f, x1, y2, z).texture(u1, v2).next(); - bufferBuilder.vertex(matrix4f, x2, y2, z).texture(u2, v2).next(); - bufferBuilder.vertex(matrix4f, x2, y1, z).texture(u2, v1).next(); + private void innerAdd(int x1, int x2, int y1, int y2, int z, float u1, float u2, float v1, float v2, int argb) { + vertexConsumer.vertex(matrix4f, x1, y1, z).color(argb).texture(u1, v1).light(light).next(); + vertexConsumer.vertex(matrix4f, x1, y2, z).color(argb).texture(u1, v2).light(light).next(); + vertexConsumer.vertex(matrix4f, x2, y2, z).color(argb).texture(u2, v2).light(light).next(); + vertexConsumer.vertex(matrix4f, x2, y1, z).color(argb).texture(u2, v1).light(light).next(); } @Override public void close() { - BufferRenderer.drawWithGlobalProgram(bufferBuilder.end()); + if (bufferBuilder != null) BufferRenderer.drawWithGlobalProgram(bufferBuilder.end()); } } diff --git a/src/main/java/folk/sisby/antique_atlas/util/DrawUtil.java b/src/main/java/folk/sisby/antique_atlas/util/DrawUtil.java index 01b087f39..0f4e96f85 100644 --- a/src/main/java/folk/sisby/antique_atlas/util/DrawUtil.java +++ b/src/main/java/folk/sisby/antique_atlas/util/DrawUtil.java @@ -1,17 +1,20 @@ package folk.sisby.antique_atlas.util; -import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.util.Identifier; import net.minecraft.util.math.RotationAxis; public class DrawUtil { - public static void drawCenteredWithRotation(DrawContext context, Identifier texture, double x, double y, float scale, int textureWidth, int textureHeight, float rotation) { - context.getMatrices().push(); - context.getMatrices().translate(x, y, 0.0); - context.getMatrices().scale(scale, scale, 1.0F); - context.getMatrices().multiply(RotationAxis.POSITIVE_Z.rotationDegrees(180 + rotation)); - context.getMatrices().translate(-textureWidth / 2f, -textureHeight / 2f, 0f); - context.drawTexture(texture, 0, 0, 0, 0, textureWidth, textureHeight, textureWidth, textureHeight); - context.getMatrices().pop(); + public static void drawCenteredWithRotation(MatrixStack matrices, VertexConsumerProvider vertexConsumers, Identifier texture, double x, double y, float scale, int textureWidth, int textureHeight, float rotation, int light, int argb) { + matrices.push(); + matrices.translate(x, y, 0.0); + matrices.scale(scale, scale, 1.0F); + matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(180 + rotation)); + matrices.translate(-textureWidth / 2f, -textureHeight / 2f, 0f); + try (DrawBatcher batcher = new DrawBatcher(matrices, vertexConsumers, texture, textureWidth, textureHeight, light)) { + batcher.add(0, 0, textureWidth, textureHeight, 0, 0, textureWidth, textureHeight, argb); + } + matrices.pop(); } } diff --git a/src/main/java/folk/sisby/antique_atlas/util/MathUtil.java b/src/main/java/folk/sisby/antique_atlas/util/MathUtil.java index f4c1831f0..a05574df5 100644 --- a/src/main/java/folk/sisby/antique_atlas/util/MathUtil.java +++ b/src/main/java/folk/sisby/antique_atlas/util/MathUtil.java @@ -1,5 +1,8 @@ package folk.sisby.antique_atlas.util; +import net.minecraft.client.util.math.Rect2i; +import org.joml.Vector2d; + public class MathUtil { /** * Returns the nearest number to a multiple of a given number. @@ -7,4 +10,17 @@ public class MathUtil { public static int roundToBase(int a, int base) { return a - a % base; } + + /** + * Returns the nearest number to a multiple of a given number. + */ + public static int roundToBase(double a, double base) { + return (int) (a - a % base); + } + + public static double innerDistanceToEdge(Rect2i rect, Vector2d point) { + var dx = Math.min(point.x - rect.getX(), rect.getX() + rect.getWidth() - point.x); + var dy = Math.min(point.y - rect.getY(), rect.getY() + rect.getHeight() - point.y); + return Math.min(dx, dy); + } } diff --git a/src/main/resources/antique_atlas.mixins.json b/src/main/resources/antique_atlas.mixins.json new file mode 100644 index 000000000..f43255638 --- /dev/null +++ b/src/main/resources/antique_atlas.mixins.json @@ -0,0 +1,15 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "folk.sisby.antique_atlas.mixin", + "compatibilityLevel": "JAVA_17", + "client": [ + "MixinHeldItemRenderer", + "MixinItemModels", + "MixinItemStack", + "MixinModelLoader" + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/src/main/resources/assets/antique_atlas/models/item/atlas.json b/src/main/resources/assets/antique_atlas/models/item/atlas.json new file mode 100644 index 000000000..10b99e1a5 --- /dev/null +++ b/src/main/resources/assets/antique_atlas/models/item/atlas.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "antique_atlas:item/atlas" + } +} diff --git a/src/main/resources/assets/antique_atlas/textures/item/atlas.png b/src/main/resources/assets/antique_atlas/textures/item/atlas.png new file mode 100644 index 0000000000000000000000000000000000000000..8aa1da1e5fa2d011d8281ed18709a61864ecede7 GIT binary patch literal 3179 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 R`Dp+E002ovPDHLkV1ju38Q1^- literal 0 HcmV?d00001 diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 81ae2a547..c58bab3fd 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -17,6 +17,9 @@ }, "license": "${license}", "icon": "assets/${modId}/icon.png", + "mixins": [ + "${modId}.mixins.json" + ], "depends": { "minecraft": ">=${mc}", "fabricloader": ">=${fl}",