From 25ae1a56716e7935edc0291434e49e45ee2d3efb Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Fri, 17 Mar 2023 21:31:41 -0500 Subject: [PATCH 01/67] Revert "1.19.4" This reverts commit 4a48b5de7d27e73b591c04e733bde93af80eb26a. --- gradle.properties | 10 +++++----- src/main/java/dev/emi/emi/EmiPort.java | 7 +++---- src/main/java/dev/emi/emi/EmiStackList.java | 2 +- .../dev/emi/emi/api/stack/ItemEmiStack.java | 16 +++++++++++++--- .../emi/emi/api/stack/TagEmiIngredient.java | 4 ++-- .../mixin/AbstractInventoryScreenMixin.java | 4 +++- .../dev/emi/emi/mixin/HandledScreenMixin.java | 19 ++++++++++++------- ...essor.java => SmithingRecipeAccessor.java} | 6 +++--- .../dev/emi/emi/recipe/EmiSmithingRecipe.java | 6 +++--- .../java/dev/emi/emi/screen/BoMScreen.java | 2 +- .../dev/emi/emi/screen/ConfigEnumScreen.java | 2 +- .../emi/emi/screen/ConfigPresetScreen.java | 2 +- .../java/dev/emi/emi/screen/ConfigScreen.java | 2 +- .../dev/emi/emi/screen/EmiScreenManager.java | 2 +- .../java/dev/emi/emi/screen/RecipeScreen.java | 6 +++--- .../java/dev/emi/emi/screen/StackBatcher.java | 2 +- .../screen/tooltip/EmiTooltipComponent.java | 7 +++---- src/main/resources/assets/emi/lang/en_us.json | 7 ------- .../emi/models/item/tags/minecraft/tools.json | 7 ------- .../assets/emi/tag/exclusions/emi.json | 5 ----- src/main/resources/emi.mixins.json | 3 ++- 21 files changed, 59 insertions(+), 62 deletions(-) rename src/main/java/dev/emi/emi/mixin/accessor/{LegacySmithingRecipeAccessor.java => SmithingRecipeAccessor.java} (66%) delete mode 100644 src/main/resources/assets/emi/models/item/tags/minecraft/tools.json diff --git a/gradle.properties b/gradle.properties index f12e74af..28032bfd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,8 +4,8 @@ mod_version = 0.7.1 maven_group = dev.emi archives_base_name = emi -platform_version = 1.19.4 -minecraft_version = 1.19.4 -yarn_mappings = 1.19.4+build.1 -loader_version = 0.14.17 -fabric_api_version = 0.76.0+1.19.4 +platform_version = 1.19.3 +minecraft_version = 1.19.3-rc1 +yarn_mappings = 1.19.3-rc1+build.2 +loader_version = 0.14.11 +fabric_api_version = 0.68.1+1.19.3 diff --git a/src/main/java/dev/emi/emi/EmiPort.java b/src/main/java/dev/emi/emi/EmiPort.java index 86bb509d..c5352360 100644 --- a/src/main/java/dev/emi/emi/EmiPort.java +++ b/src/main/java/dev/emi/emi/EmiPort.java @@ -180,12 +180,11 @@ public static ButtonWidget newButton(int x, int y, int w, int h, Text name, Pres } public static ItemStack getOutput(Recipe recipe) { - MinecraftClient client = MinecraftClient.getInstance(); - return recipe.getOutput(client.player.world.getRegistryManager()); + return recipe.getOutput(); } public static void focus(TextFieldWidget widget, boolean focused) { - widget.setFocused(focused); + widget.setTextFieldFocused(focused); } public static void drawCenteredText(MatrixStack matrices, TextRenderer renderer, Text text, int x, int y, int color) { @@ -196,7 +195,7 @@ public static void drawCenteredText(MatrixStack matrices, TextRenderer renderer, if (shadow) { DrawableHelper.drawCenteredTextWithShadow(matrices, renderer, text.asOrderedText(), x, y, color); } else { - renderer.draw(matrices, text, x - renderer.getWidth(text) / 2, y, color); + DrawableHelper.drawCenteredText(matrices, renderer, text, x, y, color); } } } diff --git a/src/main/java/dev/emi/emi/EmiStackList.java b/src/main/java/dev/emi/emi/EmiStackList.java index 9cb928e0..d77a78f9 100644 --- a/src/main/java/dev/emi/emi/EmiStackList.java +++ b/src/main/java/dev/emi/emi/EmiStackList.java @@ -38,7 +38,7 @@ public static void clear() { public static void reload() { List stacks = Lists.newLinkedList(); MinecraftClient client = MinecraftClient.getInstance(); - ItemGroups.updateDisplayContext(client.player.networkHandler.getEnabledFeatures(), false, client.player.world.getRegistryManager()); + ItemGroups.updateDisplayParameters(client.player.networkHandler.getEnabledFeatures(), false); stacks.addAll(ItemGroups.getSearchGroup().getDisplayStacks().stream().map(EmiStack::of).toList()); for (int i = 0; i < EmiPort.getFluidRegistry().size(); i++) { Fluid fluid = EmiPort.getFluidRegistry().get(i); diff --git a/src/main/java/dev/emi/emi/api/stack/ItemEmiStack.java b/src/main/java/dev/emi/emi/api/stack/ItemEmiStack.java index 7ed404ca..76e88fa1 100644 --- a/src/main/java/dev/emi/emi/api/stack/ItemEmiStack.java +++ b/src/main/java/dev/emi/emi/api/stack/ItemEmiStack.java @@ -3,6 +3,7 @@ import java.util.List; import com.google.common.collect.Lists; +import com.mojang.blaze3d.systems.RenderSystem; import dev.emi.emi.EmiPort; import dev.emi.emi.EmiRenderHelper; @@ -20,7 +21,7 @@ import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.item.ItemRenderer; import net.minecraft.client.render.model.BakedModel; -import net.minecraft.client.render.model.json.ModelTransformationMode; +import net.minecraft.client.render.model.json.ModelTransformation; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NbtCompound; @@ -95,8 +96,17 @@ public void render(MatrixStack matrices, int x, int y, float delta, int flags) { MinecraftClient client = MinecraftClient.getInstance(); ItemStack stack = getItemStack(); if ((flags & RENDER_ICON) != 0) { + MatrixStack view = RenderSystem.getModelViewStack(); + view.push(); + view.multiplyPositionMatrix(matrices.peek().getPositionMatrix()); + RenderSystem.applyModelViewMatrix(); ItemRenderer itemRenderer = client.getItemRenderer(); - itemRenderer.renderInGui(matrices, stack, x, y); + float zOffset = itemRenderer.zOffset; + itemRenderer.zOffset = 0; + itemRenderer.renderInGui(stack, x, y); + itemRenderer.zOffset = zOffset; + view.pop(); + RenderSystem.applyModelViewMatrix(); } if ((flags & RENDER_AMOUNT) != 0) { String count = ""; @@ -137,7 +147,7 @@ public void renderForBatch(VertexConsumerProvider vcp, MatrixStack matrices, int matrices.translate(x, y, 100.0f + z + (model.hasDepth() ? 50 : 0)); matrices.translate(8.0, 8.0, 0.0); matrices.scale(16.0f, 16.0f, 16.0f); - ir.renderItem(stack, ModelTransformationMode.GUI, false, matrices, vcp, LightmapTextureManager.MAX_LIGHT_COORDINATE, OverlayTexture.DEFAULT_UV, model); + ir.renderItem(stack, ModelTransformation.Mode.GUI, false, matrices, vcp, LightmapTextureManager.MAX_LIGHT_COORDINATE, OverlayTexture.DEFAULT_UV, model); } finally { matrices.pop(); } diff --git a/src/main/java/dev/emi/emi/api/stack/TagEmiIngredient.java b/src/main/java/dev/emi/emi/api/stack/TagEmiIngredient.java index aab997eb..c90e20af 100644 --- a/src/main/java/dev/emi/emi/api/stack/TagEmiIngredient.java +++ b/src/main/java/dev/emi/emi/api/stack/TagEmiIngredient.java @@ -25,7 +25,7 @@ import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.item.ItemRenderer; import net.minecraft.client.render.model.BakedModel; -import net.minecraft.client.render.model.json.ModelTransformationMode; +import net.minecraft.client.render.model.json.ModelTransformation; import net.minecraft.client.resource.language.I18n; import net.minecraft.client.util.ModelIdentifier; import net.minecraft.client.util.math.MatrixStack; @@ -122,7 +122,7 @@ public void render(MatrixStack matrices, int x, int y, float delta, int flags) { RenderSystem.applyModelViewMatrix(); MatrixStack ms = new MatrixStack(); - model.getTransformation().getTransformation(ModelTransformationMode.GUI).apply(false, ms); + model.getTransformation().getTransformation(ModelTransformation.Mode.GUI).apply(false, ms); ms.translate(-0.5, -0.5, -0.5); if (!model.isSideLit()) { diff --git a/src/main/java/dev/emi/emi/mixin/AbstractInventoryScreenMixin.java b/src/main/java/dev/emi/emi/mixin/AbstractInventoryScreenMixin.java index 19546eee..bbbb562a 100644 --- a/src/main/java/dev/emi/emi/mixin/AbstractInventoryScreenMixin.java +++ b/src/main/java/dev/emi/emi/mixin/AbstractInventoryScreenMixin.java @@ -15,6 +15,7 @@ import com.google.common.collect.Ordering; import com.mojang.blaze3d.systems.RenderSystem; +import dev.emi.emi.EmiPort; import dev.emi.emi.config.EmiConfig; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.client.gui.screen.ingame.AbstractInventoryScreen; @@ -103,7 +104,8 @@ private void drawStatusEffects(MatrixStack matrices, int mouseX, int mouseY, Cal this.y = restoreY; } if (hovered != null && size > 1) { - List list = List.of(this.getStatusEffectDescription(hovered), StatusEffectUtil.durationToString(hovered, 1.0f)); + List list = List.of(this.getStatusEffectDescription(hovered), + EmiPort.literal(StatusEffectUtil.durationToString(hovered, 1.0f))); this.renderTooltip(matrices, list, Optional.empty(), mouseX, Math.max(mouseY, 16)); } return true; diff --git a/src/main/java/dev/emi/emi/mixin/HandledScreenMixin.java b/src/main/java/dev/emi/emi/mixin/HandledScreenMixin.java index d8488f62..3957369c 100644 --- a/src/main/java/dev/emi/emi/mixin/HandledScreenMixin.java +++ b/src/main/java/dev/emi/emi/mixin/HandledScreenMixin.java @@ -8,6 +8,8 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import com.mojang.blaze3d.systems.RenderSystem; + import dev.emi.emi.EmiPort; import dev.emi.emi.api.stack.EmiStack; import dev.emi.emi.screen.EmiScreen; @@ -35,12 +37,12 @@ private void init(CallbackInfo info) { } @Intrinsic @Override - public void renderBackground(MatrixStack matrices) { - super.renderBackground(matrices); + public void renderBackground(MatrixStack matrices, int vOffset) { + super.renderBackground(matrices, vOffset); } - @Inject(at = @At("RETURN"), method = "renderBackground(Lnet/minecraft/client/util/math/MatrixStack;)V") - private void renderBackground(MatrixStack matrices, CallbackInfo info) { + @Inject(at = @At("RETURN"), method = "renderBackground(Lnet/minecraft/client/util/math/MatrixStack;I)V") + private void renderBackground(MatrixStack matrices, int vOffset, CallbackInfo info) { Window window = client.getWindow(); int mouseX = (int) (client.mouse.getX() * window.getScaledWidth() / window.getWidth()); int mouseY = (int) (client.mouse.getY() * window.getScaledHeight() / window.getHeight()); @@ -52,11 +54,14 @@ private void renderBackground(MatrixStack matrices, CallbackInfo info) { shift = Shift.AFTER), method = "render") private void render(MatrixStack matrices, int mouseX, int mouseY, float delta, CallbackInfo info) { - matrices.push(); - matrices.translate(-x, -y, 0.0); + MatrixStack viewStack = RenderSystem.getModelViewStack(); + viewStack.push(); + viewStack.translate(-x, -y, 0.0); + RenderSystem.applyModelViewMatrix(); EmiPort.setPositionTexShader(); EmiScreenManager.render(matrices, mouseX, mouseY, delta); - matrices.pop(); + viewStack.pop(); + RenderSystem.applyModelViewMatrix(); } @Inject(at = @At("TAIL"), method = "drawSlot") diff --git a/src/main/java/dev/emi/emi/mixin/accessor/LegacySmithingRecipeAccessor.java b/src/main/java/dev/emi/emi/mixin/accessor/SmithingRecipeAccessor.java similarity index 66% rename from src/main/java/dev/emi/emi/mixin/accessor/LegacySmithingRecipeAccessor.java rename to src/main/java/dev/emi/emi/mixin/accessor/SmithingRecipeAccessor.java index 65970c70..fe607113 100644 --- a/src/main/java/dev/emi/emi/mixin/accessor/LegacySmithingRecipeAccessor.java +++ b/src/main/java/dev/emi/emi/mixin/accessor/SmithingRecipeAccessor.java @@ -4,10 +4,10 @@ import org.spongepowered.asm.mixin.gen.Accessor; import net.minecraft.recipe.Ingredient; -import net.minecraft.recipe.LegacySmithingRecipe; +import net.minecraft.recipe.SmithingRecipe; -@Mixin(LegacySmithingRecipe.class) -public interface LegacySmithingRecipeAccessor { +@Mixin(SmithingRecipe.class) +public interface SmithingRecipeAccessor { @Accessor("base") Ingredient getBase(); diff --git a/src/main/java/dev/emi/emi/recipe/EmiSmithingRecipe.java b/src/main/java/dev/emi/emi/recipe/EmiSmithingRecipe.java index 39f3f55e..5f5e28fa 100644 --- a/src/main/java/dev/emi/emi/recipe/EmiSmithingRecipe.java +++ b/src/main/java/dev/emi/emi/recipe/EmiSmithingRecipe.java @@ -10,7 +10,7 @@ import dev.emi.emi.api.stack.EmiIngredient; import dev.emi.emi.api.stack.EmiStack; import dev.emi.emi.api.widget.WidgetHolder; -import dev.emi.emi.mixin.accessor.LegacySmithingRecipeAccessor; +import dev.emi.emi.mixin.accessor.SmithingRecipeAccessor; import net.minecraft.recipe.SmithingRecipe; import net.minecraft.util.Identifier; @@ -22,8 +22,8 @@ public class EmiSmithingRecipe implements EmiRecipe { public EmiSmithingRecipe(SmithingRecipe recipe) { this.id = recipe.getId(); - input = EmiIngredient.of(((LegacySmithingRecipeAccessor) recipe).getBase()); - addition = EmiIngredient.of(((LegacySmithingRecipeAccessor) recipe).getAddition()); + input = EmiIngredient.of(((SmithingRecipeAccessor) recipe).getBase()); + addition = EmiIngredient.of(((SmithingRecipeAccessor) recipe).getAddition()); output = EmiStack.of(EmiPort.getOutput(recipe)); } diff --git a/src/main/java/dev/emi/emi/screen/BoMScreen.java b/src/main/java/dev/emi/emi/screen/BoMScreen.java index e6c2d6b4..121d9169 100644 --- a/src/main/java/dev/emi/emi/screen/BoMScreen.java +++ b/src/main/java/dev/emi/emi/screen/BoMScreen.java @@ -188,7 +188,7 @@ public void recalculateTree() { @Override public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { - this.renderBackgroundTexture(matrices); + this.renderBackgroundTexture(0); lastMouseX = mouseX; lastMouseY = mouseY; float scale = getScale(); diff --git a/src/main/java/dev/emi/emi/screen/ConfigEnumScreen.java b/src/main/java/dev/emi/emi/screen/ConfigEnumScreen.java index b9497256..6c1901f6 100644 --- a/src/main/java/dev/emi/emi/screen/ConfigEnumScreen.java +++ b/src/main/java/dev/emi/emi/screen/ConfigEnumScreen.java @@ -49,7 +49,7 @@ public void init() { @Override public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { list.setScrollAmount(list.getScrollAmount()); - this.renderBackgroundTexture(matrices); + this.renderBackgroundTexture(0); list.render(matrices, mouseX, mouseY, delta); super.render(matrices, mouseX, mouseY, delta); ListWidget.Entry entry = list.getHoveredEntry(); diff --git a/src/main/java/dev/emi/emi/screen/ConfigPresetScreen.java b/src/main/java/dev/emi/emi/screen/ConfigPresetScreen.java index 286403d2..7d241bd4 100644 --- a/src/main/java/dev/emi/emi/screen/ConfigPresetScreen.java +++ b/src/main/java/dev/emi/emi/screen/ConfigPresetScreen.java @@ -72,7 +72,7 @@ public void init() { @Override public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { list.setScrollAmount(list.getScrollAmount()); - this.renderBackgroundTexture(matrices); + this.renderBackgroundTexture(0); list.render(matrices, mouseX, mouseY, delta); super.render(matrices, mouseX, mouseY, delta); if (list.getHoveredEntry() instanceof PresetWidget widget) { diff --git a/src/main/java/dev/emi/emi/screen/ConfigScreen.java b/src/main/java/dev/emi/emi/screen/ConfigScreen.java index 3d4d1580..345df46d 100644 --- a/src/main/java/dev/emi/emi/screen/ConfigScreen.java +++ b/src/main/java/dev/emi/emi/screen/ConfigScreen.java @@ -364,7 +364,7 @@ public void updateChanges() { @Override public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { list.setScrollAmount(list.getScrollAmount()); - this.renderBackgroundTexture(matrices); + this.renderBackgroundTexture(-100); list.render(matrices, mouseX, mouseY, delta); super.render(matrices, mouseX, mouseY, delta); if (list.getHoveredEntry() != null) { diff --git a/src/main/java/dev/emi/emi/screen/EmiScreenManager.java b/src/main/java/dev/emi/emi/screen/EmiScreenManager.java index fc836b3f..1a97652c 100644 --- a/src/main/java/dev/emi/emi/screen/EmiScreenManager.java +++ b/src/main/java/dev/emi/emi/screen/EmiScreenManager.java @@ -1448,7 +1448,7 @@ public void render(MatrixStack matrices, int mouseX, int mouseY, float delta, in EmiPort.setPositionTexShader(); RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); int hx = -1, hy = -1; - batcher.begin(0, 0, 0); + batcher.begin(this.tx + PADDING_SIZE, this.ty + PADDING_SIZE, 0); int i = startIndex; List stacks = getStacks(); outer: for (int yo = 0; yo < this.th; yo++) { diff --git a/src/main/java/dev/emi/emi/screen/RecipeScreen.java b/src/main/java/dev/emi/emi/screen/RecipeScreen.java index c66bc34e..d0a4e093 100644 --- a/src/main/java/dev/emi/emi/screen/RecipeScreen.java +++ b/src/main/java/dev/emi/emi/screen/RecipeScreen.java @@ -202,9 +202,9 @@ public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { int extraWidth = client.textRenderer.getWidth("..."); text = EmiPort.literal(client.textRenderer.trimToWidth(text, (minimumWidth - 40) - extraWidth).getString() + "..."); } - EmiPort.drawCenteredText(matrices, textRenderer, text, x + backgroundWidth / 2, y + 7, categoryNameColor, true); - EmiPort.drawCenteredText(matrices, textRenderer, EmiRenderHelper.getPageText(this.page + 1, tab.recipes.size(), minimumWidth - 40), - x + backgroundWidth / 2, y + 21, 0xffffff, true); + EmiPort.drawCenteredText(matrices, textRenderer, text, x + backgroundWidth / 2, y + 7, categoryNameColor); + EmiPort.drawCenteredText(matrices, textRenderer,EmiRenderHelper.getPageText(this.page + 1, tab.recipes.size(), minimumWidth - 40), + x + backgroundWidth / 2, y + 21, 0xffffff); List workstations = EmiRecipes.workstations.getOrDefault(tab.category, List.of()); int workstationAmount = Math.min(workstations.size(), getMaxWorkstations()); diff --git a/src/main/java/dev/emi/emi/screen/StackBatcher.java b/src/main/java/dev/emi/emi/screen/StackBatcher.java index 234dce5b..6eb17718 100644 --- a/src/main/java/dev/emi/emi/screen/StackBatcher.java +++ b/src/main/java/dev/emi/emi/screen/StackBatcher.java @@ -143,7 +143,7 @@ public void render(EmiIngredient stack, MatrixStack matrices, int x, int y, floa if (stack instanceof Batchable b && !b.isUnbatchable() && isEnabled() && (flags & EmiIngredient.RENDER_ICON) != 0) { if (!populated) { try { - b.renderForBatch(b.isSideLit() ? imm : unlitFacade, matrices, x-this.x, -y-this.y, z, delta); + b.renderForBatch(b.isSideLit() ? imm : unlitFacade, matrices, x-this.x, -y+this.y, z, delta); if (sodiumSpriteHandle != null && !stack.isEmpty()) { ItemStack is = stack.getEmiStacks().get(0).getItemStack(); MinecraftClient client = MinecraftClient.getInstance(); diff --git a/src/main/java/dev/emi/emi/screen/tooltip/EmiTooltipComponent.java b/src/main/java/dev/emi/emi/screen/tooltip/EmiTooltipComponent.java index c0f23e7b..588df2f3 100644 --- a/src/main/java/dev/emi/emi/screen/tooltip/EmiTooltipComponent.java +++ b/src/main/java/dev/emi/emi/screen/tooltip/EmiTooltipComponent.java @@ -4,7 +4,6 @@ import dev.emi.emi.EmiPort; import net.minecraft.client.font.TextRenderer; -import net.minecraft.client.font.TextRenderer.TextLayerType; import net.minecraft.client.gui.tooltip.TooltipComponent; import net.minecraft.client.render.LightmapTextureManager; import net.minecraft.client.render.VertexConsumerProvider.Immediate; @@ -21,9 +20,9 @@ default void drawTooltipText(TextRenderData text) { } @Override - default void drawItems(TextRenderer textRenderer, int x, int y, MatrixStack matrices, ItemRenderer itemRenderer) { + default void drawItems(TextRenderer textRenderer, int x, int y, MatrixStack matrices, ItemRenderer itemRenderer, int z) { matrices.push(); - matrices.translate(x, y, 0); + matrices.translate(x, y, z); drawTooltip(matrices, new TooltipRenderData(textRenderer, itemRenderer, x, y)); matrices.pop(); } @@ -52,7 +51,7 @@ public void draw(String text, int x, int y, int color, boolean shadow) { } public void draw(Text text, int x, int y, int color, boolean shadow) { - renderer.draw(text, x + this.x, y + this.y, color, shadow, matrix, vertexConsumers, TextLayerType.NORMAL, 0, LightmapTextureManager.MAX_LIGHT_COORDINATE); + renderer.draw(text, x + this.x, y + this.y, color, shadow, matrix, vertexConsumers, false, 0, LightmapTextureManager.MAX_LIGHT_COORDINATE); } } diff --git a/src/main/resources/assets/emi/lang/en_us.json b/src/main/resources/assets/emi/lang/en_us.json index 2c59703c..9757be97 100644 --- a/src/main/resources/assets/emi/lang/en_us.json +++ b/src/main/resources/assets/emi/lang/en_us.json @@ -338,13 +338,6 @@ "tag.minecraft.compasses": "Compasses", "tag.minecraft.chest_boats": "Chest Boats", "tag.minecraft.overworld_natural_logs": "Natural Overworld Logs", - "tag.minecraft.axes": "Axes", - "tag.minecraft.hoes": "Hoes", - "tag.minecraft.pickaxes": "Pickaxes", - "tag.minecraft.shovels": "Shovels", - "tag.minecraft.smelts_to_glass": "Smelts to Glass", - "tag.minecraft.swords": "Swords", - "tag.minecraft.tools": "Tools", "tag.c.stone": "Stone", "tag.c.cobblestone": "Cobblestone", diff --git a/src/main/resources/assets/emi/models/item/tags/minecraft/tools.json b/src/main/resources/assets/emi/models/item/tags/minecraft/tools.json deleted file mode 100644 index 1fdb7922..00000000 --- a/src/main/resources/assets/emi/models/item/tags/minecraft/tools.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "parent": "emi:item/half_item", - "textures": { - "first": "minecraft:item/golden_sword", - "second": "minecraft:item/iron_pickaxe" - } -} \ No newline at end of file diff --git a/src/main/resources/assets/emi/tag/exclusions/emi.json b/src/main/resources/assets/emi/tag/exclusions/emi.json index 404faaf6..eb613942 100644 --- a/src/main/resources/assets/emi/tag/exclusions/emi.json +++ b/src/main/resources/assets/emi/tag/exclusions/emi.json @@ -4,11 +4,6 @@ "minecraft:cluster_max_harvestables", "minecraft:completes_find_tree_tutorial", "minecraft:dampens_vibrations", - "c:axes", - "c:hoes", - "c:pickaxes", - "c:shovels", - "c:swords", "c:hidden_from_recipe_viewers", "c:ore_bearing_ground/stone", "c:ore_bearing_ground/deepslate", diff --git a/src/main/resources/emi.mixins.json b/src/main/resources/emi.mixins.json index 2c30f5fe..50c38f19 100644 --- a/src/main/resources/emi.mixins.json +++ b/src/main/resources/emi.mixins.json @@ -10,9 +10,9 @@ "accessor.HandledScreenAccessor", "accessor.HoeItemAccessor", "accessor.ItemRendererAccessor", - "accessor.LegacySmithingRecipeAccessor", "accessor.ScreenAccessor", "accessor.ShovelItemAccessor", + "accessor.SmithingRecipeAccessor", "api.EmiIngredientMixin", "conversion.FluidMixin", "conversion.ItemConvertibleMixin", @@ -24,6 +24,7 @@ "HoeItemMixin", "ItemStackMixin", "KeyboardMixin", + "MinecraftClientGameMixin", "MinecraftClientMixin", "MouseMixin", "ScreenMixin", From a1040c4a7f897f82f17020dfc9fce1d4eecfba96 Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Fri, 17 Mar 2023 21:35:28 -0500 Subject: [PATCH 02/67] Remove game mixin --- src/main/resources/emi.mixins.json | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/resources/emi.mixins.json b/src/main/resources/emi.mixins.json index 50c38f19..44ffbddc 100644 --- a/src/main/resources/emi.mixins.json +++ b/src/main/resources/emi.mixins.json @@ -24,7 +24,6 @@ "HoeItemMixin", "ItemStackMixin", "KeyboardMixin", - "MinecraftClientGameMixin", "MinecraftClientMixin", "MouseMixin", "ScreenMixin", From df347c054d0451477f7992c417e24b204c3a37c5 Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Sun, 19 Mar 2023 16:20:46 -0500 Subject: [PATCH 03/67] Revert "Update modmenu" This reverts commit 0b131fa8e2e8df12ac04ee08c7df3c4c42240c8e. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index cc920d51..22fdda54 100644 --- a/build.gradle +++ b/build.gradle @@ -52,7 +52,7 @@ dependencies { modCompileOnly "net.fabricmc.fabric-api:fabric-api:${project.fabric_api_version}" modLocalRuntime "net.fabricmc.fabric-api:fabric-api:${project.fabric_api_version}" - modCompileOnly "com.terraformersmc:modmenu:6.1.0-rc.4" + modCompileOnly "com.terraformersmc:modmenu:5.0.0-alpha.4" } processResources { From 8c26828e822d99b56d05bdd76e9c90388e9909f7 Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Sat, 22 Apr 2023 15:40:40 -0500 Subject: [PATCH 04/67] Readjust for 1.19.3 --- .../main/java/dev/emi/emi/api/stack/TagEmiIngredient.java | 4 ++-- .../dev/emi/emi/mixin/AbstractInventoryScreenMixin.java | 3 ++- .../main/java/dev/emi/emi/mixin/HandledScreenMixin.java | 8 ++++---- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/xplat/src/main/java/dev/emi/emi/api/stack/TagEmiIngredient.java b/xplat/src/main/java/dev/emi/emi/api/stack/TagEmiIngredient.java index 6f548ff1..ce013e7a 100644 --- a/xplat/src/main/java/dev/emi/emi/api/stack/TagEmiIngredient.java +++ b/xplat/src/main/java/dev/emi/emi/api/stack/TagEmiIngredient.java @@ -25,7 +25,7 @@ import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.item.ItemRenderer; import net.minecraft.client.render.model.BakedModel; -import net.minecraft.client.render.model.json.ModelTransformationMode; +import net.minecraft.client.render.model.json.ModelTransformation; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; @@ -119,7 +119,7 @@ public void render(MatrixStack matrices, int x, int y, float delta, int flags) { RenderSystem.applyModelViewMatrix(); MatrixStack ms = new MatrixStack(); - model.getTransformation().getTransformation(ModelTransformationMode.GUI).apply(false, ms); + model.getTransformation().getTransformation(ModelTransformation.Mode.GUI).apply(false, ms); ms.translate(-0.5, -0.5, -0.5); if (!model.isSideLit()) { diff --git a/xplat/src/main/java/dev/emi/emi/mixin/AbstractInventoryScreenMixin.java b/xplat/src/main/java/dev/emi/emi/mixin/AbstractInventoryScreenMixin.java index 5a26c325..7c4e15cc 100644 --- a/xplat/src/main/java/dev/emi/emi/mixin/AbstractInventoryScreenMixin.java +++ b/xplat/src/main/java/dev/emi/emi/mixin/AbstractInventoryScreenMixin.java @@ -15,6 +15,7 @@ import com.google.common.collect.Ordering; import com.mojang.blaze3d.systems.RenderSystem; +import dev.emi.emi.EmiPort; import dev.emi.emi.config.EffectLocation; import dev.emi.emi.config.EmiConfig; import dev.emi.emi.platform.EmiAgnos; @@ -105,7 +106,7 @@ private void drawStatusEffects(MatrixStack matrices, int mouseX, int mouseY, Cal } if (hovered != null && size > 1) { List list = List.of(this.getStatusEffectDescription(hovered), - StatusEffectUtil.durationToString(hovered, 1.0f)); + EmiPort.literal(StatusEffectUtil.durationToString(hovered, 1.0f))); this.renderTooltip(matrices, list, Optional.empty(), mouseX, Math.max(mouseY, 16)); } return true; diff --git a/xplat/src/main/java/dev/emi/emi/mixin/HandledScreenMixin.java b/xplat/src/main/java/dev/emi/emi/mixin/HandledScreenMixin.java index 4e0137fe..13f56b80 100644 --- a/xplat/src/main/java/dev/emi/emi/mixin/HandledScreenMixin.java +++ b/xplat/src/main/java/dev/emi/emi/mixin/HandledScreenMixin.java @@ -38,13 +38,13 @@ private void init(CallbackInfo info) { } @Intrinsic @Override - public void renderBackground(MatrixStack matrices, int vOffset) { - super.renderBackground(matrices, vOffset); + public void renderBackground(MatrixStack matrices) { + super.renderBackground(matrices); } @Dynamic - @Inject(at = @At("RETURN"), method = "renderBackground(Lnet/minecraft/client/util/math/MatrixStack;I)V") - private void renderBackground(MatrixStack matrices, int vOffset, CallbackInfo info) { + @Inject(at = @At("RETURN"), method = "renderBackground(Lnet/minecraft/client/util/math/MatrixStack;)V") + private void renderBackground(MatrixStack matrices, CallbackInfo info) { Window window = client.getWindow(); int mouseX = (int) (client.mouse.getX() * window.getScaledWidth() / window.getWidth()); int mouseY = (int) (client.mouse.getY() * window.getScaledHeight() / window.getHeight()); From 097cb056f9ac452c7a9401bdad10839590f7c23d Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Wed, 24 May 2023 20:56:35 -0500 Subject: [PATCH 05/67] Use view matrix for foreground --- .../java/dev/emi/emi/mixin/HandledScreenMixin.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/xplat/src/main/java/dev/emi/emi/mixin/HandledScreenMixin.java b/xplat/src/main/java/dev/emi/emi/mixin/HandledScreenMixin.java index bf061df2..19e698b9 100644 --- a/xplat/src/main/java/dev/emi/emi/mixin/HandledScreenMixin.java +++ b/xplat/src/main/java/dev/emi/emi/mixin/HandledScreenMixin.java @@ -71,10 +71,14 @@ private void render(MatrixStack matrices, int mouseX, int mouseY, float delta, C shift = Shift.AFTER), method = "render") private void renderForeground(MatrixStack matrices, int mouseX, int mouseY, float delta, CallbackInfo info) { - matrices.push(); - matrices.translate(-x, -y, 0.0); + MatrixStack viewStack = RenderSystem.getModelViewStack(); + viewStack.push(); + viewStack.translate(-x, -y, 0.0); + RenderSystem.applyModelViewMatrix(); + EmiPort.setPositionTexShader(); EmiScreenManager.drawForeground(matrices, mouseX, mouseY, delta); - matrices.pop(); + viewStack.pop(); + RenderSystem.applyModelViewMatrix(); } @Inject(at = @At("TAIL"), method = "drawSlot") From 70c1e4ea89b361f50656935933a17f2b6a9e6494 Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Sat, 27 May 2023 17:02:29 -0500 Subject: [PATCH 06/67] Use unique IDs --- .github/workflows/release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0686043d..7787c6cc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -59,7 +59,7 @@ jobs: prerelease: false - name: Upload Fabric Release Asset - id: upload_release_asset + id: upload_fabric_release_asset uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -70,7 +70,7 @@ jobs: asset_content_type: application/java-archive - name: Upload Forge Release Asset - id: upload_release_asset + id: upload_forge_release_asset uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From d137250f1d9466060c6fbc0101bff9673edb7fa8 Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Tue, 30 May 2023 19:16:18 -0500 Subject: [PATCH 07/67] Use legacy API for more compatibility --- .../java/dev/emi/emi/jemi/runtime/JemiDragDropHandler.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xplat/src/main/java/dev/emi/emi/jemi/runtime/JemiDragDropHandler.java b/xplat/src/main/java/dev/emi/emi/jemi/runtime/JemiDragDropHandler.java index 81408a0f..8bc62262 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/runtime/JemiDragDropHandler.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/runtime/JemiDragDropHandler.java @@ -56,11 +56,12 @@ private void render(Screen screen, MatrixStack matrices, Optional List> getTargets(Screen screen, ITypedIngredient typed) { Optional> optGhost = JemiPlugin.runtime.getScreenHelper().getGhostIngredientHandler(screen); if (optGhost.isPresent()) { IGhostIngredientHandler ghost = optGhost.get(); - return ghost.getTargetsTyped(screen, typed, false); + return ghost.getTargets(screen, typed.getIngredient(), false); } return List.of(); } From 0fd85e2ce57799bf1b87af31613b0502be44b440 Mon Sep 17 00:00:00 2001 From: Juuz <6596629+Juuxel@users.noreply.github.com> Date: Sat, 10 Jun 2023 19:32:17 +0300 Subject: [PATCH 08/67] Add Finnish translation (#206) * Add Finnish translation * Fix translation of crops --- .../main/resources/assets/emi/lang/fi_fi.json | 673 ++++++++++++++++++ 1 file changed, 673 insertions(+) create mode 100644 xplat/src/main/resources/assets/emi/lang/fi_fi.json diff --git a/xplat/src/main/resources/assets/emi/lang/fi_fi.json b/xplat/src/main/resources/assets/emi/lang/fi_fi.json new file mode 100644 index 00000000..00b80c46 --- /dev/null +++ b/xplat/src/main/resources/assets/emi/lang/fi_fi.json @@ -0,0 +1,673 @@ +{ + "key.keyboard.control": "Ctrl", + "key.keyboard.alt": "Alt", + "key.keyboard.shift": "Shift", + + "key.emi.toggle_visibility": "Kytke näkyvyys", + "key.emi.focus_search": "Kohdista haku", + "key.emi.clear_search": "Tyhjennä haku", + "key.emi.view_recipes": "Näytä reseptit", + "key.emi.view_uses": "Näytä käyttökohteet", + "key.emi.favorite": "Aseta suosikiksi", + "key.emi.set_default": "Aseta oletukseksi", + "key.emi.default_stack": "Oletuspino", + "key.emi.view_stack_tree": "Näytä pinopuu", + "key.emi.view_tree": "Näytä puu", + "key.emi.back": "Takaisin", + "key.emi.craft_one": "Valmista yksi", + "key.emi.craft_all": "Valmista kaikki", + "key.emi.craft_one_to_inventory": "Valmista yksi tavaraluetteloon", + "key.emi.craft_all_to_inventory": "Valmista kaikki tavaraluetteloon", + "key.emi.craft_one_to_cursor": "Valmista yksi kursorille", + "key.emi.show_craft": "Näytä valmistus", + "key.emi.cheat_one_to_inventory": "Huijaa yksi tavaraluetteloon", + "key.emi.cheat_stack_to_inventory": "Huijaa pino tavaraluetteloon", + "key.emi.cheat_one_to_cursor": "Huijaa yksi kursorille", + "key.emi.cheat_stack_to_cursor": "Huijaa pino kursorille", + "key.emi.delete_cursor_stack": "Poista kursorin pino", + "key.emi.hide_stack": "Piilota pino", + "key.emi.hide_stack_by_id": "Piilota pino ID:n perusteella", + + "emi.help_level.verbose": "Monisanainen", + "emi.help_level.normal": "Tavallinen", + "emi.help_level.none": "Ei mitään", + "emi.align.horizontal.left": "Vasemmalla", + "emi.align.horizontal.center": "Keskitetty", + "emi.align.horizontal.right": "Oikealla", + "emi.align.vertical.top": "Ylhäällä", + "emi.align.vertical.center": "Keskitetty", + "emi.align.vertical.bottom": "Alhaalla", + "emi.sidebar.type.none": "Ei mitään", + "emi.sidebar.type.index": "Hakemisto", + "emi.sidebar.type.craftables": "Valmistettavat", + "emi.sidebar.type.favorites": "Suosikit", + "emi.sidebar.type.lookup_history": "Hakuhistoria", + "emi.sidebar.type.craft_history": "Valmistushistoria", + "emi.sidebar.type.chess": "Shakki", + "emi.sidebar.theme.transparent": "Läpinäkyvä", + "emi.sidebar.theme.vanilla": "Vanilja", + "emi.sidebar.theme.modern": "Nykyaikainen", + "emi.header.visible": "Näkyvä", + "emi.header.invisible": "Näkymätön", + "emi.sidebar.size.columns": "Sarakkeet", + "emi.sidebar.size.rows": "Rivit", + "emi.sidebar.margins.top": "Yläreuna", + "emi.sidebar.margins.right": "Oikea reuna", + "emi.sidebar.margins.bottom": "Alareuna", + "emi.sidebar.margins.left": "Vasen reuna", + "emi.sidebar.none": "Ei mitään", + "emi.sidebar.left": "Vasen reuna", + "emi.sidebar.right": "Oikea reuna", + "emi.sidebar.top": "Yläreuna", + "emi.sidebar.bottom": "Alareuna", + "emi.effect_location.top": "Ylhäällä", + "emi.effect_location.left_compressed": "Vasemmalla (tiivistetty)", + "emi.effect_location.right_compressed": "Oikealla (tiivistetty)", + "emi.effect_location.left": "Vasemmalla", + "emi.effect_location.right": "Oikealla", + "emi.recipe_book_action.default": "Oletus", + "emi.recipe_book_action.toggle_craftables": "Kytke valmistettavat", + "emi.recipe_book_action.toggle_visibility": "Kytke näkyvyys", + + "config.emi.group.general": "Yleiset", + "config.emi.group.general.search": "Haku", + "config.emi.group.ui": "Käyttöliittymä", + "config.emi.group.ui.mod_id": "Modi-ID", + "config.emi.group.ui.recipe_screen": "Reseptinäkymä", + "config.emi.group.ui.recipe_buttons": "Reseptipainikkeet", + "config.emi.group.ui.left_sidebar": "Vasen sivupalkki", + "config.emi.group.ui.right_sidebar": "Oikea sivupalkki", + "config.emi.group.ui.top_sidebar": "Yläsivupalkki", + "config.emi.group.ui.bottom_sidebar": "Alasivupalkki", + "config.emi.group.binds": "Näppäimet", + "config.emi.group.dev": "Kehittäjä", + + "config.emi.group.binds.crafts": "Valmistus", + "config.emi.group.binds.cheats": "Huijaus", + + "config.emi.general.enabled": "Käytössä", + "config.emi.general.cheat_mode": "Huijaustila", + "config.emi.general.help_level": "Avun taso", + "config.emi.general.search_tooltip_by_default": "Hae vinkeistä oletuksena", + "config.emi.general.search_mod_name_by_default": "Hae modien nimistä oletuksena", + "config.emi.general.search_tags_by_default": "Hae tunnisteista oletuksena", + + "config.emi.ui.effect_location": "Vaikutusten sijainti", + "config.emi.ui.center_search_bar": "Keskitä hakupankki", + "config.emi.ui.show_hover_overlay": "Näytä osoitetun peitekerros", + "config.emi.ui.append_mod_id": "Lisää modi-ID", + "config.emi.ui.append_item_mod_id": "Lisää tavaran modi-ID", + "config.emi.ui.recipe_book_action": "Reseptikirjan toiminto", + "config.emi.ui.search_sidebar_focus": "Hakusivupalkin fokus", + "config.emi.ui.empty_search_sidebar_focus": "Tyhjän haun sivupalkin fokus", + + "config.emi.ui.left_sidebar_pages": "Sivut", + "config.emi.ui.left_sidebar_subpanels": "Alapaneelit", + "config.emi.ui.left_sidebar_size": "Koko", + "config.emi.ui.left_sidebar_margins": "Marginaalit", + "config.emi.ui.left_sidebar_align": "Tasaus", + "config.emi.ui.left_sidebar_header": "Otsake", + "config.emi.ui.left_sidebar_theme": "Teema", + + "config.emi.ui.right_sidebar_pages": "Sivut", + "config.emi.ui.right_sidebar_subpanels": "Alapaneelit", + "config.emi.ui.right_sidebar_size": "Koko", + "config.emi.ui.right_sidebar_margins": "Marginaalit", + "config.emi.ui.right_sidebar_align": "Tasaus", + "config.emi.ui.right_sidebar_header": "Otsake", + "config.emi.ui.right_sidebar_theme": "Teema", + + "config.emi.ui.top_sidebar_pages": "Sivut", + "config.emi.ui.top_sidebar_subpanels": "Alapaneelit", + "config.emi.ui.top_sidebar_size": "Koko", + "config.emi.ui.top_sidebar_margins": "Marginaalit", + "config.emi.ui.top_sidebar_align": "Tasaus", + "config.emi.ui.top_sidebar_header": "Otsake", + "config.emi.ui.top_sidebar_theme": "Teema", + + "config.emi.ui.bottom_sidebar_pages": "Sivut", + "config.emi.ui.bottom_sidebar_subpanels": "Alapaneelit", + "config.emi.ui.bottom_sidebar_size": "Koko", + "config.emi.ui.bottom_sidebar_margins": "Marginaalit", + "config.emi.ui.bottom_sidebar_align": "Tasaus", + "config.emi.ui.bottom_sidebar_header": "Otsake", + "config.emi.ui.bottom_sidebar_theme": "Teema", + + "config.emi.ui.vertical_margin": "Pystymarginaali", + "config.emi.ui.minimum_recipe_screen_width": "Reseptinäkymän minimileveys", + "config.emi.ui.workstation_location": "Työpisteen sijainti", + "config.emi.ui.miscraft_prevention": "Vahinkovalmistuksen esto", + "config.emi.ui.fluid_unit": "Fluidiyksikkö", + "config.emi.ui.show_cost_per_batch": "Näytä kulut erää kohden", + "config.emi.ui.recipe_default_button": "Reseptin oletuspainike", + "config.emi.ui.recipe_tree_button": "Reseptin puupainike", + "config.emi.ui.recipe_fill_button": "Reseptin täyttöpainike", + "config.emi.ui.recipe_screenshot_button": "Reseptin kuvakaappauspainike", + "config.emi.ui.recipe_screenshot_scale": "Reseptin kuvakaappauksen skaala", + "config.emi.ui.use_batched_renderer": "Piirrä erissä", + + "config.emi.dev.dev_mode": "Kehittäjätila", + "config.emi.dev.edit_mode": "Muokkaustila", + "config.emi.dev.log_untranslated_tags": "Kirjoita kääntämättömät tunnisteet lokiin", + "config.emi.dev.log_non_tag_ingredients": "Kirjoita lokiin raaka-aineet, jotka eivät ole tunnisteita", + "config.emi.dev.show_recipe_ids": "Näytä reseptien ID:t", + "config.emi.dev.highlight_defaulted": "Korosta määritetyt oletukset", + "config.emi.dev.highlight_exclusion_areas": "Korosta poissuljetut alueet", + + "config.emi.presets.sidebars": "Sivupalkit", + "config.emi.presets.binds": "Näppäimet", + "config.emi.presets.restore": "Palauta", + + "config.emi.presets.empty_search_craftable": "Tyhjä haku: valmistettavat", + "config.emi.presets.recipe_book_plus": "Reseptikirja plus", + + "config.emi.presets.author_binds": "Tekijän näppäimet", + + "config.emi.presets.backup": "Palauta varmuuskopio", + "config.emi.presets.defaults": "Palauta oletukset", + + "emi.unit.liters": "Litrat", + "emi.unit.millibuckets": "Milliämpärit", + "emi.unit.droplets": "Tipat", + "emi.fluid.amount.liters": "%s l", + "emi.fluid.amount.millibuckets": "%s mÄ", + "emi.fluid.amount.droplets": "%s tp", + + "emi.disabled": "EMI pois käytöstä! Kytke näppäimellä", + "emi.reloading": "EMI lataa...", + "emi.reloading.waiting": "EMI odottaa reseptitietoja palvelimelta...", + "emi.reloading.error": "§cEMI kohtasi vakavan virheen lataamisen aikana, tarkista loki", + "emi.reloading.worry": "§cLataamisessa on viivettä, onko kaikki kunnossa?", + "emi.search": "Hae EMIstä...", + "emi.search_config": "Hae asetuksista...", + "emi.delete_stack": "§cPoista pidelty pino", + "emi.inapplicable": "Tämä työpiste ei tue reseptiä", + "emi.not_enough_ingredients": "Ei tarpeeksi raaka-aineita", + "emi.too_small": "Työstämisruudukko liian pieni raaka-aineille", + "emi.favorite_recipe": "Merkitse resepti suosikiksi painamalla %s", + "emi.resolve.resolve": "Käytä tätä reseptipuussa painamalla %s", + "emi.resolve.default": "Käytä oletuksena kaikissa puissa painamalla %s", + "emi.page": "Sivu %s/%s", + "emi.page.short": "%s/%s", + "emi.total_cost": "Kulut yhteensä", + "emi.cost_per": "Kulut erää kohden:", + "emi.leftovers": "Ylijäämät", + "emi.view_all_recipes": "Katso kaikki reseptit klikkaamalla", + "emi.tree_welcome": "Tervetuloa %sin", + "emi.no_tree": "Et ole vielä asettanut katseltavaa reseptipuuta...", + "emi.random_tree": "Haluaisitko kenties nähdä satunnaisen?", + "emi.random_tree_input": "Paina §6[ctrl + r]", + "emi.edit_mode.hide_one": "Piilota pino painamalla %s", + "emi.edit_mode.hide_all": "Piilota pinoja ID:n perusteella painamalla %s", + "tooltip.emi.chance.consume": "Kulutuksen todennäköisyys: %s%%", + "tooltip.emi.chance.produce": "Tuottamisen todennäköisyys: %s%%", + "tooltip.emi.accepts": "Hyväksyy:", + "tooltip.emi.fill_recipe": "Täytä resepti", + "tooltip.emi.fill_recipe_no_server": "Reseptiä ei voida täyttää ilman EMIä palvelimella", + "tooltip.emi.set_default": "Aseta oletusreseptiksi", + "tooltip.emi.current_defaults": "Tällä hetkellä oletusreseptinä näille:", + "tooltip.emi.unset_default": "Poista oletusresepti", + "tooltip.emi.set_default_stack": "Aseta tuotoksen pinolle oletusresepti painamalla %s", + "tooltip.emi.view_tree": "Katso reseptipuu", + "tooltip.emi.recipe_screenshot": "Ota kuvakaappaus reseptistä", + "tooltip.emi.resolution": "Selvitetään raaka-aineen reseptipuuta", + "tooltip.emi.select_resolution": "Klikkaa §6reseptin tuotosta§r asettaaksesi §dtälle§r reseptipuulle", + "tooltip.emi.default_resolution": "Klikkaa §6reseptin oletuspainiketta§r asettaaksesi §akaikille§r reseptipuille", + "tooltip.emi.clear_resolution": "Paina §6tästä§r §ctyhjentääksesi§r selvityksen", + + "tooltip.emi.config": "%s-asetukset", + "tooltip.emi.recipe_tree": "Reseptipuu", + + "tooltip.emi.config.global": "Kytke kaikkien peliasennusten välillä jaetut EMI-asetukset jokaisen asennuksen omien asetusten sijaan", + + "tooltip.emi.synfav.uncraftable": "Ei voida valmistaa §cyhtään§r erää", + "tooltip.emi.synfav.partially_craftable": "Voidaan valmistaa §djoitakin§r eriä", + "tooltip.emi.synfav.fully_craftable": "Voidaan valmistaa §akaikki %s§r erää", + "tooltip.emi.synfav.craft_some": "Valmista mahdollisimman monta erää painamalla %s", + "tooltip.emi.synfav.craft_all": "Valmista kaikki §9%2$s§r erää painamalla %1$s", + + "tooltip.emi.bom.batch_size": "Erän koko: %s\nSäädä vierittämällä\nSäädä 16 kerralla pitämällä pohjassa §6[shift]§r-näppäintä", + "tooltip.emi.bom.batch_size.ideal": "Hanki vähäisimmät ylijäämät painamalla %s", + "tooltip.emi.bom.mode.view": "§6Katsotaan§r reseptipuuta", + "tooltip.emi.bom.mode.craft": "§6Valmistetaan§r reseptipuuta\nEdistyminen näkyy reseptipuussa\n§bSynteettiset suosikit§r lisätty sivupalkkiin", + "tooltip.emi.bom.help": "Reseptipuu näyttää reseptin prosessin ja pohjakulut\nNäkymää voi siirrellä ja suurentaa\n\nAseta solmukohdan resepti hiiren vasemmalla painikkeella\nValitse automaattisesti tavaraluettelon perusteella §6[shift]§r-näppäimellä\n\nPienennä reseptisolmu väliaikaisesti hiiren oikealla painikkeella\nTyhjennä resepti §6[shift]§r-näppäimellä\n\nPuun lähtötilaa ohjataan oletusresepteillä\nOletusreseptit voi asettaa reseptien viereisellä painikkeella\n\nReseptipuun valmistamisessa voi auttaa kokonaiskulujen kytkeminen\nValmistuksen aikana näytetään materiaalit, jotka täytyy kerätä\nSuosikkipalkkiin lisätään §bsynteettisiä suosikkeja§r, jotka näyttävät\nkeskeneräiset vaiheet ja joita voi käyttää valmistamiseen", + + "tooltip.emi.fluid_interaction.basalt.soul_soil": "Laavan alla", + "tooltip.emi.fluid_interaction.basalt.blue_ice": "Laavan vieressä", + + "screen.emi.recipe": "Resepti", + "screen.emi.config": "Asetukset", + "screen.emi.presets": "Esiasetukset", + + "screen.emi.config.reset": "Kumoa %s muutos(ta)", + + "emi.error.recipe.initialize": "Käynnistysvirhe", + "emi.error.recipe.render": "Piirtämisvirhe", + + "emi.chess.piece.white_pawn": "Valkoinen sotilas", + "emi.chess.piece.white_rook": "Valkoinen torni", + "emi.chess.piece.white_knight": "Valkoinen ratsu", + "emi.chess.piece.white_bishop": "Valkoinen lähetti", + "emi.chess.piece.white_queen": "Valkoinen kuningatar", + "emi.chess.piece.white_king": "Valkoinen kuningas", + "emi.chess.piece.black_pawn": "Musta sotilas", + "emi.chess.piece.black_rook": "Musta torni", + "emi.chess.piece.black_knight": "Musta ratsu", + "emi.chess.piece.black_bishop": "Musta lähetti", + "emi.chess.piece.black_queen": "Musta kuningatar", + "emi.chess.piece.black_king": "Musta kuningas", + "emi.chess.tooltip.invite": "Kutsu hakupalkkisi pelaaja pelaamaan shakkia", + "emi.chess.tooltip.accept": "Hyväksy pelaajan %s shakkikutsu", + "emi.chess.tooltip.decline": "Kieltäydy pelaajan %s shakkikutsusta hiiren oikealla painikkeella", + "emi.chess.tooltip.restart": "Aloita alusta hiiren oikealla painikkeella", + "emi.chess.multiplayer.invited": "%s kutsui sinut pelaamaan shakkia", + "emi.chess.multiplayer.accepted": "%s hyväksyi kutsusi pelata shakkia", + "emi.chess.multiplayer.cancelled": "%s perui shakkipelin", + "emi.chess.multiplayer.unavailable": "%s ei voi pelata shakkia", + + "emi.cooking.experience": "%s XP", + "emi.cooking.time": "%s sekunti(a)", + "emi.grinding.experience": "%s - %s XP", + "emi.fuel_time.items": "Sulattaa %s tavaraa", + + "emi.category.minecraft.crafting": "Työstäminen", + "emi.category.minecraft.smelting": "Sulattaminen", + "emi.category.minecraft.blasting": "Lietsottu sulattaminen", + "emi.category.minecraft.smoking": "Savustaminen", + "emi.category.minecraft.campfire_cooking": "Paistaminen nuotiolla", + "emi.category.minecraft.stonecutting": "Kiven leikkaaminen", + "emi.category.minecraft.smithing": "Taonta", + "emi.category.emi.anvil_repairing": "Korjaus alasimella", + "emi.category.minecraft.brewing": "Hauduttaminen", + "emi.category.emi.grinding": "Tahkoaminen", + "emi.category.emi.world_interaction": "Vuorovaikutus maailmassa", + "emi.category.emi.fuel": "Polttoaine", + "emi.category.emi.composting": "Kompostointi", + "emi.category.emi.info": "Tiedot", + + "emi.category.emi.tag": "Tunnisteet", + "emi.category.emi.ingredient": "Raaka-aineet", + + "alias.emi.workbench": "Työpiste", + + "tag.item.minecraft.logs": "Halot", + "tag.item.minecraft.oak_logs": "Tammihalot", + "tag.item.minecraft.birch_logs": "Koivuhalot", + "tag.item.minecraft.spruce_logs": "Kuusihalot", + "tag.item.minecraft.jungle_logs": "Viidakkopuuhalot", + "tag.item.minecraft.dark_oak_logs": "Tummat tammihalot", + "tag.item.minecraft.crimson_stems": "Karmiinivarret", + "tag.item.minecraft.warped_stems": "Kummavarret", + "tag.item.minecraft.acacia_logs": "Akaasiahalot", + "tag.item.minecraft.logs_that_burn": "Palavat halot", + "tag.item.minecraft.planks": "Laudat", + "tag.item.minecraft.non_flammable_wood": "Palamaton puu", + "tag.item.minecraft.coal_ores": "Hiilimalmit", + "tag.item.minecraft.copper_ores": "Kuparimalmit", + "tag.item.minecraft.diamond_ores": "Timanttimalmit", + "tag.item.minecraft.emerald_ores": "Smaragdimalmit", + "tag.item.minecraft.gold_ores": "Kultamalmit", + "tag.item.minecraft.iron_ores": "Rautamalmit", + "tag.item.minecraft.lapis_ores": "Lasuriittimalmit", + "tag.item.minecraft.redstone_ores": "Redstone-malmit", + "tag.item.minecraft.anvil": "Alasimet", + "tag.item.minecraft.arrows": "Nuolet", + "tag.item.minecraft.axolotl_tempt_items": "Aksolotlin houkuttelijat", + "tag.item.minecraft.banners": "Viirit", + "tag.item.minecraft.beacon_payment_items": "Merkkivalon maksuvälineet", + "tag.item.minecraft.beds": "Sängyt", + "tag.item.minecraft.boats": "Veneet", + "tag.item.minecraft.buttons": "Napit", + "tag.item.minecraft.candles": "Kynttilät", + "tag.item.minecraft.carpets": "Matot", + "tag.item.minecraft.coals": "Hiilet", + "tag.item.minecraft.creeper_drop_music_discs": "Creepereiden tiputtamat musiikkilevyt", + "tag.item.minecraft.creeper_igniters": "Creepereiden sytyttäjät", + "tag.item.minecraft.dirt": "Multa", + "tag.item.minecraft.doors": "Ovet", + "tag.item.minecraft.fences": "Aidat", + "tag.item.minecraft.fence_gates": "Portit", + "tag.item.minecraft.fishes": "Kalat", + "tag.item.minecraft.flowers": "Kukat", + "tag.item.minecraft.fox_food": "Ketun ruoka", + "tag.item.minecraft.freeze_immune_wearables": "Jäätymisen kestävät varusteet", + "tag.item.minecraft.ignored_by_piglin_babies": "Piglinvauvojen sivuuttama", + "tag.item.minecraft.leaves": "Lehdet", + "tag.item.minecraft.lectern_books": "Kateederikirjat", + "tag.item.minecraft.music_discs": "Musiikkilevyt", + "tag.item.minecraft.occludes_vibration_signals": "Peittää värinäsignaalit", + "tag.item.minecraft.piglin_food": "Piglinin ruoka", + "tag.item.minecraft.piglin_loved": "Piglinien rakastama", + "tag.item.minecraft.piglin_repellents": "Piglinien karkottajat", + "tag.item.minecraft.rails": "Raiteet", + "tag.item.minecraft.sand": "Hiekka", + "tag.item.minecraft.saplings": "Taimet", + "tag.item.minecraft.signs": "Kyltit", + "tag.item.minecraft.slabs": "Laatat", + "tag.item.minecraft.small_flowers": "Pienet kukat", + "tag.item.minecraft.soul_fire_base_blocks": "Sielutulen pohjat", + "tag.item.minecraft.stairs": "Portaat", + "tag.item.minecraft.stone_bricks": "Kivitiilet", + "tag.item.minecraft.stone_crafting_materials": "Kiviset työstömateriaalit", + "tag.item.minecraft.stone_tool_materials": "Kiviset työkalumateriaalit", + "tag.item.minecraft.tall_flowers": "Korkeat kukat", + "tag.item.minecraft.terracotta": "Terrakotta", + "tag.item.minecraft.trapdoors": "Luukut", + "tag.item.minecraft.walls": "Muurit", + "tag.item.minecraft.wooden_buttons": "Puunapit", + "tag.item.minecraft.wooden_doors": "Puuovet", + "tag.item.minecraft.wooden_fences": "Puuaidat", + "tag.item.minecraft.wooden_pressure_plates": "Puupainelaatat", + "tag.item.minecraft.wooden_slabs": "Puulaatat", + "tag.item.minecraft.wooden_stairs": "Puuportaat", + "tag.item.minecraft.wooden_trapdoors": "Puuluukut", + "tag.item.minecraft.wool": "Villa", + "tag.item.minecraft.wart_blocks": "Pahkakuutiot", + "tag.item.minecraft.wool_carpets": "Villamatot", + "tag.item.minecraft.mangrove_logs": "Mangrovepuuhalot", + "tag.item.minecraft.compasses": "Kompassit", + "tag.item.minecraft.chest_boats": "Veneet arkuilla", + "tag.item.minecraft.overworld_natural_logs": "Luonnolliset ylämaailman halot", + "tag.item.minecraft.axes": "Kirveet", + "tag.item.minecraft.hoes": "Kuokat", + "tag.item.minecraft.pickaxes": "Hakut", + "tag.item.minecraft.shovels": "Lapiot", + "tag.item.minecraft.smelts_to_glass": "Sulaa lasiksi", + "tag.item.minecraft.swords": "Miekat", + "tag.item.minecraft.tools": "Työkalut", + + "tag.fluid.minecraft.water": "Vesi", + "tag.fluid.minecraft.lava": "Laava", + "tag.fluid.c.water": "Vesi", + "tag.fluid.c.lava": "Laava", + "tag.fluid.c.milk": "Maito", + + "tag.item.c.stone": "Kivi", + "tag.item.c.cobblestone": "Mukulakivi", + "tag.item.c.cobblestone.deepslate": "Murtunut pohjaliuskekivi", + "tag.item.c.cobblestone.infested": "Saastunut mukulakivi", + "tag.item.c.cobblestone.mossy": "Sammaleinen mukulakivi", + "tag.item.c.cobblestone.normal": "Mukulakivi", + "tag.item.c.sandstone": "Hiekkakivi", + "tag.item.c.glass_blocks": "Lasikuutiot", + "tag.item.c.stained_glass": "Värjätty lasi", + "tag.item.c.stained_glass_panes": "Värjätyt lasipaneelit", + "tag.item.c.glass": "Lasi", + "tag.item.c.glass.colorless": "Väritön lasi", + "tag.item.c.glass.silica": "Silikalasi", + "tag.item.c.quartz_blocks": "Kvartsikuutiot", + "tag.item.c.glass_panes": "Lasipaneelit", + "tag.item.c.glass.tinted": "Värjätty lasi", + "tag.item.c.glass_panes.colorless": "Värittömät lasipaneelit", + "tag.item.c.raw_materials": "Raakamateriaalit", + "tag.item.c.rods": "Sauvat", + "tag.item.c.ores": "Malmit", + "tag.item.c.nuggets": "Hiput", + "tag.item.c.ingots": "Harkot", + "tag.item.c.gems": "Jalokivet", + "tag.item.c.plates": "Levyt", + "tag.item.c.dusts": "Jauheet", + "tag.item.c.storage_blocks": "Varastointikuutiot", + "tag.item.c.seeds": "Siemenet", + "tag.item.c.crops": "Viljelykasvit", + "tag.item.c.heads": "Päät", + "tag.item.c.dyes": "Väriaineet", + "tag.item.c.mushrooms": "Sienet", + "tag.item.c.fence_gates": "Portit", + "tag.item.c.fence_gates.wooden": "Puuportit", + "tag.item.c.chests": "Arkut", + "tag.item.c.wooden_chests": "Puuarkut", + "tag.item.c.ores_in_ground.stone": "Kivimalmit", + "tag.item.c.ores_in_ground.deepslate": "Pohjaliuskemalmit", + "tag.item.c.ores_in_ground.netherrack": "Netherrack-malmit", + + "tag.item.c.chest": "Arkut", + "tag.item.c.coal": "Hiilet", + "tag.item.c.sand": "Hiekat", + "tag.item.c.glass_pane": "Lasipaneelit", + "tag.item.c.beacon_payment": "Merkkivalon maksuvälineet", + "tag.item.c.fences": "Aidat", + "tag.item.c.fences.wooden": "Puuaidat", + "tag.item.c.ores.coal": "Hiilimalmit", + "tag.item.c.ores.copper": "Kuparimalmit", + "tag.item.c.ores.iron": "Rautamalmit", + "tag.item.c.ores.gold": "Kultamalmit", + "tag.item.c.ores.redstone": "Redstone-malmit", + "tag.item.c.ores.lapis": "Lasuriittimalmit", + "tag.item.c.ores.emerald": "Smaragdimalmit", + "tag.item.c.ores.diamond": "Timanttimalmit", + + "tag.item.c.storage_blocks.coal": "Hiilen varastointikuutiot", + + "tag.item.c.raw_materials.copper": "Raaka kupari", + "tag.item.c.copper_dusts": "Kuparijauheet", + "tag.item.c.dusts.copper": "Kuparijauheet", + "tag.item.c.copper_ingots": "Kupariharkot", + "tag.item.c.ingots.copper": "Kupariharkot", + "tag.item.c.copper_nuggets": "Kuparihiput", + "tag.item.c.nuggets.copper": "Kuparihiput", + "tag.item.c.plates.copper": "Kuparilevyt", + "tag.item.c.raw_copper_ores": "Raa'at kuparimalmit", + "tag.item.c.raw_copper_blocks": "Raa'at kuparikuutiot", + "tag.item.c.copper_blocks": "Kuparikuutiot", + "tag.item.c.storage_blocks.raw_copper": "Raa'an kuparin varastointikuutiot", + "tag.item.c.storage_blocks.copper": "Kuparin varastointikuutiot", + + "tag.item.c.raw_materials.iron": "Raaka rauta", + "tag.item.c.iron_dusts": "Rautajauheet", + "tag.item.c.dusts.iron": "Rautajauheet", + "tag.item.c.iron_ingots": "Rautaharkot", + "tag.item.c.ingots.iron": "Rautaharkot", + "tag.item.c.iron_nuggets": "Rautahiput", + "tag.item.c.nuggets.iron": "Rautahiput", + "tag.item.c.plates.iron": "Rautalevyt", + "tag.item.c.raw_iron_ores": "Raa'at rautamalmit", + "tag.item.c.raw_iron_blocks": "Raa'at rautakuutiot", + "tag.item.c.iron_blocks": "Rautakuutiot", + "tag.item.c.storage_blocks.raw_iron": "Raa'an raudan varastointikuutiot", + "tag.item.c.storage_blocks.iron": "Raudan varastointikuutiot", + + "tag.item.c.raw_materials.gold": "Raaka kulta", + "tag.item.c.gold_dusts": "Kultajauheet", + "tag.item.c.dusts.gold": "Kultajauheet", + "tag.item.c.gold_ingots": "Kultaharkot", + "tag.item.c.ingots.gold": "Kultaharkot", + "tag.item.c.gold_nuggets": "Kultahiput", + "tag.item.c.nuggets.gold": "Kultahiput", + "tag.item.c.plates.gold": "Kultalevyt", + "tag.item.c.raw_gold_ores": "Raa'at kultamalmit", + "tag.item.c.raw_gold_blocks": "Raa'at kultakuutiot", + "tag.item.c.gold_blocks": "Kultakuutiot", + "tag.item.c.storage_blocks.gold": "Kullan varastointikuutiot", + "tag.item.c.storage_blocks.raw_gold": "Raa'an kullan varastointikuutiot", + + "tag.item.c.gems.amethyst": "Ametistit", + "tag.item.c.amethyst_dusts": "Ametistijauheet", + "tag.item.c.storage_blocks.amethyst": "Ametistien varastointikuutiot", + + "tag.item.c.storage_blocks.diamond": "Timanttien varastointikuutiot", + "tag.item.c.storage_blocks.emerald": "Smaradgien varastointikuutiot", + "tag.item.c.storage_blocks.lapis": "Lasuriitin varastointikuutiot", + "tag.item.c.storage_blocks.netherite": "Netheriitin varastointikuutiot", + "tag.item.c.storage_blocks.quartz": "Kvartsin varastointikuutiot", + "tag.item.c.storage_blocks.redstone": "Redstonen varastointikuutiot", + "tag.item.c.redstone_dusts": "Redstone-jauheet", + "tag.item.c.redstone_ores": "Redstone-malmit", + "tag.item.c.quartz": "Kvartsi", + "tag.item.c.quartz_ores": "Kvartsimalmit", + "tag.item.c.diamond_dusts": "Timanttijauheet", + "tag.item.c.diamonds": "Timantit", + "tag.item.c.dusts.glowstone": "Hehkukivijauheet", + "tag.item.c.dusts.prismarine": "Prismariinijauheet", + "tag.item.c.dusts.redstone": "Redstone-jauheet", + "tag.item.c.emeralds": "Smaragdit", + "tag.item.c.ender_pearl_dusts": "Ender-helmijauheet", + "tag.item.c.ender_pearls": "Ender-helmet", + "tag.item.c.gems.diamond": "Timantit", + "tag.item.c.gems.emerald": "Smaragdit", + "tag.item.c.gems.lapis": "Lasuriitti", + "tag.item.c.gems.prismarine": "Prismariini", + "tag.item.c.gems.quartz": "Kvartsi", + "tag.item.c.ingots.brick": "Tiilet", + "tag.item.c.ingots.nether_brick": "Nether-tiilet", + "tag.item.c.ingots.netherite": "Netheriittiharkot", + "tag.item.c.lapis": "Lasuriitti", + "tag.item.c.nether_quartz_dusts": "Nether-kvartsijauheet", + "tag.item.c.netherite_ingots": "Netheriittiharkot", + "tag.item.c.netherite_scrap_dusts": "Netheriittiromujauheet", + "tag.item.c.ores.netherite_scrap": "Netheriittiromumalmit", + "tag.item.c.ores.quartz": "Kvartsimalmit", + + "tag.item.c.spears": "Keihäät", + "tag.item.c.axes": "Kirveet", + "tag.item.c.barrels": "Tynnyrit", + "tag.item.c.barrels.wooden": "Puutynnyrit", + "tag.item.c.white_dyes": "Valkoiset väriaineet", + "tag.item.c.orange_dyes": "Oranssit väriaineet", + "tag.item.c.magenta_dyes": "Purppurat väriaineet", + "tag.item.c.light_blue_dyes": "Vaaleansiniset väriaineet", + "tag.item.c.yellow_dyes": "Keltaiset väriaineet", + "tag.item.c.lime_dyes": "Limetinvihreät väriaineet", + "tag.item.c.pink_dyes": "Vaaleanpunaiset väriaineet", + "tag.item.c.gray_dyes": "Harmaat väriaineet", + "tag.item.c.light_gray_dyes": "Vaaleanharmaat väriaineet", + "tag.item.c.cyan_dyes": "Syaanit väriaineet", + "tag.item.c.purple_dyes": "Violetit väriaineet", + "tag.item.c.blue_dyes": "Siniset väriaineet", + "tag.item.c.brown_dyes": "Ruskeat väriaineet", + "tag.item.c.green_dyes": "Vihreät väriaineet", + "tag.item.c.red_dyes": "Punaiset väriaineet", + "tag.item.c.black_dyes": "Mustat väriaineet", + "tag.item.c.dyes.white": "Valkoiset väriaineet", + "tag.item.c.dyes.orange": "Oranssit väriaineet", + "tag.item.c.dyes.magenta": "Purppurat väriaineet", + "tag.item.c.dyes.light_blue": "Vaaleansiniset väriaineet", + "tag.item.c.dyes.yellow": "Keltaiset väriaineet", + "tag.item.c.dyes.lime": "Limetinvihreät väriaineet", + "tag.item.c.dyes.pink": "Vaaleanpunaiset väriaineet", + "tag.item.c.dyes.gray": "Harmaat väriaineet", + "tag.item.c.dyes.light_gray": "Vaaleanharmaat väriaineet", + "tag.item.c.dyes.cyan": "Syaanit väriaineet", + "tag.item.c.dyes.purple": "Violetit väriaineet", + "tag.item.c.dyes.blue": "Siniset väriaineet", + "tag.item.c.dyes.brown": "Ruskeat väriaineet", + "tag.item.c.dyes.green": "Vihreät väriaineet", + "tag.item.c.dyes.red": "Punaiset väriaineet", + "tag.item.c.dyes.black": "Mustat väriaineet", + "tag.item.c.glass.white": "Valkoinen lasi", + "tag.item.c.glass.orange": "Oranssi lasi", + "tag.item.c.glass.magenta": "Purppura lasi", + "tag.item.c.glass.light_blue": "Vaaleansininen lasi", + "tag.item.c.glass.yellow": "Keltainen lasi", + "tag.item.c.glass.lime": "Limetinvihreä lasi", + "tag.item.c.glass.pink": "Vaaleanpunainen lasi", + "tag.item.c.glass.gray": "Harmaa lasi", + "tag.item.c.glass.light_gray": "Vaaleanharmaa lasi", + "tag.item.c.glass.cyan": "Syaani lasi", + "tag.item.c.glass.purple": "Violetti lasi", + "tag.item.c.glass.blue": "Sininen lasi", + "tag.item.c.glass.brown": "Ruskea lasi", + "tag.item.c.glass.green": "Vihreä lasi", + "tag.item.c.glass.red": "Punainen lasi", + "tag.item.c.glass.black": "Musta lasi", + "tag.item.c.glass_panes.white": "Valkoiset lasipaneelit", + "tag.item.c.glass_panes.orange": "Oranssit lasipaneelit", + "tag.item.c.glass_panes.magenta": "Purppurat lasipaneelit", + "tag.item.c.glass_panes.light_blue": "Vaaleansiniset lasipaneelit", + "tag.item.c.glass_panes.yellow": "Keltaiset lasipaneelit", + "tag.item.c.glass_panes.lime": "Limetinvihreät lasipaneelit", + "tag.item.c.glass_panes.pink": "Vaaleanpunaiset lasipaneelit", + "tag.item.c.glass_panes.gray": "Harmaat lasipaneelit", + "tag.item.c.glass_panes.light_gray": "Vaaleanharmaat lasipaneelit", + "tag.item.c.glass_panes.cyan": "Syaanit lasipaneelit", + "tag.item.c.glass_panes.purple": "Violetit lasipaneelit", + "tag.item.c.glass_panes.blue": "Siniset lasipaneelit", + "tag.item.c.glass_panes.brown": "Ruskeat lasipaneelit", + "tag.item.c.glass_panes.green": "Vihreät lasipaneelit", + "tag.item.c.glass_panes.red": "Punaiset lasipaneelit", + "tag.item.c.glass_panes.black": "Mustat lasipaneelit", + "tag.item.c.bones": "Luut", + "tag.item.c.bookshelves": "Kirjahyllyt", + "tag.item.c.bows": "Jouset", + "tag.item.c.buckets.honey": "Hunajaämpärit", + "tag.item.c.chests.ender": "Ender-arkut", + "tag.item.c.chests.trapped": "Ansoitetut arkut", + "tag.item.c.chests.wooden": "Puuarkut", + "tag.item.c.circuits": "Virtapiirit", + "tag.item.c.crops.beetroot": "Punajuuret", + "tag.item.c.crops.carrot": "Porkkanat", + "tag.item.c.crops.nether_wart": "Nether-pahkat", + "tag.item.c.crops.potato": "Perunat", + "tag.item.c.crops.wheat": "Vehnä", + "tag.item.c.eggs": "Munat", + "tag.item.c.empty_buckets": "Tyhjät ämpärit", + "tag.item.c.enchanting_fuels": "Lumoamisen polttoaineet", + "tag.item.c.end_stones": "End-kivet", + "tag.item.c.feathers": "Sulat", + "tag.item.c.fences.nether_brick": "Nether-tiiliaidat", + "tag.item.c.foods": "Ruoka", + "tag.item.c.gravel": "Sora", + "tag.item.c.gunpowder": "Ruuti", + "tag.item.c.hoes": "Kuokat", + "tag.item.c.lava_buckets": "Laavaämpärit", + "tag.item.c.leather": "Nahka", + "tag.item.c.milk_bottles": "Maitopullot", + "tag.item.c.milk_buckets": "Maitoämpärit", + "tag.item.c.nether_stars": "Nether-tähdet", + "tag.item.c.netherrack": "Netherrack", + "tag.item.c.obsidian": "Obsidiaani", + "tag.item.c.pickaxes": "Hakut", + "tag.item.c.potions": "Taikajuomat", + "tag.item.c.red_sandstone": "Punahiekkakivi", + "tag.item.c.red_sandstone_slabs": "Punahiekkakivilaatat", + "tag.item.c.red_sandstone_stairs": "Punahiekkakiviportaat", + "tag.item.c.rods.blaze": "Roihusauvat", + "tag.item.c.rods.wooden": "Puusauvat", + "tag.item.c.sand.colorless": "Väritön hiekka", + "tag.item.c.sand.red": "Punahiekka", + "tag.item.c.sandstone_slabs": "Hiekkakivilaatat", + "tag.item.c.sandstone_stairs": "Hiekkakiviportaat", + "tag.item.c.seeds.beetroot": "Punajuuren siemenet", + "tag.item.c.seeds.melon": "Melonin siemenet", + "tag.item.c.seeds.pumpkin": "Kurpitsan siemenet", + "tag.item.c.seeds.wheat": "Vehnän siemenet", + "tag.item.c.shears": "Keritsimet", + "tag.item.c.shields": "Kilvet", + "tag.item.c.shovels": "Lapiot", + "tag.item.c.shulker_boxes": "Shulker-laatikot", + "tag.item.c.skulls": "Kallot", + "tag.item.c.slime_balls": "Limapallot", + "tag.item.c.slimeballs": "Limapallot", + "tag.item.c.stone_dusts": "Kivijauheet", + "tag.item.c.stones": "Kivet", + "tag.item.c.string": "Lanka", + "tag.item.c.strings": "Lanka", + "tag.item.c.swords": "Miekat", + "tag.item.c.water_buckets": "Vesiämpärit", + "tag.item.c.wrenches": "Kiintoavaimet", + + "tag.item.c.armors": "Haarniskan osat", + "tag.item.c.armors.boots": "Saappaat", + "tag.item.c.armors.chestplates": "Rintapanssarit", + "tag.item.c.armors.helmets": "Kypärät", + "tag.item.c.armors.leggings": "Housut", + "tag.item.c.tools": "Työkalut", + "tag.item.c.tools.axes": "Kirveet", + "tag.item.c.tools.bows": "Jouset", + "tag.item.c.tools.crossbows": "Varsijouset", + "tag.item.c.tools.fishing_rods": "Onkivavat", + "tag.item.c.tools.hoes": "Kuokat", + "tag.item.c.tools.pickaxes": "Hakut", + "tag.item.c.tools.shields": "Kilvet", + "tag.item.c.tools.shovels": "Lapiot", + "tag.item.c.tools.swords": "Miekat", + "tag.item.c.tools.tridents": "Atraimet", + + "tag.item.fabric.pickaxes": "Hakut", + "tag.item.fabric.axes": "Kirveet", + "tag.item.fabric.shovels": "Lapiot", + "tag.item.fabric.hoes": "Kuokat", + "tag.item.fabric.swords": "Miekat", + "tag.item.fabric.shears": "Keritsimet" + } + \ No newline at end of file From 192d8e3d898f97c44151917f22d27d1d4ac87ded Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Tue, 13 Jun 2023 19:09:18 -0500 Subject: [PATCH 09/67] Revert "1.20" This reverts commit a5d47f26f27c6368d4df2fb8a89955607dbbbce7. --- gradle.properties | 12 ++--- .../java/dev/emi/emi/EmiRenderHelper.java | 40 ++++++-------- .../main/java/dev/emi/emi/VanillaPlugin.java | 15 +----- .../dev/emi/emi/api/EmiDragDropHandler.java | 8 +-- .../dev/emi/emi/api/recipe/EmiInfoRecipe.java | 2 +- .../emi/api/recipe/EmiIngredientRecipe.java | 12 ++--- .../emi/emi/api/recipe/EmiRecipeCategory.java | 10 ++-- .../api/recipe/handler/EmiRecipeHandler.java | 4 +- .../recipe/handler/StandardRecipeHandler.java | 10 ++-- .../dev/emi/emi/api/render/EmiRender.java | 18 +++---- .../dev/emi/emi/api/render/EmiRenderable.java | 4 +- .../dev/emi/emi/api/render/EmiTexture.java | 6 +-- .../emi/api/render/EmiTooltipComponents.java | 10 ---- .../dev/emi/emi/api/stack/EmiIngredient.java | 8 +-- .../dev/emi/emi/api/stack/EmptyEmiStack.java | 4 +- .../dev/emi/emi/api/stack/FluidEmiStack.java | 8 +-- .../dev/emi/emi/api/stack/ItemEmiStack.java | 17 +++--- .../emi/emi/api/stack/ListEmiIngredient.java | 10 ++-- .../emi/emi/api/stack/TagEmiIngredient.java | 5 +- .../emi/api/widget/AnimatedTextureWidget.java | 6 +-- .../dev/emi/emi/api/widget/ButtonWidget.java | 6 +-- .../emi/emi/api/widget/DrawableWidget.java | 8 +-- .../emi/api/widget/FillingArrowWidget.java | 6 +-- .../emi/api/widget/GeneratedSlotWidget.java | 6 +-- .../dev/emi/emi/api/widget/SlotWidget.java | 28 +++++----- .../dev/emi/emi/api/widget/TankWidget.java | 8 +-- .../dev/emi/emi/api/widget/TextWidget.java | 6 +-- .../dev/emi/emi/api/widget/TextureWidget.java | 6 +-- .../dev/emi/emi/api/widget/TooltipWidget.java | 4 +- .../java/dev/emi/emi/api/widget/Widget.java | 4 +- .../java/dev/emi/emi/chess/ChessEmiStack.java | 4 +- .../emi/emi/handler/CoercedRecipeHandler.java | 4 +- .../dev/emi/emi/jemi/JemiRecipeHandler.java | 4 +- .../main/java/dev/emi/emi/jemi/JemiStack.java | 4 +- .../dev/emi/emi/jemi/impl/JemiRecipeSlot.java | 4 +- .../emi/jemi/runtime/JemiDragDropHandler.java | 4 +- .../emi/emi/jemi/widget/JemiSlotWidget.java | 8 +-- .../emi/emi/jemi/widget/JemiTankWidget.java | 6 +-- .../mixin/AbstractInventoryScreenMixin.java | 26 +++++----- .../emi/mixin/CraftingResultSlotMixin.java | 10 ++-- .../dev/emi/emi/mixin/DrawContextMixin.java | 20 ------- .../dev/emi/emi/mixin/HandledScreenMixin.java | 18 +++---- .../java/dev/emi/emi/mixin/ScreenMixin.java | 20 +++++++ .../dev/emi/emi/mixin/ToastManagerMixin.java | 4 +- .../accessor/CraftingResultSlotAccessor.java | 4 +- .../mixin/accessor/DrawContextAccessor.java | 18 ------- ...java => LegacySmithingRecipeAccessor.java} | 11 ++-- .../emi/mixin/accessor/ScreenAccessor.java | 24 +++++++++ .../SmithingTransformRecipeAccessor.java | 20 ------- .../dev/emi/emi/recipe/EmiSmithingRecipe.java | 37 ++++++------- .../recipe/special/EmiSmithingTrimRecipe.java | 52 ------------------- .../emi/emi/registry/EmiDragDropHandlers.java | 8 +-- .../dev/emi/emi/registry/EmiRecipeFiller.java | 6 +-- .../emi/emi/registry/EmiStackProviders.java | 4 +- .../dev/emi/emi/runtime/EmiDrawContext.java | 42 ++++++++------- .../java/dev/emi/emi/runtime/EmiFavorite.java | 10 ++-- .../emi/runtime/EmiScreenshotRecorder.java | 5 +- .../java/dev/emi/emi/screen/BoMScreen.java | 3 +- .../dev/emi/emi/screen/ConfigEnumScreen.java | 6 +-- .../emi/emi/screen/ConfigPresetScreen.java | 8 +-- .../java/dev/emi/emi/screen/ConfigScreen.java | 6 +-- .../dev/emi/emi/screen/DisabledToast.java | 4 +- .../dev/emi/emi/screen/EmiScreenManager.java | 8 ++- .../java/dev/emi/emi/screen/FakeScreen.java | 3 +- .../java/dev/emi/emi/screen/RecipeScreen.java | 6 +-- .../java/dev/emi/emi/screen/StackBatcher.java | 25 +++++---- .../screen/tooltip/EmiTooltipComponent.java | 8 ++- .../emi/screen/widget/EmiSearchWidget.java | 3 +- .../screen/widget/ResolutionButtonWidget.java | 8 +-- .../emi/screen/widget/SizedButtonWidget.java | 4 +- .../widget/config/ConfigEntryWidget.java | 4 +- .../widget/config/ConfigJumpButton.java | 4 +- .../screen/widget/config/EmiNameWidget.java | 4 +- .../screen/widget/config/GroupNameWidget.java | 4 +- .../emi/screen/widget/config/ListWidget.java | 18 +++---- .../widget/config/SubGroupNameWidget.java | 4 +- .../dev/emi/emi/widget/RecipeBackground.java | 4 +- .../emi/emi/widget/RecipeButtonWidget.java | 4 +- .../widget/RecipeScreenshotButtonWidget.java | 7 +-- .../main/resources/assets/emi/lang/en_us.json | 14 ----- xplat/src/main/resources/emi.mixins.json | 7 ++- 81 files changed, 360 insertions(+), 474 deletions(-) delete mode 100644 xplat/src/main/java/dev/emi/emi/mixin/DrawContextMixin.java create mode 100644 xplat/src/main/java/dev/emi/emi/mixin/ScreenMixin.java delete mode 100644 xplat/src/main/java/dev/emi/emi/mixin/accessor/DrawContextAccessor.java rename xplat/src/main/java/dev/emi/emi/mixin/accessor/{SmithingTrimRecipeAccessor.java => LegacySmithingRecipeAccessor.java} (59%) create mode 100644 xplat/src/main/java/dev/emi/emi/mixin/accessor/ScreenAccessor.java delete mode 100644 xplat/src/main/java/dev/emi/emi/mixin/accessor/SmithingTransformRecipeAccessor.java delete mode 100644 xplat/src/main/java/dev/emi/emi/recipe/special/EmiSmithingTrimRecipe.java diff --git a/gradle.properties b/gradle.properties index b28aabdc..5138bd85 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ org.gradle.jvmargs=-Xmx2048M -minecraft_version=1.20 +minecraft_version=1.19.4 enabled_platforms=fabric,forge archives_base_name=emi @@ -9,11 +9,11 @@ maven_group=dev.emi architectury_version=4.9.83 -yarn_mappings=1.20+build.1 +yarn_mappings=1.19.4+build.2 -fabric_loader_version=0.14.21 -fabric_api_version=0.83.0+1.20 +fabric_loader_version=0.14.19 +fabric_api_version=0.76.0+1.19.4 -forge_version=1.20-46.0.1 +forge_version=1.19.4-45.0.39 -jei_version=jei-1.20-fabric:14.0.0.5 +jei_version=jei-1.19.4-fabric:13.1.0.9 diff --git a/xplat/src/main/java/dev/emi/emi/EmiRenderHelper.java b/xplat/src/main/java/dev/emi/emi/EmiRenderHelper.java index 38864318..5b323fa9 100644 --- a/xplat/src/main/java/dev/emi/emi/EmiRenderHelper.java +++ b/xplat/src/main/java/dev/emi/emi/EmiRenderHelper.java @@ -5,7 +5,6 @@ import org.apache.commons.compress.utils.Lists; import org.joml.Matrix4f; -import org.joml.Vector2i; import com.mojang.blaze3d.systems.RenderSystem; @@ -19,8 +18,8 @@ import dev.emi.emi.api.widget.Widget; import dev.emi.emi.api.widget.WidgetHolder; import dev.emi.emi.config.EmiConfig; -import dev.emi.emi.mixin.accessor.DrawContextAccessor; import dev.emi.emi.mixin.accessor.OrderedTextTooltipComponentAccessor; +import dev.emi.emi.mixin.accessor.ScreenAccessor; import dev.emi.emi.registry.EmiRecipeFiller; import dev.emi.emi.runtime.EmiDrawContext; import dev.emi.emi.screen.EmiScreenManager; @@ -30,7 +29,6 @@ import net.minecraft.client.gui.tooltip.HoveredTooltipPositioner; import net.minecraft.client.gui.tooltip.OrderedTextTooltipComponent; import net.minecraft.client.gui.tooltip.TooltipComponent; -import net.minecraft.client.gui.tooltip.TooltipPositioner; import net.minecraft.client.render.BufferBuilder; import net.minecraft.client.render.Tessellator; import net.minecraft.client.render.VertexFormat.DrawMode; @@ -151,15 +149,13 @@ public static Text getPageText(int page, int total, int maxWidth) { } public static void drawLeftTooltip(Screen screen, EmiDrawContext context, List components, int x, int y) { - drawTooltip(screen, context, components, x, y, screen.width / 2 - 16, - (screenWidth, screenHeight, mouseX, mouseY, tooltipWidth, tooltipHeight) -> { - Vector2i pos = new Vector2i(mouseX, mouseY).add(12, -12); - pos.x = Math.max(pos.x - 24 - tooltipWidth, 4); - if (pos.y + tooltipHeight + 3 > screenHeight) { - pos.y = screenHeight - tooltipHeight - 3; - } - return pos; - }); + int original = screen.width; + try { + screen.width = x; + drawTooltip(screen, context, components, x, y, original / 2 - 16); + } finally { + screen.width = original; + } } public static void drawTooltip(Screen screen, EmiDrawContext context, List components, int x, int y) { @@ -167,10 +163,6 @@ public static void drawTooltip(Screen screen, EmiDrawContext context, List components, int x, int y, int maxWidth) { - drawTooltip(screen, context, components, x, y, maxWidth, HoveredTooltipPositioner.INSTANCE); - } - - public static void drawTooltip(Screen screen, EmiDrawContext context, List components, int x, int y, int maxWidth, TooltipPositioner positioner) { y = Math.max(16, y); // Some mods assume this list will be mutable, oblige them List mutable = Lists.newArrayList(); @@ -198,15 +190,12 @@ public static void drawTooltip(Screen screen, EmiDrawContext context, List T add(T widget) { } }; - context.push(); - context.matrices().translate(x + 4, y + 4, 0); + MatrixStack view = RenderSystem.getModelViewStack(); + view.push(); + view.translate(x + 4, y + 4, 0); + RenderSystem.applyModelViewMatrix(); recipe.addWidgets(holder); float delta = MinecraftClient.getInstance().getTickDelta(); @@ -362,7 +353,8 @@ public T add(T widget) { } } - context.pop(); + view.pop(); + RenderSystem.applyModelViewMatrix(); // Force translucency to match that of the recipe background RenderSystem.disableBlend(); diff --git a/xplat/src/main/java/dev/emi/emi/VanillaPlugin.java b/xplat/src/main/java/dev/emi/emi/VanillaPlugin.java index d0b882ea..5a5eedd7 100644 --- a/xplat/src/main/java/dev/emi/emi/VanillaPlugin.java +++ b/xplat/src/main/java/dev/emi/emi/VanillaPlugin.java @@ -58,8 +58,6 @@ import dev.emi.emi.mixin.accessor.HandledScreenAccessor; import dev.emi.emi.mixin.accessor.HoeItemAccessor; import dev.emi.emi.mixin.accessor.ShovelItemAccessor; -import dev.emi.emi.mixin.accessor.SmithingTransformRecipeAccessor; -import dev.emi.emi.mixin.accessor.SmithingTrimRecipeAccessor; import dev.emi.emi.platform.EmiAgnos; import dev.emi.emi.platform.EmiClient; import dev.emi.emi.recipe.EmiAnvilRecipe; @@ -85,7 +83,6 @@ import dev.emi.emi.recipe.special.EmiGrindstoneDisenchantingRecipe; import dev.emi.emi.recipe.special.EmiMapCloningRecipe; import dev.emi.emi.recipe.special.EmiRepairItemRecipe; -import dev.emi.emi.recipe.special.EmiSmithingTrimRecipe; import dev.emi.emi.recipe.special.EmiSuspiciousStewRecipe; import dev.emi.emi.registry.EmiTags; import dev.emi.emi.runtime.EmiDrawContext; @@ -182,7 +179,7 @@ public class VanillaPlugin implements EmiPlugin { STONECUTTING = new EmiRecipeCategory(new Identifier("minecraft:stonecutting"), EmiStack.of(Items.STONECUTTER), simplifiedRenderer(160, 240), EmiRecipeSorting.compareInputThenOutput()); SMITHING = new EmiRecipeCategory(new Identifier("minecraft:smithing"), - EmiStack.of(Items.SMITHING_TABLE), simplifiedRenderer(240, 224), EmiRecipeSorting.compareInputThenOutput()); + EmiStack.of(Items.SMITHING_TABLE), simplifiedRenderer(240, 224), EmiRecipeSorting.none()); ANVIL_REPAIRING = new EmiRecipeCategory(new Identifier("emi:anvil_repairing"), EmiStack.of(Items.ANVIL), simplifiedRenderer(240, 224), EmiRecipeSorting.none()); GRINDING = new EmiRecipeCategory(new Identifier("emi:grinding"), @@ -417,15 +414,7 @@ public void register(EmiRegistry registry) { addRecipeSafe(registry, () -> new EmiCookingRecipe(recipe, CAMPFIRE_COOKING, 1, true), recipe); } for (SmithingRecipe recipe : registry.getRecipeManager().listAllOfType(RecipeType.SMITHING)) { - //addRecipeSafe(registry, () -> new EmiSmithingRecipe(recipe), recipe); - MinecraftClient client = MinecraftClient.getInstance(); - if (recipe instanceof SmithingTransformRecipeAccessor stra) { - addRecipeSafe(registry, () -> new EmiSmithingRecipe(EmiIngredient.of(stra.getTemplate()), EmiIngredient.of(stra.getBase()), - EmiIngredient.of(stra.getAddition()), EmiStack.of(recipe.getOutput(client.world.getRegistryManager())), recipe.getId()), recipe); - } else if (recipe instanceof SmithingTrimRecipeAccessor stra) { - addRecipeSafe(registry, () -> new EmiSmithingTrimRecipe(EmiIngredient.of(stra.getTemplate()), EmiIngredient.of(stra.getBase()), - EmiIngredient.of(stra.getAddition()), EmiStack.of(recipe.getOutput(client.world.getRegistryManager())), recipe), recipe); - } + addRecipeSafe(registry, () -> new EmiSmithingRecipe(recipe), recipe); } for (StonecuttingRecipe recipe : registry.getRecipeManager().listAllOfType(RecipeType.STONECUTTING)) { addRecipeSafe(registry, () -> new EmiStonecuttingRecipe(recipe), recipe); diff --git a/xplat/src/main/java/dev/emi/emi/api/EmiDragDropHandler.java b/xplat/src/main/java/dev/emi/emi/api/EmiDragDropHandler.java index 59ee1a27..d5878f3e 100644 --- a/xplat/src/main/java/dev/emi/emi/api/EmiDragDropHandler.java +++ b/xplat/src/main/java/dev/emi/emi/api/EmiDragDropHandler.java @@ -16,9 +16,9 @@ import dev.emi.emi.api.widget.Bounds; import dev.emi.emi.mixin.accessor.HandledScreenAccessor; import dev.emi.emi.runtime.EmiDrawContext; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.ingame.HandledScreen; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.screen.ScreenHandler; import net.minecraft.screen.slot.Slot; @@ -33,7 +33,7 @@ public interface EmiDragDropHandler { /** * Called when a stack is being dragged. */ - default void render(T screen, EmiIngredient dragged, DrawContext draw, int mouseX, int mouseY, float delta) { + default void render(T screen, EmiIngredient dragged, MatrixStack matrices, int mouseX, int mouseY, float delta) { } /** @@ -68,8 +68,8 @@ public boolean dropStack(T screen, EmiIngredient stack, int x, int y) { } @Override - public void render(T screen, EmiIngredient dragged, DrawContext draw, int mouseX, int mouseY, float delta) { - EmiDrawContext context = EmiDrawContext.wrap(draw); + public void render(T screen, EmiIngredient dragged, MatrixStack matrices, int mouseX, int mouseY, float delta) { + EmiDrawContext context = EmiDrawContext.wrap(matrices); for (Bounds b : bounds.apply(screen).keySet()) { context.fill(b.x(), b.y(), b.width(), b.height(), 0x8822BB33); } diff --git a/xplat/src/main/java/dev/emi/emi/api/recipe/EmiInfoRecipe.java b/xplat/src/main/java/dev/emi/emi/api/recipe/EmiInfoRecipe.java index e2d5dc22..e15362e9 100644 --- a/xplat/src/main/java/dev/emi/emi/api/recipe/EmiInfoRecipe.java +++ b/xplat/src/main/java/dev/emi/emi/api/recipe/EmiInfoRecipe.java @@ -59,7 +59,7 @@ public int getDisplayWidth() { @Override public int getDisplayHeight() { - int stackHeight = ((Math.min(stacks.size(), MAX_STACKS) - 1) / STACK_WIDTH + 1) * 18; + int stackHeight = ((Math.min(stacks.size(), MAX_STACKS) - 1) / 6 + 1) * 18; return stackHeight + CLIENT.textRenderer.fontHeight * text.size() + PADDING; } diff --git a/xplat/src/main/java/dev/emi/emi/api/recipe/EmiIngredientRecipe.java b/xplat/src/main/java/dev/emi/emi/api/recipe/EmiIngredientRecipe.java index e2535ee9..01bd36ff 100644 --- a/xplat/src/main/java/dev/emi/emi/api/recipe/EmiIngredientRecipe.java +++ b/xplat/src/main/java/dev/emi/emi/api/recipe/EmiIngredientRecipe.java @@ -10,7 +10,7 @@ import dev.emi.emi.api.widget.WidgetHolder; import dev.emi.emi.bom.BoM; import dev.emi.emi.runtime.EmiDrawContext; -import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.util.math.MatrixStack; /** * Represents a recipe that disambiguates an ingredient. @@ -127,16 +127,16 @@ public EmiRecipe getRecipe() { } @Override - public void render(DrawContext draw, int mouseX, int mouseY, float delta) { + public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { if (!getStack().isEmpty()) { - super.render(draw, mouseX, mouseY, delta); + super.render(matrices, mouseX, mouseY, delta); } } @Override - public void drawBackground(DrawContext draw, int mouseX, int mouseY, float delta) { - super.drawBackground(draw, mouseX, mouseY, delta); - EmiDrawContext context = EmiDrawContext.wrap(draw); + public void drawBackground(MatrixStack matrices, int mouseX, int mouseY, float delta) { + super.drawBackground(matrices, mouseX, mouseY, delta); + EmiDrawContext context = EmiDrawContext.wrap(matrices); if (BoM.getRecipe(getIngredient()) instanceof EmiResolutionRecipe err && err.stack.equals(getStack())) { context.drawTexture(EmiRenderHelper.WIDGETS, x, y, 36, 128, 18, 18); } diff --git a/xplat/src/main/java/dev/emi/emi/api/recipe/EmiRecipeCategory.java b/xplat/src/main/java/dev/emi/emi/api/recipe/EmiRecipeCategory.java index 6bedb937..be093866 100644 --- a/xplat/src/main/java/dev/emi/emi/api/recipe/EmiRecipeCategory.java +++ b/xplat/src/main/java/dev/emi/emi/api/recipe/EmiRecipeCategory.java @@ -14,8 +14,8 @@ import dev.emi.emi.api.stack.EmiStack; import dev.emi.emi.config.EmiConfig; import dev.emi.emi.data.EmiRecipeCategoryProperties; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.tooltip.TooltipComponent; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.Text; import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; @@ -63,12 +63,12 @@ public Identifier getId() { } @Override - public void render(DrawContext draw, int x, int y, float delta) { - EmiRecipeCategoryProperties.getIcon(this).render(draw, x, y, delta); + public void render(MatrixStack matrices, int x, int y, float delta) { + EmiRecipeCategoryProperties.getIcon(this).render(matrices, x, y, delta); } - public void renderSimplified(DrawContext draw, int x, int y, float delta) { - EmiRecipeCategoryProperties.getSimplifiedIcon(this).render(draw, x, y, delta); + public void renderSimplified(MatrixStack matrices, int x, int y, float delta) { + EmiRecipeCategoryProperties.getSimplifiedIcon(this).render(matrices, x, y, delta); } public List getTooltip() { diff --git a/xplat/src/main/java/dev/emi/emi/api/recipe/handler/EmiRecipeHandler.java b/xplat/src/main/java/dev/emi/emi/api/recipe/handler/EmiRecipeHandler.java index 9f16146b..0f8628bc 100644 --- a/xplat/src/main/java/dev/emi/emi/api/recipe/handler/EmiRecipeHandler.java +++ b/xplat/src/main/java/dev/emi/emi/api/recipe/handler/EmiRecipeHandler.java @@ -6,9 +6,9 @@ import dev.emi.emi.api.recipe.EmiPlayerInventory; import dev.emi.emi.api.recipe.EmiRecipe; import dev.emi.emi.api.widget.Widget; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.client.gui.tooltip.TooltipComponent; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.screen.ScreenHandler; import net.minecraft.text.Text; @@ -65,6 +65,6 @@ default List getTooltip(EmiRecipe recipe, EmiCraftContext c * Render feedback about the status of the current fill. * Common use is to render an overlay on missing ingredients */ - default void render(EmiRecipe recipe, EmiCraftContext context, List widgets, DrawContext draw) { + default void render(EmiRecipe recipe, EmiCraftContext context, List widgets, MatrixStack matrices) { } } diff --git a/xplat/src/main/java/dev/emi/emi/api/recipe/handler/StandardRecipeHandler.java b/xplat/src/main/java/dev/emi/emi/api/recipe/handler/StandardRecipeHandler.java index aaa68706..3b63d1bc 100644 --- a/xplat/src/main/java/dev/emi/emi/api/recipe/handler/StandardRecipeHandler.java +++ b/xplat/src/main/java/dev/emi/emi/api/recipe/handler/StandardRecipeHandler.java @@ -20,8 +20,8 @@ import dev.emi.emi.registry.EmiRecipeFiller; import dev.emi.emi.runtime.EmiDrawContext; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.ingame.HandledScreen; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.item.ItemStack; import net.minecraft.screen.ScreenHandler; import net.minecraft.screen.slot.Slot; @@ -86,13 +86,13 @@ default boolean craft(EmiRecipe recipe, EmiCraftContext context) { } @Override - default void render(EmiRecipe recipe, EmiCraftContext context, List widgets, DrawContext draw) { - renderMissing(recipe, context.getInventory(), widgets, draw); + default void render(EmiRecipe recipe, EmiCraftContext context, List widgets, MatrixStack matrices) { + renderMissing(recipe, context.getInventory(), widgets, matrices); } @ApiStatus.Internal - public static void renderMissing(EmiRecipe recipe, EmiPlayerInventory inv, List widgets, DrawContext draw) { - EmiDrawContext context = EmiDrawContext.wrap(draw); + public static void renderMissing(EmiRecipe recipe, EmiPlayerInventory inv, List widgets, MatrixStack matrices) { + EmiDrawContext context = EmiDrawContext.wrap(matrices); RenderSystem.enableDepthTest(); Map availableForCrafting = getAvailable(recipe, inv); for (Widget w : widgets) { diff --git a/xplat/src/main/java/dev/emi/emi/api/render/EmiRender.java b/xplat/src/main/java/dev/emi/emi/api/render/EmiRender.java index 3830d4ee..f33899f6 100644 --- a/xplat/src/main/java/dev/emi/emi/api/render/EmiRender.java +++ b/xplat/src/main/java/dev/emi/emi/api/render/EmiRender.java @@ -3,23 +3,23 @@ import dev.emi.emi.EmiRenderHelper; import dev.emi.emi.api.stack.EmiIngredient; import dev.emi.emi.runtime.EmiDrawContext; -import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.util.math.MatrixStack; public class EmiRender { - public static void renderIngredientIcon(EmiIngredient ingredient, DrawContext draw, int x, int y) { - EmiRenderHelper.renderIngredient(ingredient, EmiDrawContext.wrap(draw), x, y); + public static void renderIngredientIcon(EmiIngredient ingredient, MatrixStack matrices, int x, int y) { + EmiRenderHelper.renderIngredient(ingredient, EmiDrawContext.wrap(matrices), x, y); } - public static void renderTagIcon(EmiIngredient ingredient, DrawContext draw, int x, int y) { - EmiRenderHelper.renderTag(ingredient, EmiDrawContext.wrap(draw), x, y); + public static void renderTagIcon(EmiIngredient ingredient, MatrixStack matrices, int x, int y) { + EmiRenderHelper.renderTag(ingredient, EmiDrawContext.wrap(matrices), x, y); } - public static void renderRemainderIcon(EmiIngredient ingredient, DrawContext draw, int x, int y) { - EmiRenderHelper.renderRemainder(ingredient, EmiDrawContext.wrap(draw), x, y); + public static void renderRemainderIcon(EmiIngredient ingredient, MatrixStack matrices, int x, int y) { + EmiRenderHelper.renderRemainder(ingredient, EmiDrawContext.wrap(matrices), x, y); } - public static void renderCatalystIcon(EmiIngredient ingredient, DrawContext draw, int x, int y) { - EmiRenderHelper.renderCatalyst(ingredient, EmiDrawContext.wrap(draw), x, y); + public static void renderCatalystIcon(EmiIngredient ingredient, MatrixStack matrices, int x, int y) { + EmiRenderHelper.renderCatalyst(ingredient, EmiDrawContext.wrap(matrices), x, y); } } diff --git a/xplat/src/main/java/dev/emi/emi/api/render/EmiRenderable.java b/xplat/src/main/java/dev/emi/emi/api/render/EmiRenderable.java index 0577ccca..1bf499f8 100644 --- a/xplat/src/main/java/dev/emi/emi/api/render/EmiRenderable.java +++ b/xplat/src/main/java/dev/emi/emi/api/render/EmiRenderable.java @@ -1,11 +1,11 @@ package dev.emi.emi.api.render; -import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.util.math.MatrixStack; /** * Provides a method to render something at a position */ public interface EmiRenderable { - void render(DrawContext draw, int x, int y, float delta); + void render(MatrixStack matrices, int x, int y, float delta); } diff --git a/xplat/src/main/java/dev/emi/emi/api/render/EmiTexture.java b/xplat/src/main/java/dev/emi/emi/api/render/EmiTexture.java index e0885fd9..76dffe29 100644 --- a/xplat/src/main/java/dev/emi/emi/api/render/EmiTexture.java +++ b/xplat/src/main/java/dev/emi/emi/api/render/EmiTexture.java @@ -2,7 +2,7 @@ import dev.emi.emi.EmiRenderHelper; import dev.emi.emi.runtime.EmiDrawContext; -import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.util.Identifier; public class EmiTexture implements EmiRenderable { @@ -36,8 +36,8 @@ public EmiTexture(Identifier texture, int u, int v, int width, int height, } @Override - public void render(DrawContext draw, int x, int y, float delta) { - EmiDrawContext context = EmiDrawContext.wrap(draw); + public void render(MatrixStack matrices, int x, int y, float delta) { + EmiDrawContext context = EmiDrawContext.wrap(matrices); context.drawTexture(texture, x, y, width, height, u, v, regionWidth, regionHeight, textureWidth, textureHeight); } } diff --git a/xplat/src/main/java/dev/emi/emi/api/render/EmiTooltipComponents.java b/xplat/src/main/java/dev/emi/emi/api/render/EmiTooltipComponents.java index 2302e306..ab2d4da7 100644 --- a/xplat/src/main/java/dev/emi/emi/api/render/EmiTooltipComponents.java +++ b/xplat/src/main/java/dev/emi/emi/api/render/EmiTooltipComponents.java @@ -1,11 +1,8 @@ package dev.emi.emi.api.render; -import java.util.List; - import dev.emi.emi.EmiRenderHelper; import dev.emi.emi.api.recipe.EmiRecipe; import dev.emi.emi.api.stack.EmiIngredient; -import dev.emi.emi.screen.tooltip.IngredientTooltipComponent; import dev.emi.emi.screen.tooltip.RecipeCostTooltipComponent; import dev.emi.emi.screen.tooltip.RecipeTooltipComponent; import dev.emi.emi.screen.tooltip.RemainderTooltipComponent; @@ -36,13 +33,6 @@ public static TooltipComponent getRecipeCostTooltipComponent(EmiRecipe recipe) { return new RecipeCostTooltipComponent(recipe); } - /** - * @return A tooltip component that displays a collection of stacks to represent an ingredient - */ - public static TooltipComponent getIngredientTooltipComponent(List stacks) { - return new IngredientTooltipComponent(stacks); - } - /** * @return A tooltip component that displays the amount of a provided stack. */ diff --git a/xplat/src/main/java/dev/emi/emi/api/stack/EmiIngredient.java b/xplat/src/main/java/dev/emi/emi/api/stack/EmiIngredient.java index e8a4fc5c..036baa66 100644 --- a/xplat/src/main/java/dev/emi/emi/api/stack/EmiIngredient.java +++ b/xplat/src/main/java/dev/emi/emi/api/stack/EmiIngredient.java @@ -5,8 +5,8 @@ import dev.emi.emi.api.render.EmiRenderable; import dev.emi.emi.registry.EmiTags; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.tooltip.TooltipComponent; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.fluid.Fluid; import net.minecraft.item.Item; import net.minecraft.recipe.Ingredient; @@ -44,11 +44,11 @@ default boolean isEmpty() { EmiIngredient setChance(float chance); @Override - default void render(DrawContext draw, int x, int y, float delta) { - render(draw, x, y, delta, -1); + default void render(MatrixStack matrices, int x, int y, float delta) { + render(matrices, x, y, delta, -1); } - void render(DrawContext draw, int x, int y, float delta, int flags); + void render(MatrixStack matrices, int x, int y, float delta, int flags); List getTooltip(); diff --git a/xplat/src/main/java/dev/emi/emi/api/stack/EmptyEmiStack.java b/xplat/src/main/java/dev/emi/emi/api/stack/EmptyEmiStack.java index 57ea9921..4749e583 100644 --- a/xplat/src/main/java/dev/emi/emi/api/stack/EmptyEmiStack.java +++ b/xplat/src/main/java/dev/emi/emi/api/stack/EmptyEmiStack.java @@ -5,8 +5,8 @@ import org.jetbrains.annotations.ApiStatus; import dev.emi.emi.EmiPort; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.tooltip.TooltipComponent; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.nbt.NbtCompound; @@ -76,7 +76,7 @@ public boolean isEqual(EmiStack stack) { } @Override - public void render(DrawContext draw, int x, int y, float delta, int flags) { + public void render(MatrixStack matrices, int x, int y, float delta, int flags) { } @Override diff --git a/xplat/src/main/java/dev/emi/emi/api/stack/FluidEmiStack.java b/xplat/src/main/java/dev/emi/emi/api/stack/FluidEmiStack.java index 98415b05..518e51d2 100644 --- a/xplat/src/main/java/dev/emi/emi/api/stack/FluidEmiStack.java +++ b/xplat/src/main/java/dev/emi/emi/api/stack/FluidEmiStack.java @@ -12,8 +12,8 @@ import dev.emi.emi.api.render.EmiTooltipComponents; import dev.emi.emi.config.EmiConfig; import dev.emi.emi.platform.EmiAgnos; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.tooltip.TooltipComponent; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.fluid.Fluid; import net.minecraft.nbt.NbtCompound; import net.minecraft.text.Text; @@ -69,12 +69,12 @@ public Identifier getId() { } @Override - public void render(DrawContext draw, int x, int y, float delta, int flags) { + public void render(MatrixStack matrices, int x, int y, float delta, int flags) { if ((flags & RENDER_ICON) != 0) { - EmiAgnos.renderFluid(this, draw.getMatrices(), x, y, delta); + EmiAgnos.renderFluid(this, matrices, x, y, delta); } if ((flags & RENDER_REMAINDER) != 0) { - EmiRender.renderRemainderIcon(this, draw, x, y); + EmiRender.renderRemainderIcon(this, matrices, x, y); } } diff --git a/xplat/src/main/java/dev/emi/emi/api/stack/ItemEmiStack.java b/xplat/src/main/java/dev/emi/emi/api/stack/ItemEmiStack.java index 57754b21..1bd385d3 100644 --- a/xplat/src/main/java/dev/emi/emi/api/stack/ItemEmiStack.java +++ b/xplat/src/main/java/dev/emi/emi/api/stack/ItemEmiStack.java @@ -14,7 +14,6 @@ import dev.emi.emi.screen.FakeScreen; import dev.emi.emi.screen.StackBatcher.Batchable; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.tooltip.TooltipComponent; import net.minecraft.client.item.TooltipContext; import net.minecraft.client.render.DiffuseLighting; @@ -24,6 +23,7 @@ import net.minecraft.client.render.item.ItemRenderer; import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.render.model.json.ModelTransformationMode; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NbtCompound; import net.minecraft.text.Text; @@ -82,13 +82,14 @@ public Identifier getId() { } @Override - public void render(DrawContext draw, int x, int y, float delta, int flags) { - EmiDrawContext context = EmiDrawContext.wrap(draw); + public void render(MatrixStack matrices, int x, int y, float delta, int flags) { + EmiDrawContext context = EmiDrawContext.wrap(matrices); ItemStack stack = getItemStack(); if ((flags & RENDER_ICON) != 0) { DiffuseLighting.enableGuiDepthLighting(); - draw.drawItem(stack, x, y); - draw.drawItemInSlot(client.textRenderer, stack, x, y, ""); + ItemRenderer itemRenderer = client.getItemRenderer(); + itemRenderer.renderInGui(context.raw(), stack, x, y); + itemRenderer.renderGuiItemOverlay(context.raw(), client.textRenderer, stack, x, y, ""); } if ((flags & RENDER_AMOUNT) != 0) { String count = ""; @@ -120,8 +121,8 @@ public void setUnbatchable() { } @Override - public void renderForBatch(VertexConsumerProvider vcp, DrawContext draw, int x, int y, int z, float delta) { - EmiDrawContext context = EmiDrawContext.wrap(draw); + public void renderForBatch(VertexConsumerProvider vcp, MatrixStack matrices, int x, int y, int z, float delta) { + EmiDrawContext context = EmiDrawContext.wrap(matrices); ItemStack stack = getItemStack(); ItemRenderer ir = client.getItemRenderer(); BakedModel model = ir.getModel(stack, null, null, 0); @@ -130,7 +131,7 @@ public void renderForBatch(VertexConsumerProvider vcp, DrawContext draw, int x, context.matrices().translate(x, y, 100.0f + z + (model.hasDepth() ? 50 : 0)); context.matrices().translate(8.0, 8.0, 0.0); context.matrices().scale(16.0f, 16.0f, 16.0f); - ir.renderItem(stack, ModelTransformationMode.GUI, false, context.matrices(), vcp, LightmapTextureManager.MAX_LIGHT_COORDINATE, OverlayTexture.DEFAULT_UV, model); + ir.renderItem(stack, ModelTransformationMode.GUI, false, context.raw(), vcp, LightmapTextureManager.MAX_LIGHT_COORDINATE, OverlayTexture.DEFAULT_UV, model); } finally { context.pop(); } diff --git a/xplat/src/main/java/dev/emi/emi/api/stack/ListEmiIngredient.java b/xplat/src/main/java/dev/emi/emi/api/stack/ListEmiIngredient.java index db18949f..e0b6370a 100644 --- a/xplat/src/main/java/dev/emi/emi/api/stack/ListEmiIngredient.java +++ b/xplat/src/main/java/dev/emi/emi/api/stack/ListEmiIngredient.java @@ -8,8 +8,8 @@ import dev.emi.emi.EmiPort; import dev.emi.emi.api.render.EmiRender; import dev.emi.emi.screen.tooltip.IngredientTooltipComponent; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.tooltip.TooltipComponent; +import net.minecraft.client.util.math.MatrixStack; @ApiStatus.Internal public class ListEmiIngredient implements EmiIngredient { @@ -81,17 +81,17 @@ public EmiIngredient setChance(float chance) { } @Override - public void render(DrawContext draw, int x, int y, float delta, int flags) { + public void render(MatrixStack matrices, int x, int y, float delta, int flags) { int item = (int) (System.currentTimeMillis() / 1000 % ingredients.size()); EmiIngredient current = ingredients.get(item); if ((flags & RENDER_ICON) != 0) { - current.render(draw, x, y, delta, -1 ^ RENDER_AMOUNT); + current.render(matrices, x, y, delta, -1 ^ RENDER_AMOUNT); } if ((flags & RENDER_AMOUNT) != 0) { - current.copy().setAmount(amount).render(draw, x, y, delta, RENDER_AMOUNT); + current.copy().setAmount(amount).render(matrices, x, y, delta, RENDER_AMOUNT); } if ((flags & RENDER_INGREDIENT) != 0) { - EmiRender.renderIngredientIcon(this, draw, x, y); + EmiRender.renderIngredientIcon(this, matrices, x, y); } } diff --git a/xplat/src/main/java/dev/emi/emi/api/stack/TagEmiIngredient.java b/xplat/src/main/java/dev/emi/emi/api/stack/TagEmiIngredient.java index 1ad2c686..e211b828 100644 --- a/xplat/src/main/java/dev/emi/emi/api/stack/TagEmiIngredient.java +++ b/xplat/src/main/java/dev/emi/emi/api/stack/TagEmiIngredient.java @@ -19,7 +19,6 @@ import dev.emi.emi.screen.tooltip.RemainderTooltipComponent; import dev.emi.emi.screen.tooltip.TagTooltipComponent; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.tooltip.TooltipComponent; import net.minecraft.client.render.DiffuseLighting; import net.minecraft.client.render.LightmapTextureManager; @@ -114,8 +113,8 @@ public EmiIngredient setChance(float chance) { } @Override - public void render(DrawContext draw, int x, int y, float delta, int flags) { - EmiDrawContext context = EmiDrawContext.wrap(draw); + public void render(MatrixStack matrices, int x, int y, float delta, int flags) { + EmiDrawContext context = EmiDrawContext.wrap(matrices); MinecraftClient client = MinecraftClient.getInstance(); if ((flags & RENDER_ICON) != 0) { diff --git a/xplat/src/main/java/dev/emi/emi/api/widget/AnimatedTextureWidget.java b/xplat/src/main/java/dev/emi/emi/api/widget/AnimatedTextureWidget.java index 48cff205..eaaeab37 100644 --- a/xplat/src/main/java/dev/emi/emi/api/widget/AnimatedTextureWidget.java +++ b/xplat/src/main/java/dev/emi/emi/api/widget/AnimatedTextureWidget.java @@ -1,7 +1,7 @@ package dev.emi.emi.api.widget; import dev.emi.emi.runtime.EmiDrawContext; -import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.util.Identifier; public class AnimatedTextureWidget extends TextureWidget { @@ -23,8 +23,8 @@ public AnimatedTextureWidget(Identifier texture, int x, int y, int width, int he } @Override - public void render(DrawContext draw, int mouseX, int mouseY, float delta) { - EmiDrawContext context = EmiDrawContext.wrap(draw); + public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { + EmiDrawContext context = EmiDrawContext.wrap(matrices); int subTime = (int) (System.currentTimeMillis() % time); if (endToStart ^ fullToEmpty) { subTime = time - subTime; diff --git a/xplat/src/main/java/dev/emi/emi/api/widget/ButtonWidget.java b/xplat/src/main/java/dev/emi/emi/api/widget/ButtonWidget.java index fe479f23..830b8075 100644 --- a/xplat/src/main/java/dev/emi/emi/api/widget/ButtonWidget.java +++ b/xplat/src/main/java/dev/emi/emi/api/widget/ButtonWidget.java @@ -7,8 +7,8 @@ import dev.emi.emi.EmiRenderHelper; import dev.emi.emi.runtime.EmiDrawContext; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.sound.PositionedSoundInstance; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.sound.SoundEvents; import net.minecraft.util.Identifier; @@ -40,8 +40,8 @@ public Bounds getBounds() { } @Override - public void render(DrawContext draw, int mouseX, int mouseY, float delta) { - EmiDrawContext context = EmiDrawContext.wrap(draw); + public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { + EmiDrawContext context = EmiDrawContext.wrap(matrices); int v = this.v; boolean active = this.isActive.getAsBoolean(); if (!active) { diff --git a/xplat/src/main/java/dev/emi/emi/api/widget/DrawableWidget.java b/xplat/src/main/java/dev/emi/emi/api/widget/DrawableWidget.java index 95b85e62..929eb284 100644 --- a/xplat/src/main/java/dev/emi/emi/api/widget/DrawableWidget.java +++ b/xplat/src/main/java/dev/emi/emi/api/widget/DrawableWidget.java @@ -4,8 +4,8 @@ import java.util.function.BiFunction; import dev.emi.emi.runtime.EmiDrawContext; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.tooltip.TooltipComponent; +import net.minecraft.client.util.math.MatrixStack; public class DrawableWidget extends Widget implements WidgetTooltipHolder { protected final DrawableWidgetConsumer consumer; @@ -37,8 +37,8 @@ public List getTooltip(int mouseX, int mouseY) { } @Override - public void render(DrawContext draw, int mouseX, int mouseY, float delta) { - EmiDrawContext context = EmiDrawContext.wrap(draw); + public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { + EmiDrawContext context = EmiDrawContext.wrap(matrices); context.push(); context.matrices().translate(x, y, 0); consumer.render(context.raw(), mouseX, mouseY, delta); @@ -47,6 +47,6 @@ public void render(DrawContext draw, int mouseX, int mouseY, float delta) { public static interface DrawableWidgetConsumer { - void render(DrawContext draw, int mouseX, int mouseY, float delta); + void render(MatrixStack matrices, int mouseX, int mouseY, float delta); } } diff --git a/xplat/src/main/java/dev/emi/emi/api/widget/FillingArrowWidget.java b/xplat/src/main/java/dev/emi/emi/api/widget/FillingArrowWidget.java index e487c899..b5321c42 100644 --- a/xplat/src/main/java/dev/emi/emi/api/widget/FillingArrowWidget.java +++ b/xplat/src/main/java/dev/emi/emi/api/widget/FillingArrowWidget.java @@ -2,7 +2,7 @@ import dev.emi.emi.EmiRenderHelper; import dev.emi.emi.runtime.EmiDrawContext; -import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.util.math.MatrixStack; public class FillingArrowWidget extends AnimatedTextureWidget { @@ -11,8 +11,8 @@ public FillingArrowWidget(int x, int y, int time) { } @Override - public void render(DrawContext draw, int mouseX, int mouseY, float delta) { - EmiDrawContext context = EmiDrawContext.wrap(draw); + public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { + EmiDrawContext context = EmiDrawContext.wrap(matrices); context.drawTexture(this.texture, x, y, width, height, u, 0, regionWidth, regionHeight, textureWidth, textureHeight); super.render(context.raw(), mouseX, mouseY, delta); } diff --git a/xplat/src/main/java/dev/emi/emi/api/widget/GeneratedSlotWidget.java b/xplat/src/main/java/dev/emi/emi/api/widget/GeneratedSlotWidget.java index 29753d5f..9a024a10 100644 --- a/xplat/src/main/java/dev/emi/emi/api/widget/GeneratedSlotWidget.java +++ b/xplat/src/main/java/dev/emi/emi/api/widget/GeneratedSlotWidget.java @@ -7,7 +7,7 @@ import dev.emi.emi.api.stack.EmiIngredient; import dev.emi.emi.api.stack.EmiStack; import dev.emi.emi.runtime.EmiDrawContext; -import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.util.math.MatrixStack; public class GeneratedSlotWidget extends SlotWidget { private static final int INCREMENT = 1000; @@ -23,8 +23,8 @@ public GeneratedSlotWidget(Function stackSupplier, int un } @Override - public void drawOverlay(DrawContext draw, int mouseX, int mouseY, float delta) { - EmiDrawContext context = EmiDrawContext.wrap(draw); + public void drawOverlay(MatrixStack matrices, int mouseX, int mouseY, float delta) { + EmiDrawContext context = EmiDrawContext.wrap(matrices); if (!getStack().isEmpty()) { int off = 1; if (output) { diff --git a/xplat/src/main/java/dev/emi/emi/api/widget/SlotWidget.java b/xplat/src/main/java/dev/emi/emi/api/widget/SlotWidget.java index c159be65..10f2b0a0 100644 --- a/xplat/src/main/java/dev/emi/emi/api/widget/SlotWidget.java +++ b/xplat/src/main/java/dev/emi/emi/api/widget/SlotWidget.java @@ -27,8 +27,8 @@ import dev.emi.emi.screen.RecipeScreen; import dev.emi.emi.screen.tooltip.EmiTooltip; import dev.emi.emi.screen.tooltip.RecipeCostTooltipComponent; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.tooltip.TooltipComponent; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.Text; import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; @@ -154,16 +154,16 @@ public Bounds getBounds() { } @Override - public void render(DrawContext draw, int mouseX, int mouseY, float delta) { + public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { EmiPort.setPositionTexShader(); RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f); - drawBackground(draw, mouseX, mouseY, delta); - drawStack(draw, mouseX, mouseY, delta); - drawOverlay(draw, mouseX, mouseY, delta); + drawBackground(matrices, mouseX, mouseY, delta); + drawStack(matrices, mouseX, mouseY, delta); + drawOverlay(matrices, mouseX, mouseY, delta); } - public void drawBackground(DrawContext draw, int mouseX, int mouseY, float delta) { - EmiDrawContext context = EmiDrawContext.wrap(draw); + public void drawBackground(MatrixStack matrices, int mouseX, int mouseY, float delta) { + EmiDrawContext context = EmiDrawContext.wrap(matrices); Bounds bounds = getBounds(); int width = bounds.width(); int height = bounds.height(); @@ -181,25 +181,25 @@ public void drawBackground(DrawContext draw, int mouseX, int mouseY, float delta } } - public void drawStack(DrawContext draw, int mouseX, int mouseY, float delta) { + public void drawStack(MatrixStack matrices, int mouseX, int mouseY, float delta) { Bounds bounds = getBounds(); int xOff = (bounds.width() - 16) / 2; int yOff = (bounds.height() - 16) / 2; - getStack().render(draw, bounds.x() + xOff, bounds.y() + yOff, delta); + getStack().render(matrices, bounds.x() + xOff, bounds.y() + yOff, delta); } - public void drawOverlay(DrawContext draw, int mouseX, int mouseY, float delta) { + public void drawOverlay(MatrixStack matrices, int mouseX, int mouseY, float delta) { Bounds bounds = getBounds(); int width = bounds.width(); int height = bounds.height(); int xOff = (width - 16) / 2; int yOff = (height - 16) / 2; if (catalyst) { - EmiRender.renderCatalystIcon(getStack(), draw, x + xOff, y + yOff); + EmiRender.renderCatalystIcon(getStack(), matrices, x + xOff, y + yOff); } if (shouldDrawSlotHighlight(mouseX, mouseY)) { - drawSlotHighlight(draw, bounds); + drawSlotHighlight(matrices, bounds); } } @@ -207,9 +207,9 @@ public boolean shouldDrawSlotHighlight(int mouseX, int mouseY) { return getBounds().contains(mouseX, mouseY) && EmiConfig.showHoverOverlay; } - public void drawSlotHighlight(DrawContext draw, Bounds bounds) { + public void drawSlotHighlight(MatrixStack matrices, Bounds bounds) { RenderSystem.disableDepthTest(); - EmiRenderHelper.drawSlotHightlight(EmiDrawContext.wrap(draw), bounds.x() + 1, bounds.y() + 1, bounds.width() - 2, bounds.height() - 2); + EmiRenderHelper.drawSlotHightlight(EmiDrawContext.wrap(matrices), bounds.x() + 1, bounds.y() + 1, bounds.width() - 2, bounds.height() - 2); } @Override diff --git a/xplat/src/main/java/dev/emi/emi/api/widget/TankWidget.java b/xplat/src/main/java/dev/emi/emi/api/widget/TankWidget.java index 6689b8b0..6be4b423 100644 --- a/xplat/src/main/java/dev/emi/emi/api/widget/TankWidget.java +++ b/xplat/src/main/java/dev/emi/emi/api/widget/TankWidget.java @@ -4,7 +4,7 @@ import dev.emi.emi.api.stack.EmiStack; import dev.emi.emi.api.stack.FluidEmiStack; import dev.emi.emi.platform.EmiAgnos; -import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.fluid.Fluid; import net.minecraft.util.Identifier; @@ -31,7 +31,7 @@ public SlotWidget backgroundTexture(Identifier id, int u, int v) { } @Override - public void drawStack(DrawContext draw, int mouseX, int mouseY, float delta) { + public void drawStack(MatrixStack matrices, int mouseX, int mouseY, float delta) { EmiIngredient ingredient = getStack(); for (EmiStack stack : ingredient.getEmiStacks()) { if (stack.getKey() instanceof Fluid fluid) { @@ -49,9 +49,9 @@ public void drawStack(DrawContext draw, int mouseX, int mouseY, float delta) { for (int ox = 0; ox < w; ox += 16) { int rw = Math.min(16, w - ox); if (floaty) { - EmiAgnos.renderFluid(fes, draw.getMatrices(), x + ox, sy + oy, delta, 0, 0, rw, rh); + EmiAgnos.renderFluid(fes, matrices, x + ox, sy + oy, delta, 0, 0, rw, rh); } else { - EmiAgnos.renderFluid(fes, draw.getMatrices(), x + ox, sy + (oy + rh) * -1, delta, 0, 16 - rh, rw, rh); + EmiAgnos.renderFluid(fes, matrices, x + ox, sy + (oy + rh) * -1, delta, 0, 16 - rh, rw, rh); } } } diff --git a/xplat/src/main/java/dev/emi/emi/api/widget/TextWidget.java b/xplat/src/main/java/dev/emi/emi/api/widget/TextWidget.java index 0cad63bb..896595a3 100644 --- a/xplat/src/main/java/dev/emi/emi/api/widget/TextWidget.java +++ b/xplat/src/main/java/dev/emi/emi/api/widget/TextWidget.java @@ -2,7 +2,7 @@ import dev.emi.emi.runtime.EmiDrawContext; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.OrderedText; public class TextWidget extends Widget { @@ -41,8 +41,8 @@ public Bounds getBounds() { } @Override - public void render(DrawContext draw, int mouseX, int mouseY, float delta) { - EmiDrawContext context = EmiDrawContext.wrap(draw); + public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { + EmiDrawContext context = EmiDrawContext.wrap(matrices); context.push(); int xOff = horizontalAlignment.offset(CLIENT.textRenderer.getWidth(text)); int yOff = verticalAlignment.offset(CLIENT.textRenderer.fontHeight); diff --git a/xplat/src/main/java/dev/emi/emi/api/widget/TextureWidget.java b/xplat/src/main/java/dev/emi/emi/api/widget/TextureWidget.java index e3add67f..d68f9cf5 100644 --- a/xplat/src/main/java/dev/emi/emi/api/widget/TextureWidget.java +++ b/xplat/src/main/java/dev/emi/emi/api/widget/TextureWidget.java @@ -4,8 +4,8 @@ import java.util.function.BiFunction; import dev.emi.emi.runtime.EmiDrawContext; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.tooltip.TooltipComponent; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.util.Identifier; public class TextureWidget extends Widget implements WidgetTooltipHolder { @@ -53,8 +53,8 @@ public List getTooltip(int mouseX, int mouseY) { } @Override - public void render(DrawContext draw, int mouseX, int mouseY, float delta) { - EmiDrawContext context = EmiDrawContext.wrap(draw); + public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { + EmiDrawContext context = EmiDrawContext.wrap(matrices); context.resetColor(); context.drawTexture(texture, x, y, width, height, u, v, regionWidth, regionHeight, textureWidth, textureHeight); } diff --git a/xplat/src/main/java/dev/emi/emi/api/widget/TooltipWidget.java b/xplat/src/main/java/dev/emi/emi/api/widget/TooltipWidget.java index 2973b9cc..4b487930 100644 --- a/xplat/src/main/java/dev/emi/emi/api/widget/TooltipWidget.java +++ b/xplat/src/main/java/dev/emi/emi/api/widget/TooltipWidget.java @@ -3,8 +3,8 @@ import java.util.List; import java.util.function.BiFunction; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.tooltip.TooltipComponent; +import net.minecraft.client.util.math.MatrixStack; public class TooltipWidget extends Widget { private final Bounds bounds; @@ -26,6 +26,6 @@ public List getTooltip(int mouseX, int mouseY) { } @Override - public void render(DrawContext draw, int mouseX, int mouseY, float delta) { + public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { } } diff --git a/xplat/src/main/java/dev/emi/emi/api/widget/Widget.java b/xplat/src/main/java/dev/emi/emi/api/widget/Widget.java index b12cddb6..bf686961 100644 --- a/xplat/src/main/java/dev/emi/emi/api/widget/Widget.java +++ b/xplat/src/main/java/dev/emi/emi/api/widget/Widget.java @@ -2,15 +2,15 @@ import java.util.List; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.Drawable; import net.minecraft.client.gui.tooltip.TooltipComponent; +import net.minecraft.client.util.math.MatrixStack; public abstract class Widget implements Drawable { public abstract Bounds getBounds(); - public abstract void render(DrawContext draw, int mouseX, int mouseY, float delta); + public abstract void render(MatrixStack matrices, int mouseX, int mouseY, float delta); public List getTooltip(int mouseX, int mouseY) { return List.of(); diff --git a/xplat/src/main/java/dev/emi/emi/chess/ChessEmiStack.java b/xplat/src/main/java/dev/emi/emi/chess/ChessEmiStack.java index 742438ff..ef319471 100644 --- a/xplat/src/main/java/dev/emi/emi/chess/ChessEmiStack.java +++ b/xplat/src/main/java/dev/emi/emi/chess/ChessEmiStack.java @@ -12,8 +12,8 @@ import dev.emi.emi.runtime.EmiDrawContext; import dev.emi.emi.screen.EmiScreenManager; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.tooltip.TooltipComponent; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.nbt.NbtCompound; import net.minecraft.text.Text; @@ -27,7 +27,7 @@ public ChessEmiStack(int position) { } @Override - public void render(DrawContext raw, int x, int y, float delta, int flags) { + public void render(MatrixStack raw, int x, int y, float delta, int flags) { EmiDrawContext context = EmiDrawContext.wrap(raw); ChessPiece piece = EmiChess.getBoard().get(position); RenderSystem.enableDepthTest(); diff --git a/xplat/src/main/java/dev/emi/emi/handler/CoercedRecipeHandler.java b/xplat/src/main/java/dev/emi/emi/handler/CoercedRecipeHandler.java index 8e34c349..292ee779 100644 --- a/xplat/src/main/java/dev/emi/emi/handler/CoercedRecipeHandler.java +++ b/xplat/src/main/java/dev/emi/emi/handler/CoercedRecipeHandler.java @@ -10,14 +10,14 @@ import dev.emi.emi.api.recipe.handler.StandardRecipeHandler; import dev.emi.emi.mixin.accessor.CraftingResultSlotAccessor; import net.minecraft.client.MinecraftClient; -import net.minecraft.inventory.RecipeInputInventory; +import net.minecraft.inventory.CraftingInventory; import net.minecraft.screen.ScreenHandler; import net.minecraft.screen.slot.CraftingResultSlot; import net.minecraft.screen.slot.Slot; public class CoercedRecipeHandler implements StandardRecipeHandler { private CraftingResultSlot output; - private RecipeInputInventory inv; + private CraftingInventory inv; public CoercedRecipeHandler(CraftingResultSlot output) { this.output = output; diff --git a/xplat/src/main/java/dev/emi/emi/jemi/JemiRecipeHandler.java b/xplat/src/main/java/dev/emi/emi/jemi/JemiRecipeHandler.java index 5d2f4798..ef4c216b 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/JemiRecipeHandler.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/JemiRecipeHandler.java @@ -21,8 +21,8 @@ import mezz.jei.api.recipe.transfer.IRecipeTransferError; import mezz.jei.api.recipe.transfer.IRecipeTransferHandler; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.ingame.HandledScreen; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.recipe.Recipe; import net.minecraft.recipe.RecipeManager; import net.minecraft.screen.ScreenHandler; @@ -75,7 +75,7 @@ public boolean craft(EmiRecipe recipe, EmiCraftContext context) { } @Override - public void render(EmiRecipe recipe, EmiCraftContext context, List widgets, DrawContext raw) { + public void render(EmiRecipe recipe, EmiCraftContext context, List widgets, MatrixStack raw) { /*IRecipeTransferError err = jeiCraft(recipe, context, false); if (err != null) { R rawRecipe = getRawRecipe(recipe); diff --git a/xplat/src/main/java/dev/emi/emi/jemi/JemiStack.java b/xplat/src/main/java/dev/emi/emi/jemi/JemiStack.java index 63d4abcb..824c6626 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/JemiStack.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/JemiStack.java @@ -15,9 +15,9 @@ import mezz.jei.api.ingredients.IIngredientTypeWithSubtypes; import mezz.jei.api.ingredients.subtypes.UidContext; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.tooltip.TooltipComponent; import net.minecraft.client.item.TooltipContext; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.nbt.NbtCompound; import net.minecraft.text.Text; import net.minecraft.util.Formatting; @@ -43,7 +43,7 @@ public JemiStack(IIngredientType type, IIngredientHelper helper, IIngredie } @Override - public void render(DrawContext raw, int x, int y, float delta, int flags) { + public void render(MatrixStack raw, int x, int y, float delta, int flags) { EmiDrawContext context = EmiDrawContext.wrap(raw); int xOff = (16 - renderer.getWidth()) / 2; int yOff = (16 - renderer.getHeight()) / 2; diff --git a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlot.java b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlot.java index 6c6f279e..61148881 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlot.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlot.java @@ -15,7 +15,7 @@ import mezz.jei.api.ingredients.IIngredientType; import mezz.jei.api.ingredients.ITypedIngredient; import mezz.jei.api.recipe.RecipeIngredientRole; -import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.util.math.MatrixStack; @SuppressWarnings("unchecked") public class JemiRecipeSlot implements IRecipeSlotView { @@ -95,7 +95,7 @@ public RecipeIngredientRole getRole() { } @Override - public void drawHighlight(DrawContext raw, int color) { + public void drawHighlight(MatrixStack raw, int color) { } public static record OffsetDrawable(IDrawable drawable, int xOff, int yOff){ diff --git a/xplat/src/main/java/dev/emi/emi/jemi/runtime/JemiDragDropHandler.java b/xplat/src/main/java/dev/emi/emi/jemi/runtime/JemiDragDropHandler.java index f974d6e1..f7b68131 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/runtime/JemiDragDropHandler.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/runtime/JemiDragDropHandler.java @@ -10,8 +10,8 @@ import dev.emi.emi.runtime.EmiDrawContext; import mezz.jei.api.gui.handlers.IGhostIngredientHandler; import mezz.jei.api.ingredients.ITypedIngredient; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.Rect2i; public class JemiDragDropHandler implements EmiDragDropHandler { @@ -28,7 +28,7 @@ public boolean dropStack(Screen screen, EmiIngredient stack, int x, int y) { @Override @SuppressWarnings({"rawtypes", "unchecked"}) - public void render(Screen screen, EmiIngredient dragged, DrawContext raw, int mouseX, int mouseY, float delta) { + public void render(Screen screen, EmiIngredient dragged, MatrixStack raw, int mouseX, int mouseY, float delta) { try { this.render(screen, EmiDrawContext.wrap(raw), (Optional>) (Optional) JemiUtil.getTyped(dragged.getEmiStacks().get(0))); } catch (Exception e) { diff --git a/xplat/src/main/java/dev/emi/emi/jemi/widget/JemiSlotWidget.java b/xplat/src/main/java/dev/emi/emi/jemi/widget/JemiSlotWidget.java index 4afd516d..39105018 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/widget/JemiSlotWidget.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/widget/JemiSlotWidget.java @@ -20,8 +20,8 @@ import mezz.jei.api.ingredients.IIngredientRenderer; import mezz.jei.api.ingredients.ITypedIngredient; import mezz.jei.api.recipe.RecipeIngredientRole; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.tooltip.TooltipComponent; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.Text; public class JemiSlotWidget extends SlotWidget { @@ -62,7 +62,7 @@ private IIngredientRenderer getRenderer() { } @Override - public void render(DrawContext raw, int mouseX, int mouseY, float delta) { + public void render(MatrixStack raw, int mouseX, int mouseY, float delta) { if (slot.background != null) { slot.background.drawable().draw(raw, x + 1 + slot.background.xOff(), y + 1 + slot.background.yOff()); } @@ -71,7 +71,7 @@ public void render(DrawContext raw, int mouseX, int mouseY, float delta) { @Override @SuppressWarnings({"rawtypes", "unchecked"}) - public void drawStack(DrawContext raw, int mouseX, int mouseY, float delta) { + public void drawStack(MatrixStack raw, int mouseX, int mouseY, float delta) { EmiDrawContext context = EmiDrawContext.wrap(raw); IIngredientRenderer renderer = getRenderer(); if (renderer != null) { @@ -90,7 +90,7 @@ public void drawStack(DrawContext raw, int mouseX, int mouseY, float delta) { } @Override - public void drawOverlay(DrawContext raw, int mouseX, int mouseY, float delta) { + public void drawOverlay(MatrixStack raw, int mouseX, int mouseY, float delta) { EmiDrawContext context = EmiDrawContext.wrap(raw); if (slot.overlay != null) { RenderSystem.enableBlend(); diff --git a/xplat/src/main/java/dev/emi/emi/jemi/widget/JemiTankWidget.java b/xplat/src/main/java/dev/emi/emi/jemi/widget/JemiTankWidget.java index 81b0f99a..4ff5ded9 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/widget/JemiTankWidget.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/widget/JemiTankWidget.java @@ -9,8 +9,8 @@ import dev.emi.emi.jemi.impl.JemiRecipeSlot; import dev.emi.emi.runtime.EmiDrawContext; import mezz.jei.api.recipe.RecipeIngredientRole; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.tooltip.TooltipComponent; +import net.minecraft.client.util.math.MatrixStack; public class JemiTankWidget extends TankWidget { private final JemiRecipeSlot slot; @@ -28,7 +28,7 @@ public JemiTankWidget(JemiRecipeSlot slot, EmiRecipe recipe) { } @Override - public void render(DrawContext raw, int mouseX, int mouseY, float delta) { + public void render(MatrixStack raw, int mouseX, int mouseY, float delta) { EmiDrawContext context = EmiDrawContext.wrap(raw); if (slot.background != null) { slot.background.drawable().draw(context.raw(), x + 1 + slot.background.xOff(), y + 1 + slot.background.yOff()); @@ -37,7 +37,7 @@ public void render(DrawContext raw, int mouseX, int mouseY, float delta) { } @Override - public void drawOverlay(DrawContext raw, int mouseX, int mouseY, float delta) { + public void drawOverlay(MatrixStack raw, int mouseX, int mouseY, float delta) { EmiDrawContext context = EmiDrawContext.wrap(raw); if (slot.overlay != null) { RenderSystem.enableBlend(); diff --git a/xplat/src/main/java/dev/emi/emi/mixin/AbstractInventoryScreenMixin.java b/xplat/src/main/java/dev/emi/emi/mixin/AbstractInventoryScreenMixin.java index f9f7452e..560e051b 100644 --- a/xplat/src/main/java/dev/emi/emi/mixin/AbstractInventoryScreenMixin.java +++ b/xplat/src/main/java/dev/emi/emi/mixin/AbstractInventoryScreenMixin.java @@ -18,10 +18,10 @@ import dev.emi.emi.config.EffectLocation; import dev.emi.emi.config.EmiConfig; import dev.emi.emi.platform.EmiAgnos; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.ingame.AbstractInventoryScreen; import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen; import net.minecraft.client.gui.screen.ingame.HandledScreen; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.effect.StatusEffectInstance; import net.minecraft.entity.effect.StatusEffectUtil; import net.minecraft.screen.ScreenHandler; @@ -40,26 +40,26 @@ private Text getStatusEffectDescription(StatusEffectInstance effect) { } @Shadow - private void drawStatusEffectBackgrounds(DrawContext draw, int x, int height, Iterable statusEffects, boolean wide) { + private void drawStatusEffectBackgrounds(MatrixStack matrices, int x, int height, Iterable statusEffects, boolean wide) { throw new UnsupportedOperationException(); } @Shadow - private void drawStatusEffectSprites(DrawContext draw, int x, int height, Iterable statusEffects, boolean wide) { + private void drawStatusEffectSprites(MatrixStack matrices, int x, int height, Iterable statusEffects, boolean wide) { throw new UnsupportedOperationException(); } @Shadow - private void drawStatusEffectDescriptions(DrawContext draw, int x, int height, Iterable statusEffects) { + private void drawStatusEffectDescriptions(MatrixStack matrices, int x, int height, Iterable statusEffects) { throw new UnsupportedOperationException(); } @Inject(at = @At(value = "INVOKE", - target = "net/minecraft/client/gui/screen/ingame/AbstractInventoryScreen.drawStatusEffectBackgrounds(Lnet/minecraft/client/gui/DrawContext;IILjava/lang/Iterable;Z)V"), + target = "net/minecraft/client/gui/screen/ingame/AbstractInventoryScreen.drawStatusEffectBackgrounds(Lnet/minecraft/client/util/math/MatrixStack;IILjava/lang/Iterable;Z)V"), method = "drawStatusEffects") - private void drawStatusEffects(DrawContext draw, int mouseX, int mouseY, CallbackInfo info) { + private void drawStatusEffects(MatrixStack matrices, int mouseX, int mouseY, CallbackInfo info) { if (EmiConfig.effectLocation == EffectLocation.TOP) { - emi$drawCenteredEffects(draw, mouseX, mouseY); + emi$drawCenteredEffects(matrices, mouseX, mouseY); } } @@ -72,7 +72,7 @@ private Collection drawStatusEffects(Collection effects = Ordering.natural().sortedCopy(this.client.player.getStatusEffects()); int size = effects.size(); @@ -102,10 +102,10 @@ private Collection drawStatusEffects(Collection single = List.of(inst); - this.drawStatusEffectBackgrounds(draw, x, 32, single, wide); - this.drawStatusEffectSprites(draw, x, 32, single, wide); + this.drawStatusEffectBackgrounds(matrices, x, 32, single, wide); + this.drawStatusEffectSprites(matrices, x, 32, single, wide); if (wide) { - this.drawStatusEffectDescriptions(draw, x, 32, single); + this.drawStatusEffectDescriptions(matrices, x, 32, single); } if (mouseX >= x && mouseX < x + ew && mouseY >= y && mouseY < y + 32) { hovered = inst; @@ -116,8 +116,8 @@ private Collection drawStatusEffects(Collection 1) { - List list = List.of(this.getStatusEffectDescription(hovered), StatusEffectUtil.getDurationText(hovered, 1.0f)); - draw.drawTooltip(client.textRenderer, list, Optional.empty(), mouseX, Math.max(mouseY, 16)); + List list = List.of(this.getStatusEffectDescription(hovered), StatusEffectUtil.durationToString(hovered, 1.0f)); + this.renderTooltip(matrices, list, Optional.empty(), mouseX, Math.max(mouseY, 16)); } } diff --git a/xplat/src/main/java/dev/emi/emi/mixin/CraftingResultSlotMixin.java b/xplat/src/main/java/dev/emi/emi/mixin/CraftingResultSlotMixin.java index 93426f34..3571bf19 100644 --- a/xplat/src/main/java/dev/emi/emi/mixin/CraftingResultSlotMixin.java +++ b/xplat/src/main/java/dev/emi/emi/mixin/CraftingResultSlotMixin.java @@ -13,25 +13,23 @@ import dev.emi.emi.api.recipe.EmiRecipe; import dev.emi.emi.runtime.EmiSidebars; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.inventory.RecipeInputInventory; +import net.minecraft.inventory.CraftingInventory; import net.minecraft.item.ItemStack; import net.minecraft.recipe.CraftingRecipe; import net.minecraft.recipe.RecipeType; import net.minecraft.screen.slot.CraftingResultSlot; -import net.minecraft.world.World; @Mixin(CraftingResultSlot.class) public class CraftingResultSlotMixin { @Shadow @Final - private RecipeInputInventory input; + private CraftingInventory input; @Shadow @Final private PlayerEntity player; @Inject(at = @At("HEAD"), method = "onCrafted(Lnet/minecraft/item/ItemStack;)V") private void onCrafted(ItemStack stack, CallbackInfo info) { - World world = player.getWorld(); - if (world.isClient) { - Optional opt = world.getRecipeManager().getFirstMatch(RecipeType.CRAFTING, input, world); + if (player.world.isClient) { + Optional opt = player.world.getRecipeManager().getFirstMatch(RecipeType.CRAFTING, input, player.world); if (opt.isPresent()) { EmiRecipe recipe = EmiApi.getRecipeManager().getRecipe(opt.get().getId()); if (recipe != null) { diff --git a/xplat/src/main/java/dev/emi/emi/mixin/DrawContextMixin.java b/xplat/src/main/java/dev/emi/emi/mixin/DrawContextMixin.java deleted file mode 100644 index cc776283..00000000 --- a/xplat/src/main/java/dev/emi/emi/mixin/DrawContextMixin.java +++ /dev/null @@ -1,20 +0,0 @@ -package dev.emi.emi.mixin; - -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 dev.emi.emi.screen.EmiScreenManager; -import net.minecraft.client.font.TextRenderer; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.item.ItemStack; - -@Mixin(DrawContext.class) -public class DrawContextMixin { - - @Inject(at = @At("HEAD"), method = "drawItemTooltip(Lnet/minecraft/client/font/TextRenderer;Lnet/minecraft/item/ItemStack;II)V") - private void drawItemTooltip(TextRenderer text, ItemStack stack, int x, int y, CallbackInfo info) { - EmiScreenManager.lastStackTooltipRendered = stack; - } -} diff --git a/xplat/src/main/java/dev/emi/emi/mixin/HandledScreenMixin.java b/xplat/src/main/java/dev/emi/emi/mixin/HandledScreenMixin.java index 9418c012..e095d3ef 100644 --- a/xplat/src/main/java/dev/emi/emi/mixin/HandledScreenMixin.java +++ b/xplat/src/main/java/dev/emi/emi/mixin/HandledScreenMixin.java @@ -16,11 +16,11 @@ import dev.emi.emi.screen.EmiScreenManager; import dev.emi.emi.search.EmiSearch; import dev.emi.emi.search.EmiSearch.CompiledQuery; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.client.gui.screen.recipebook.RecipeBookProvider; import net.minecraft.client.util.Window; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.screen.slot.Slot; @Mixin(HandledScreen.class) @@ -36,13 +36,13 @@ private void init(CallbackInfo info) { } @Intrinsic @Override - public void renderBackground(DrawContext raw) { + public void renderBackground(MatrixStack raw) { super.renderBackground(raw); } @Dynamic - @Inject(at = @At("RETURN"), method = "renderBackground(Lnet/minecraft/client/gui/DrawContext;)V") - private void renderBackground(DrawContext raw, CallbackInfo info) { + @Inject(at = @At("RETURN"), method = "renderBackground(Lnet/minecraft/client/util/math/MatrixStack;)V") + private void renderBackground(MatrixStack raw, CallbackInfo info) { EmiDrawContext context = EmiDrawContext.wrap(raw); Window window = client.getWindow(); int mouseX = (int) (client.mouse.getX() * window.getScaledWidth() / window.getWidth()); @@ -51,10 +51,10 @@ private void renderBackground(DrawContext raw, CallbackInfo info) { } @Inject(at = @At(value = "INVOKE", - target = "net/minecraft/client/gui/screen/ingame/HandledScreen.drawForeground(Lnet/minecraft/client/gui/DrawContext;II)V", + target = "net/minecraft/client/gui/screen/ingame/HandledScreen.drawForeground(Lnet/minecraft/client/util/math/MatrixStack;II)V", shift = Shift.BEFORE), method = "render") - private void render(DrawContext raw, int mouseX, int mouseY, float delta, CallbackInfo info) { + private void render(MatrixStack raw, int mouseX, int mouseY, float delta, CallbackInfo info) { EmiDrawContext context = EmiDrawContext.wrap(raw); context.push(); context.matrices().translate(-x, -y, 0.0); @@ -64,10 +64,10 @@ private void render(DrawContext raw, int mouseX, int mouseY, float delta, Callba } @Inject(at = @At(value = "INVOKE", - target = "net/minecraft/client/gui/screen/ingame/HandledScreen.drawForeground(Lnet/minecraft/client/gui/DrawContext;II)V", + target = "net/minecraft/client/gui/screen/ingame/HandledScreen.drawForeground(Lnet/minecraft/client/util/math/MatrixStack;II)V", shift = Shift.AFTER), method = "render") - private void renderForeground(DrawContext raw, int mouseX, int mouseY, float delta, CallbackInfo info) { + private void renderForeground(MatrixStack raw, int mouseX, int mouseY, float delta, CallbackInfo info) { EmiDrawContext context = EmiDrawContext.wrap(raw); context.push(); context.matrices().translate(-x, -y, 0.0); @@ -76,7 +76,7 @@ private void renderForeground(DrawContext raw, int mouseX, int mouseY, float del } @Inject(at = @At("TAIL"), method = "drawSlot") - private void drawSlot(DrawContext raw, Slot slot, CallbackInfo info) { + private void drawSlot(MatrixStack raw, Slot slot, CallbackInfo info) { EmiDrawContext context = EmiDrawContext.wrap(raw); if (EmiScreenManager.search.highlight) { CompiledQuery query = EmiSearch.compiledQuery; diff --git a/xplat/src/main/java/dev/emi/emi/mixin/ScreenMixin.java b/xplat/src/main/java/dev/emi/emi/mixin/ScreenMixin.java new file mode 100644 index 00000000..e1c2c696 --- /dev/null +++ b/xplat/src/main/java/dev/emi/emi/mixin/ScreenMixin.java @@ -0,0 +1,20 @@ +package dev.emi.emi.mixin; + +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 dev.emi.emi.screen.EmiScreenManager; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.item.ItemStack; + +@Mixin(Screen.class) +public class ScreenMixin { + + @Inject(at = @At("HEAD"), method = "renderTooltip(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/item/ItemStack;II)V") + private void renderTooltip(MatrixStack matrices, ItemStack stack, int x, int y, CallbackInfo info) { + EmiScreenManager.lastStackTooltipRendered = stack; + } +} diff --git a/xplat/src/main/java/dev/emi/emi/mixin/ToastManagerMixin.java b/xplat/src/main/java/dev/emi/emi/mixin/ToastManagerMixin.java index e2730b47..e43e4159 100644 --- a/xplat/src/main/java/dev/emi/emi/mixin/ToastManagerMixin.java +++ b/xplat/src/main/java/dev/emi/emi/mixin/ToastManagerMixin.java @@ -8,14 +8,14 @@ import dev.emi.emi.api.EmiApi; import dev.emi.emi.config.EmiConfig; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.toast.ToastManager; +import net.minecraft.client.util.math.MatrixStack; @Mixin(ToastManager.class) public class ToastManagerMixin { @Inject(at = @At("HEAD"), method = "draw", cancellable = true) - private void drawHead(DrawContext raw, CallbackInfo info) { + private void drawHead(MatrixStack raw, CallbackInfo info) { MinecraftClient client = MinecraftClient.getInstance(); if (client.currentScreen != null && EmiConfig.enabled && EmiApi.getHandledScreen() != null) { info.cancel(); diff --git a/xplat/src/main/java/dev/emi/emi/mixin/accessor/CraftingResultSlotAccessor.java b/xplat/src/main/java/dev/emi/emi/mixin/accessor/CraftingResultSlotAccessor.java index 1e1c834b..c897d850 100644 --- a/xplat/src/main/java/dev/emi/emi/mixin/accessor/CraftingResultSlotAccessor.java +++ b/xplat/src/main/java/dev/emi/emi/mixin/accessor/CraftingResultSlotAccessor.java @@ -3,12 +3,12 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; -import net.minecraft.inventory.RecipeInputInventory; +import net.minecraft.inventory.CraftingInventory; import net.minecraft.screen.slot.CraftingResultSlot; @Mixin(CraftingResultSlot.class) public interface CraftingResultSlotAccessor { @Accessor("input") - RecipeInputInventory getInput(); + CraftingInventory getInput(); } diff --git a/xplat/src/main/java/dev/emi/emi/mixin/accessor/DrawContextAccessor.java b/xplat/src/main/java/dev/emi/emi/mixin/accessor/DrawContextAccessor.java deleted file mode 100644 index 3c2c66ed..00000000 --- a/xplat/src/main/java/dev/emi/emi/mixin/accessor/DrawContextAccessor.java +++ /dev/null @@ -1,18 +0,0 @@ -package dev.emi.emi.mixin.accessor; - -import java.util.List; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Invoker; - -import net.minecraft.client.font.TextRenderer; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.tooltip.TooltipComponent; -import net.minecraft.client.gui.tooltip.TooltipPositioner; - -@Mixin(DrawContext.class) -public interface DrawContextAccessor { - - @Invoker("drawTooltip") - void invokeDrawTooltip(TextRenderer textRenderer, List components, int x, int y, TooltipPositioner positioner); -} diff --git a/xplat/src/main/java/dev/emi/emi/mixin/accessor/SmithingTrimRecipeAccessor.java b/xplat/src/main/java/dev/emi/emi/mixin/accessor/LegacySmithingRecipeAccessor.java similarity index 59% rename from xplat/src/main/java/dev/emi/emi/mixin/accessor/SmithingTrimRecipeAccessor.java rename to xplat/src/main/java/dev/emi/emi/mixin/accessor/LegacySmithingRecipeAccessor.java index abb0ae3c..65970c70 100644 --- a/xplat/src/main/java/dev/emi/emi/mixin/accessor/SmithingTrimRecipeAccessor.java +++ b/xplat/src/main/java/dev/emi/emi/mixin/accessor/LegacySmithingRecipeAccessor.java @@ -4,14 +4,11 @@ import org.spongepowered.asm.mixin.gen.Accessor; import net.minecraft.recipe.Ingredient; -import net.minecraft.recipe.SmithingTrimRecipe; - -@Mixin(SmithingTrimRecipe.class) -public interface SmithingTrimRecipeAccessor { - - @Accessor("template") - Ingredient getTemplate(); +import net.minecraft.recipe.LegacySmithingRecipe; +@Mixin(LegacySmithingRecipe.class) +public interface LegacySmithingRecipeAccessor { + @Accessor("base") Ingredient getBase(); diff --git a/xplat/src/main/java/dev/emi/emi/mixin/accessor/ScreenAccessor.java b/xplat/src/main/java/dev/emi/emi/mixin/accessor/ScreenAccessor.java new file mode 100644 index 00000000..5cdddd4f --- /dev/null +++ b/xplat/src/main/java/dev/emi/emi/mixin/accessor/ScreenAccessor.java @@ -0,0 +1,24 @@ +package dev.emi.emi.mixin.accessor; + +import java.util.List; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.tooltip.TooltipComponent; +import net.minecraft.client.gui.tooltip.TooltipPositioner; +import net.minecraft.client.util.math.MatrixStack; + +@Mixin(Screen.class) +public interface ScreenAccessor { + + @Invoker("renderTooltipFromComponents") + void invokeRenderTooltipFromComponents(MatrixStack matrices, List components, int x, int y, TooltipPositioner positioner); + + /* + @Invoker("method_32635") + static void emi$addTooltipComponent(List components, TooltipData data) { + throw new AbstractMethodError(); + }*/ +} diff --git a/xplat/src/main/java/dev/emi/emi/mixin/accessor/SmithingTransformRecipeAccessor.java b/xplat/src/main/java/dev/emi/emi/mixin/accessor/SmithingTransformRecipeAccessor.java deleted file mode 100644 index ce8b6e5b..00000000 --- a/xplat/src/main/java/dev/emi/emi/mixin/accessor/SmithingTransformRecipeAccessor.java +++ /dev/null @@ -1,20 +0,0 @@ -package dev.emi.emi.mixin.accessor; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -import net.minecraft.recipe.Ingredient; -import net.minecraft.recipe.SmithingTransformRecipe; - -@Mixin(SmithingTransformRecipe.class) -public interface SmithingTransformRecipeAccessor { - - @Accessor("template") - Ingredient getTemplate(); - - @Accessor("base") - Ingredient getBase(); - - @Accessor("addition") - Ingredient getAddition(); -} diff --git a/xplat/src/main/java/dev/emi/emi/recipe/EmiSmithingRecipe.java b/xplat/src/main/java/dev/emi/emi/recipe/EmiSmithingRecipe.java index e41fec08..39f3f55e 100644 --- a/xplat/src/main/java/dev/emi/emi/recipe/EmiSmithingRecipe.java +++ b/xplat/src/main/java/dev/emi/emi/recipe/EmiSmithingRecipe.java @@ -2,6 +2,7 @@ import java.util.List; +import dev.emi.emi.EmiPort; import dev.emi.emi.api.recipe.EmiRecipe; import dev.emi.emi.api.recipe.EmiRecipeCategory; import dev.emi.emi.api.recipe.VanillaEmiRecipeCategories; @@ -9,21 +10,21 @@ import dev.emi.emi.api.stack.EmiIngredient; import dev.emi.emi.api.stack.EmiStack; import dev.emi.emi.api.widget.WidgetHolder; +import dev.emi.emi.mixin.accessor.LegacySmithingRecipeAccessor; +import net.minecraft.recipe.SmithingRecipe; import net.minecraft.util.Identifier; public class EmiSmithingRecipe implements EmiRecipe { - protected final Identifier id; - protected final EmiIngredient template; - protected final EmiIngredient input; - protected final EmiIngredient addition; - protected final EmiStack output; + private final Identifier id; + private final EmiIngredient input; + private final EmiIngredient addition; + private final EmiStack output; - public EmiSmithingRecipe(EmiIngredient template, EmiIngredient input, EmiIngredient addition, EmiStack output, Identifier id) { - this.id = id; - this.template = template; - this.input = input; - this.addition = addition; - this.output = output; + public EmiSmithingRecipe(SmithingRecipe recipe) { + this.id = recipe.getId(); + input = EmiIngredient.of(((LegacySmithingRecipeAccessor) recipe).getBase()); + addition = EmiIngredient.of(((LegacySmithingRecipeAccessor) recipe).getAddition()); + output = EmiStack.of(EmiPort.getOutput(recipe)); } @Override @@ -38,7 +39,7 @@ public Identifier getId() { @Override public List getInputs() { - return List.of(template, input, addition); + return List.of(input, addition); } @Override @@ -48,7 +49,7 @@ public List getOutputs() { @Override public int getDisplayWidth() { - return 112; + return 125; } @Override @@ -58,10 +59,10 @@ public int getDisplayHeight() { @Override public void addWidgets(WidgetHolder widgets) { - widgets.addTexture(EmiTexture.EMPTY_ARROW, 62, 1); - widgets.addSlot(template, 0, 0); - widgets.addSlot(input, 18, 0); - widgets.addSlot(addition, 36, 0); - widgets.addSlot(output, 94, 0).recipeContext(this); + widgets.addTexture(EmiTexture.PLUS, 27, 3); + widgets.addTexture(EmiTexture.EMPTY_ARROW, 75, 1); + widgets.addSlot(input, 0, 0); + widgets.addSlot(addition, 49, 0); + widgets.addSlot(output, 107, 0).recipeContext(this); } } diff --git a/xplat/src/main/java/dev/emi/emi/recipe/special/EmiSmithingTrimRecipe.java b/xplat/src/main/java/dev/emi/emi/recipe/special/EmiSmithingTrimRecipe.java deleted file mode 100644 index d0b0b9bb..00000000 --- a/xplat/src/main/java/dev/emi/emi/recipe/special/EmiSmithingTrimRecipe.java +++ /dev/null @@ -1,52 +0,0 @@ -package dev.emi.emi.recipe.special; - -import java.util.Random; - -import dev.emi.emi.EmiUtil; -import dev.emi.emi.api.render.EmiTexture; -import dev.emi.emi.api.render.EmiTooltipComponents; -import dev.emi.emi.api.stack.EmiIngredient; -import dev.emi.emi.api.stack.EmiStack; -import dev.emi.emi.api.widget.WidgetHolder; -import dev.emi.emi.recipe.EmiSmithingRecipe; -import net.minecraft.client.MinecraftClient; -import net.minecraft.inventory.Inventory; -import net.minecraft.inventory.SimpleInventory; -import net.minecraft.item.ItemStack; -import net.minecraft.recipe.SmithingRecipe; - -public class EmiSmithingTrimRecipe extends EmiSmithingRecipe { - private final SmithingRecipe recipe; - private final int uniq = EmiUtil.RANDOM.nextInt(); - - public EmiSmithingTrimRecipe(EmiIngredient template, EmiIngredient input, EmiIngredient addition, EmiStack output, SmithingRecipe recipe) { - super(template, input, addition, output, recipe.getId()); - this.recipe = recipe; - } - - @Override - public boolean supportsRecipeTree() { - return false; - } - - @Override - public void addWidgets(WidgetHolder widgets) { - widgets.addTexture(EmiTexture.EMPTY_ARROW, 62, 1); - widgets.addSlot(template, 0, 0); - widgets.addGeneratedSlot(r -> getStack(r, 0), uniq, 18, 0).appendTooltip(() -> EmiTooltipComponents.getIngredientTooltipComponent(input.getEmiStacks())); - widgets.addGeneratedSlot(r -> getStack(r, 1), uniq, 36, 0).appendTooltip(() -> EmiTooltipComponents.getIngredientTooltipComponent(addition.getEmiStacks())); - widgets.addGeneratedSlot(r -> getStack(r, 2), uniq, 94, 0).recipeContext(this); - } - - private EmiStack getStack(Random r, int i) { - EmiStack input = this.input.getEmiStacks().get(r.nextInt(this.input.getEmiStacks().size())); - EmiStack addition = this.addition.getEmiStacks().get(r.nextInt(this.addition.getEmiStacks().size())); - Inventory inv = new SimpleInventory(template.getEmiStacks().get(0).getItemStack(), input.getItemStack(), addition.getItemStack(), ItemStack.EMPTY); - MinecraftClient client = MinecraftClient.getInstance(); - return new EmiStack[] { - input, - addition, - EmiStack.of(recipe.craft(inv, client.world.getRegistryManager())) - }[i]; - } -} diff --git a/xplat/src/main/java/dev/emi/emi/registry/EmiDragDropHandlers.java b/xplat/src/main/java/dev/emi/emi/registry/EmiDragDropHandlers.java index 926eb5a7..48daddcc 100644 --- a/xplat/src/main/java/dev/emi/emi/registry/EmiDragDropHandlers.java +++ b/xplat/src/main/java/dev/emi/emi/registry/EmiDragDropHandlers.java @@ -8,8 +8,8 @@ import dev.emi.emi.api.EmiDragDropHandler; import dev.emi.emi.api.stack.EmiIngredient; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.util.math.MatrixStack; public class EmiDragDropHandlers { public static Map, List>> fromClass = Maps.newHashMap(); @@ -21,14 +21,14 @@ public static void clear() { } @SuppressWarnings({"unchecked", "rawtypes"}) - public static void render(Screen screen, EmiIngredient stack, DrawContext draw, int mouseX, int mouseY, float delta) { + public static void render(Screen screen, EmiIngredient stack, MatrixStack matrices, int mouseX, int mouseY, float delta) { if (fromClass.containsKey(screen.getClass())) { for (EmiDragDropHandler handler : fromClass.get(screen.getClass())) { - handler.render(screen, stack, draw, mouseX, mouseY, delta); + handler.render(screen, stack, matrices, mouseX, mouseY, delta); } } for (EmiDragDropHandler handler : generic) { - handler.render(screen, stack, draw, mouseX, mouseY, delta); + handler.render(screen, stack, matrices, mouseX, mouseY, delta); } } diff --git a/xplat/src/main/java/dev/emi/emi/registry/EmiRecipeFiller.java b/xplat/src/main/java/dev/emi/emi/registry/EmiRecipeFiller.java index 55124864..e9e4dce8 100644 --- a/xplat/src/main/java/dev/emi/emi/registry/EmiRecipeFiller.java +++ b/xplat/src/main/java/dev/emi/emi/registry/EmiRecipeFiller.java @@ -28,7 +28,7 @@ import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.client.network.ClientPlayerInteractionManager; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.inventory.RecipeInputInventory; +import net.minecraft.inventory.CraftingInventory; import net.minecraft.item.ItemStack; import net.minecraft.screen.PlayerScreenHandler; import net.minecraft.screen.ScreenHandler; @@ -84,7 +84,7 @@ public static List> getAllHandlers } for (Slot slot : screen.getScreenHandler().slots) { if (slot instanceof CraftingResultSlot crs) { - RecipeInputInventory inv = ((CraftingResultSlotAccessor) crs).getInput(); + CraftingInventory inv = ((CraftingResultSlotAccessor) crs).getInput(); if (inv != null && inv.getWidth() > 0 && inv.getHeight() > 0) { return List.of(new CoercedRecipeHandler(crs)); } @@ -241,7 +241,7 @@ public static int batchesAlreadyPresent(EmiRecipe reci List stacks = Lists.newArrayList(); Slot output = handler.getOutputSlot(screen.getScreenHandler()); if (output != null && !output.getStack().isEmpty() && recipe.getOutputs().size() > 0 - && !ItemStack.areEqual(output.getStack(), recipe.getOutputs().get(0).getItemStack())) { + && !output.getStack().isItemEqual(recipe.getOutputs().get(0).getItemStack())) { return 0; } for (Slot slot : handler.getCraftingSlots(recipe, screen.getScreenHandler())) { diff --git a/xplat/src/main/java/dev/emi/emi/registry/EmiStackProviders.java b/xplat/src/main/java/dev/emi/emi/registry/EmiStackProviders.java index 43f923e1..8d510992 100644 --- a/xplat/src/main/java/dev/emi/emi/registry/EmiStackProviders.java +++ b/xplat/src/main/java/dev/emi/emi/registry/EmiStackProviders.java @@ -15,7 +15,7 @@ import dev.emi.emi.mixin.accessor.HandledScreenAccessor; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.Screen; -import net.minecraft.inventory.RecipeInputInventory; +import net.minecraft.inventory.CraftingInventory; import net.minecraft.item.ItemStack; import net.minecraft.recipe.CraftingRecipe; import net.minecraft.recipe.RecipeType; @@ -56,7 +56,7 @@ public static EmiStackInteraction getStackAt(Screen screen, int x, int y, boolea if (s instanceof CraftingResultSlot craf) { // Emi be making assumptions try { - RecipeInputInventory inv = ((CraftingResultSlotAccessor) craf).getInput(); + CraftingInventory inv = ((CraftingResultSlotAccessor) craf).getInput(); MinecraftClient client = MinecraftClient.getInstance(); List list = client.world.getRecipeManager().getAllMatches(RecipeType.CRAFTING, inv, client.world); diff --git a/xplat/src/main/java/dev/emi/emi/runtime/EmiDrawContext.java b/xplat/src/main/java/dev/emi/emi/runtime/EmiDrawContext.java index ad77952e..923e6883 100644 --- a/xplat/src/main/java/dev/emi/emi/runtime/EmiDrawContext.java +++ b/xplat/src/main/java/dev/emi/emi/runtime/EmiDrawContext.java @@ -5,7 +5,7 @@ import dev.emi.emi.EmiPort; import dev.emi.emi.api.stack.EmiIngredient; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.DrawableHelper; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.OrderedText; import net.minecraft.text.Text; @@ -13,30 +13,30 @@ public class EmiDrawContext { private final MinecraftClient client = MinecraftClient.getInstance(); - private final DrawContext context; + private final MatrixStack matrices; - private EmiDrawContext(DrawContext context) { - this.context = context; + private EmiDrawContext(MatrixStack matrices) { + this.matrices = matrices; } - public static EmiDrawContext wrap(DrawContext context) { - return new EmiDrawContext(context); + public static EmiDrawContext wrap(MatrixStack matrices) { + return new EmiDrawContext(matrices); } - public DrawContext raw() { - return context; + public MatrixStack raw() { + return matrices; } public MatrixStack matrices() { - return context.getMatrices(); + return matrices; } public void push() { - matrices().push(); + matrices.push(); } public void pop() { - matrices().pop(); + matrices.pop(); } public void drawTexture(Identifier texture, int x, int y, int u, int v, int width, int height) { @@ -49,16 +49,18 @@ public void drawTexture(Identifier texture, int x, int y, int z, float u, float public void drawTexture(Identifier texture, int x, int y, int z, float u, float v, int width, int height, int textureWidth, int textureHeight) { EmiPort.setPositionTexShader(); - context.drawTexture(texture, x, y, z, u, v, width, height, textureWidth, textureHeight); + RenderSystem.setShaderTexture(0, texture); + DrawableHelper.drawTexture(matrices, x, y, z, u, v, width, height, textureWidth, textureHeight); } public void drawTexture(Identifier texture, int x, int y, int width, int height, float u, float v, int regionWidth, int regionHeight, int textureWidth, int textureHeight) { EmiPort.setPositionTexShader(); - context.drawTexture(texture, x, y, width, height, u, v, regionWidth, regionHeight, textureWidth, textureHeight); + RenderSystem.setShaderTexture(0, texture); + DrawableHelper.drawTexture(matrices, x, y, width, height, u, v, regionWidth, regionHeight, textureWidth, textureHeight); } public void fill(int x, int y, int width, int height, int color) { - context.fill(x, y, x + width, y + height, color); + DrawableHelper.fill(matrices, x, y, x + width, y + height, color); } public void drawText(Text text, int x, int y) { @@ -66,11 +68,11 @@ public void drawText(Text text, int x, int y) { } public void drawText(Text text, int x, int y, int color) { - context.drawText(client.textRenderer, text, x, y, color, false); + client.textRenderer.draw(matrices, text, x, y, color); } public void drawText(OrderedText text, int x, int y, int color) { - context.drawText(client.textRenderer, text, x, y, color, false); + client.textRenderer.draw(matrices, text, x, y, color); } public void drawTextWithShadow(Text text, int x, int y) { @@ -78,11 +80,11 @@ public void drawTextWithShadow(Text text, int x, int y) { } public void drawTextWithShadow(Text text, int x, int y, int color) { - context.drawText(client.textRenderer, text, x, y, color, true); + client.textRenderer.drawWithShadow(matrices, text, x, y, color); } public void drawTextWithShadow(OrderedText text, int x, int y, int color) { - context.drawText(client.textRenderer, text, x, y, color, true); + client.textRenderer.drawWithShadow(matrices, text, x, y, color); } public void drawCenteredText(Text text, int x, int y) { @@ -90,7 +92,7 @@ public void drawCenteredText(Text text, int x, int y) { } public void drawCenteredText(Text text, int x, int y, int color) { - context.drawText(client.textRenderer, text, x - client.textRenderer.getWidth(text) / 2, y, color, false); + client.textRenderer.draw(matrices, text, x - client.textRenderer.getWidth(text) / 2, y, color); } public void drawCenteredTextWithShadow(Text text, int x, int y) { @@ -98,7 +100,7 @@ public void drawCenteredTextWithShadow(Text text, int x, int y) { } public void drawCenteredTextWithShadow(Text text, int x, int y, int color) { - context.drawCenteredTextWithShadow(client.textRenderer, text.asOrderedText(), x, y, color); + DrawableHelper.drawCenteredTextWithShadow(matrices, client.textRenderer, text.asOrderedText(), x, y, color); } public void resetColor() { diff --git a/xplat/src/main/java/dev/emi/emi/runtime/EmiFavorite.java b/xplat/src/main/java/dev/emi/emi/runtime/EmiFavorite.java index 15175209..7fac7e1f 100644 --- a/xplat/src/main/java/dev/emi/emi/runtime/EmiFavorite.java +++ b/xplat/src/main/java/dev/emi/emi/runtime/EmiFavorite.java @@ -16,9 +16,9 @@ import dev.emi.emi.registry.EmiRecipeFiller; import dev.emi.emi.screen.StackBatcher.Batchable; import dev.emi.emi.screen.tooltip.RecipeTooltipComponent; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.tooltip.TooltipComponent; import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.Text; public class EmiFavorite implements EmiIngredient, Batchable { @@ -69,7 +69,7 @@ public List getEmiStacks() { } @Override - public void render(DrawContext raw, int x, int y, float delta, int flags) { + public void render(MatrixStack raw, int x, int y, float delta, int flags) { EmiDrawContext context = EmiDrawContext.wrap(raw); if (recipe != null) { flags |= EmiIngredient.RENDER_AMOUNT; @@ -113,7 +113,7 @@ public void setUnbatchable() { } @Override - public void renderForBatch(VertexConsumerProvider vcp, DrawContext raw, int x, int y, int z, float delta) { + public void renderForBatch(VertexConsumerProvider vcp, MatrixStack raw, int x, int y, int z, float delta) { if (stack instanceof Batchable b) { b.renderForBatch(vcp, raw, x, y, z, delta); } @@ -126,7 +126,7 @@ public Craftable(EmiRecipe recipe) { } @Override - public void render(DrawContext raw, int x, int y, float delta, int flags) { + public void render(MatrixStack raw, int x, int y, float delta, int flags) { super.render(raw, x, y, delta, flags & (~EmiIngredient.RENDER_INGREDIENT)); } } @@ -153,7 +153,7 @@ public Synthetic(EmiIngredient ingredient, long needed, long total) { } @Override - public void render(DrawContext raw, int x, int y, float delta, int flags) { + public void render(MatrixStack raw, int x, int y, float delta, int flags) { EmiDrawContext context = EmiDrawContext.wrap(raw); int color = 0xff2200; if (state == 1) { diff --git a/xplat/src/main/java/dev/emi/emi/runtime/EmiScreenshotRecorder.java b/xplat/src/main/java/dev/emi/emi/runtime/EmiScreenshotRecorder.java index 189e640b..7c60f744 100644 --- a/xplat/src/main/java/dev/emi/emi/runtime/EmiScreenshotRecorder.java +++ b/xplat/src/main/java/dev/emi/emi/runtime/EmiScreenshotRecorder.java @@ -6,7 +6,6 @@ import org.joml.Matrix4f; import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.systems.VertexSorter; import dev.emi.emi.EmiPort; import dev.emi.emi.config.EmiConfig; @@ -73,11 +72,11 @@ private static void saveScreenshotInner(String path, int width, int height, Runn RenderSystem.applyModelViewMatrix(); Matrix4f backupProj = RenderSystem.getProjectionMatrix(); - RenderSystem.setProjectionMatrix(new Matrix4f().identity(), VertexSorter.BY_Z); + RenderSystem.setProjectionMatrix(new Matrix4f().identity()); renderer.run(); - RenderSystem.setProjectionMatrix(backupProj, VertexSorter.BY_Z); + RenderSystem.setProjectionMatrix(backupProj); view.pop(); RenderSystem.applyModelViewMatrix(); diff --git a/xplat/src/main/java/dev/emi/emi/screen/BoMScreen.java b/xplat/src/main/java/dev/emi/emi/screen/BoMScreen.java index 27764673..0b58fd8e 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/BoMScreen.java +++ b/xplat/src/main/java/dev/emi/emi/screen/BoMScreen.java @@ -44,7 +44,6 @@ import dev.emi.emi.screen.tooltip.EmiTooltip; import dev.emi.emi.screen.tooltip.RecipeTooltipComponent; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.client.gui.tooltip.TooltipComponent; @@ -191,7 +190,7 @@ public void recalculateTree() { } @Override - public void render(DrawContext raw, int mouseX, int mouseY, float delta) { + public void render(MatrixStack raw, int mouseX, int mouseY, float delta) { EmiDrawContext context = EmiDrawContext.wrap(raw); this.renderBackgroundTexture(context.raw()); lastMouseX = mouseX; diff --git a/xplat/src/main/java/dev/emi/emi/screen/ConfigEnumScreen.java b/xplat/src/main/java/dev/emi/emi/screen/ConfigEnumScreen.java index d58103ff..76abe644 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/ConfigEnumScreen.java +++ b/xplat/src/main/java/dev/emi/emi/screen/ConfigEnumScreen.java @@ -11,11 +11,11 @@ import dev.emi.emi.screen.widget.config.EmiNameWidget; import dev.emi.emi.screen.widget.config.ListWidget; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.Element; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.tooltip.TooltipComponent; import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.Text; public class ConfigEnumScreen extends Screen { @@ -48,7 +48,7 @@ public void init() { } @Override - public void render(DrawContext raw, int mouseX, int mouseY, float delta) { + public void render(MatrixStack raw, int mouseX, int mouseY, float delta) { EmiDrawContext context = EmiDrawContext.wrap(raw); list.setScrollAmount(list.getScrollAmount()); this.renderBackgroundTexture(context.raw()); @@ -102,7 +102,7 @@ public List children() { } @Override - public void render(DrawContext raw, int index, int y, int x, int width, int height, int mouseX, int mouseY, + public void render(MatrixStack raw, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean hovered, float delta) { button.y = y; button.x = x + width / 2 - button.getWidth() / 2; diff --git a/xplat/src/main/java/dev/emi/emi/screen/ConfigPresetScreen.java b/xplat/src/main/java/dev/emi/emi/screen/ConfigPresetScreen.java index 1a2fae30..361f090b 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/ConfigPresetScreen.java +++ b/xplat/src/main/java/dev/emi/emi/screen/ConfigPresetScreen.java @@ -16,11 +16,11 @@ import dev.emi.emi.screen.widget.config.EmiNameWidget; import dev.emi.emi.screen.widget.config.ListWidget; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.Element; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.tooltip.TooltipComponent; import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.Text; public class ConfigPresetScreen extends Screen { @@ -71,7 +71,7 @@ public void init() { } @Override - public void render(DrawContext raw, int mouseX, int mouseY, float delta) { + public void render(MatrixStack raw, int mouseX, int mouseY, float delta) { EmiDrawContext context = EmiDrawContext.wrap(raw); list.setScrollAmount(list.getScrollAmount()); this.renderBackgroundTexture(context.raw()); @@ -138,7 +138,7 @@ public List children() { } @Override - public void render(DrawContext raw, int index, int y, int x, int width, int height, int mouseX, int mouseY, + public void render(MatrixStack raw, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean hovered, float delta) { button.y = y; button.x = x + width / 2 - button.getWidth() / 2; @@ -164,7 +164,7 @@ public List children() { } @Override - public void render(DrawContext raw, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean hovered, float delta) { + public void render(MatrixStack raw, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean hovered, float delta) { EmiDrawContext context = EmiDrawContext.wrap(raw); context.drawCenteredTextWithShadow(text, x + width / 2, y + 3, -1); } diff --git a/xplat/src/main/java/dev/emi/emi/screen/ConfigScreen.java b/xplat/src/main/java/dev/emi/emi/screen/ConfigScreen.java index 0c85588e..38f6f771 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/ConfigScreen.java +++ b/xplat/src/main/java/dev/emi/emi/screen/ConfigScreen.java @@ -28,8 +28,8 @@ import dev.emi.emi.config.SidebarSubpanels; import dev.emi.emi.input.EmiBind; import dev.emi.emi.input.EmiBind.ModifiedKey; -import dev.emi.emi.input.EmiInput; import dev.emi.emi.runtime.EmiDrawContext; +import dev.emi.emi.input.EmiInput; import dev.emi.emi.screen.widget.SizedButtonWidget; import dev.emi.emi.screen.widget.config.BooleanWidget; import dev.emi.emi.screen.widget.config.ConfigEntryWidget; @@ -48,13 +48,13 @@ import dev.emi.emi.screen.widget.config.SubGroupNameWidget; import dev.emi.emi.search.EmiSearch; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.tooltip.TooltipComponent; import net.minecraft.client.gui.widget.ButtonWidget; import net.minecraft.client.gui.widget.TextFieldWidget; import net.minecraft.client.resource.language.I18n; import net.minecraft.client.util.InputUtil; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.StringVisitable; import net.minecraft.text.Style; import net.minecraft.text.Text; @@ -363,7 +363,7 @@ public void updateChanges() { } @Override - public void render(DrawContext raw, int mouseX, int mouseY, float delta) { + public void render(MatrixStack raw, int mouseX, int mouseY, float delta) { EmiDrawContext context = EmiDrawContext.wrap(raw); list.setScrollAmount(list.getScrollAmount()); this.renderBackgroundTexture(context.raw()); diff --git a/xplat/src/main/java/dev/emi/emi/screen/DisabledToast.java b/xplat/src/main/java/dev/emi/emi/screen/DisabledToast.java index c9cf5a4f..f3955588 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/DisabledToast.java +++ b/xplat/src/main/java/dev/emi/emi/screen/DisabledToast.java @@ -3,14 +3,14 @@ import dev.emi.emi.EmiPort; import dev.emi.emi.config.EmiConfig; import dev.emi.emi.runtime.EmiDrawContext; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.toast.Toast; import net.minecraft.client.toast.ToastManager; +import net.minecraft.client.util.math.MatrixStack; public class DisabledToast implements Toast { @Override - public Visibility draw(DrawContext raw, ToastManager manager, long time) { + public Visibility draw(MatrixStack raw, ToastManager manager, long time) { EmiDrawContext context = EmiDrawContext.wrap(raw); context.resetColor(); context.drawTexture(TEXTURE, 0, 0, 0, 0, this.getWidth(), this.getHeight()); diff --git a/xplat/src/main/java/dev/emi/emi/screen/EmiScreenManager.java b/xplat/src/main/java/dev/emi/emi/screen/EmiScreenManager.java index 1fac02c5..c74b9b9b 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/EmiScreenManager.java +++ b/xplat/src/main/java/dev/emi/emi/screen/EmiScreenManager.java @@ -696,6 +696,10 @@ private static void renderCurrentTooltip(EmiDrawContext context, int mouseX, int } if (cursor.isEmpty() && draggedStack.isEmpty()) { client.getProfiler().swap("hover"); + MatrixStack view = RenderSystem.getModelViewStack(); + view.push(); + view.translate(0, 0, 200); + RenderSystem.applyModelViewMatrix(); EmiIngredient hov = EmiStack.EMPTY; SidebarType sidebar = SidebarType.NONE; if (getHoveredStack(mouseX, mouseY, false) instanceof SidebarEmiStackInteraction sesi) { @@ -719,6 +723,8 @@ private static void renderCurrentTooltip(EmiDrawContext context, int mouseX, int } else { EmiRenderHelper.drawTooltip(screen, context, list, mouseX, mouseY); } + view.pop(); + RenderSystem.applyModelViewMatrix(); client.getProfiler().pop(); } lastStackTooltipRendered = null; @@ -737,7 +743,7 @@ private static void renderDevMode(EmiDrawContext context, int mouseX, int mouseY context.drawTextWithShadow(EmiPort.literal(warnCount), 48, screen.height - 21, color); int width = Math.max(client.textRenderer.getWidth(title), client.textRenderer.getWidth(warnCount)); if (mouseX >= 48 && mouseX < width + 48 && mouseY > screen.height - 28) { - context.raw().drawTooltip(client.textRenderer, Stream.concat(Stream.of(" EMI detected some issues, see log for full details"), + screen.renderTooltip(context.raw(), Stream.concat(Stream.of(" EMI detected some issues, see log for full details"), EmiReloadLog.warnings.stream()).map(s -> { String a = s; if (a.length() > 10 && client.textRenderer.getWidth(a) > screen.width - 20) { diff --git a/xplat/src/main/java/dev/emi/emi/screen/FakeScreen.java b/xplat/src/main/java/dev/emi/emi/screen/FakeScreen.java index 46ce3efa..2cffa57c 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/FakeScreen.java +++ b/xplat/src/main/java/dev/emi/emi/screen/FakeScreen.java @@ -17,13 +17,14 @@ public class FakeScreen extends Screen { protected FakeScreen() { super(EmiPort.literal("")); this.client = MinecraftClient.getInstance(); + this.itemRenderer = client.getItemRenderer(); this.textRenderer = client.textRenderer; this.width = 99999; this.height = 99999; } public List getTooltipComponentListFromItem(ItemStack stack) { - List list = Screen.getTooltipFromItem(client, stack) + List list = this.getTooltipFromItem(stack) .stream().map(EmiPort::ordered).map(TooltipComponent::of).collect(Collectors.toList()); Optional data = stack.getTooltipData(); if (data.isPresent()) { diff --git a/xplat/src/main/java/dev/emi/emi/screen/RecipeScreen.java b/xplat/src/main/java/dev/emi/emi/screen/RecipeScreen.java index 01583532..b4f11505 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/RecipeScreen.java +++ b/xplat/src/main/java/dev/emi/emi/screen/RecipeScreen.java @@ -32,11 +32,11 @@ import dev.emi.emi.screen.widget.ResolutionButtonWidget; import dev.emi.emi.screen.widget.SizedButtonWidget; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.client.gui.tooltip.TooltipComponent; import net.minecraft.client.sound.PositionedSoundInstance; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.sound.SoundEvents; import net.minecraft.text.Text; import net.minecraft.util.Identifier; @@ -164,7 +164,7 @@ private void setRecipePageWidth(int width) { @SuppressWarnings({"rawtypes", "unchecked"}) @Override - public void render(DrawContext raw, int mouseX, int mouseY, float delta) { + public void render(MatrixStack raw, int mouseX, int mouseY, float delta) { EmiDrawContext context = EmiDrawContext.wrap(raw); this.renderBackground(context.raw()); context.resetColor(); @@ -250,7 +250,7 @@ public void render(DrawContext raw, int mouseX, int mouseY, float delta) { EmiScreenManager.drawForeground(context, mouseX, mouseY, delta); super.render(context.raw(), mouseX, mouseY, delta); if (categoryHovered) { - context.raw().drawTooltip(client.textRenderer, List.of( + this.renderTooltip(context.raw(), List.of( tab.category.getName(), EmiPort.translatable("emi.view_all_recipes") ), mouseX, mouseY); diff --git a/xplat/src/main/java/dev/emi/emi/screen/StackBatcher.java b/xplat/src/main/java/dev/emi/emi/screen/StackBatcher.java index 3487e088..7c06a52f 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/StackBatcher.java +++ b/xplat/src/main/java/dev/emi/emi/screen/StackBatcher.java @@ -18,7 +18,6 @@ import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.systems.VertexSorter; import dev.emi.emi.EmiPort; import dev.emi.emi.api.stack.EmiIngredient; @@ -27,7 +26,6 @@ import dev.emi.emi.runtime.EmiLog; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gl.VertexBuffer; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.render.BufferBuilder; import net.minecraft.client.render.BufferRenderer; import net.minecraft.client.render.DiffuseLighting; @@ -38,6 +36,7 @@ import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.render.model.BakedQuad; import net.minecraft.client.texture.Sprite; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.item.ItemStack; /** @@ -71,7 +70,7 @@ public interface Batchable { boolean isSideLit(); boolean isUnbatchable(); void setUnbatchable(); - void renderForBatch(VertexConsumerProvider vcp, DrawContext draw, int x, int y, int z, float delta); + void renderForBatch(VertexConsumerProvider vcp, MatrixStack matrices, int x, int y, int z, float delta); } private final BatcherVertexConsumerProvider imm; @@ -131,10 +130,10 @@ public void begin(int x, int y, int z) { } } - public void render(Batchable batchable, DrawContext draw, int x, int y, float delta) { + public void render(Batchable batchable, MatrixStack matrices, int x, int y, float delta) { if (!populated) { try { - batchable.renderForBatch(batchable.isSideLit() ? imm : unlitFacade, draw, x-this.x, -y+this.y, z, delta); + batchable.renderForBatch(batchable.isSideLit() ? imm : unlitFacade, matrices, x-this.x, -y+this.y, z, delta); } catch (Throwable t) { if (EmiConfig.devMode) { EmiLog.error("Batchable threw exception during batched rendering. See log for info"); @@ -145,15 +144,15 @@ public void render(Batchable batchable, DrawContext draw, int x, int y, float de } } - public void render(EmiIngredient stack, DrawContext draw, int x, int y, float delta) { - render(stack, draw, x, y, delta, -1 ^ EmiIngredient.RENDER_AMOUNT); + public void render(EmiIngredient stack, MatrixStack matrices, int x, int y, float delta) { + render(stack, matrices, x, y, delta, -1 ^ EmiIngredient.RENDER_AMOUNT); } - public void render(EmiIngredient stack, DrawContext draw, int x, int y, float delta, int flags) { + public void render(EmiIngredient stack, MatrixStack matrices, int x, int y, float delta, int flags) { if (stack instanceof Batchable b && !b.isUnbatchable() && isEnabled() && (flags & EmiIngredient.RENDER_ICON) != 0) { if (!populated) { try { - b.renderForBatch(b.isSideLit() ? imm : unlitFacade, draw, x-this.x, -y-this.y, z, delta); + b.renderForBatch(b.isSideLit() ? imm : unlitFacade, matrices, x-this.x, -y-this.y, z, delta); if (sodiumSpriteHandle != null && !stack.isEmpty()) { ItemStack is = stack.getEmiStacks().get(0).getItemStack(); MinecraftClient client = MinecraftClient.getInstance(); @@ -175,9 +174,9 @@ public void render(EmiIngredient stack, DrawContext draw, int x, int y, float de b.setUnbatchable(); } } - stack.render(draw, x, y, delta, flags & (~EmiIngredient.RENDER_ICON)); + stack.render(matrices, x, y, delta, flags & (~EmiIngredient.RENDER_ICON)); } else { - stack.render(draw, x, y, delta, flags); + stack.render(matrices, x, y, delta, flags); } } @@ -223,7 +222,7 @@ private void bake() { public void bake(RenderLayer layer) { BufferBuilder bldr = imm.getBufferInternal(layer); if (!imm.getActiveConsumers().remove(bldr)) return; - VertexBuffer vb = new VertexBuffer(VertexBuffer.Usage.DYNAMIC); + VertexBuffer vb = new VertexBuffer(); EmiPort.upload(vb, bldr); buffers.put(layer, vb); bldr.reset(); @@ -313,7 +312,7 @@ public void draw(RenderLayer layer) { if (!this.activeConsumers.remove(bufferBuilder)) { return; } - layer.draw(bufferBuilder, VertexSorter.BY_Z); + layer.draw(bufferBuilder, 0, 0, 0); if (bl) { this.currentLayer = Optional.empty(); } diff --git a/xplat/src/main/java/dev/emi/emi/screen/tooltip/EmiTooltipComponent.java b/xplat/src/main/java/dev/emi/emi/screen/tooltip/EmiTooltipComponent.java index 08cecf2c..9d7fd76b 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/tooltip/EmiTooltipComponent.java +++ b/xplat/src/main/java/dev/emi/emi/screen/tooltip/EmiTooltipComponent.java @@ -4,14 +4,13 @@ import dev.emi.emi.EmiPort; import dev.emi.emi.runtime.EmiDrawContext; -import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.font.TextRenderer.TextLayerType; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.tooltip.TooltipComponent; import net.minecraft.client.render.LightmapTextureManager; import net.minecraft.client.render.VertexConsumerProvider.Immediate; import net.minecraft.client.render.item.ItemRenderer; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.Text; public interface EmiTooltipComponent extends TooltipComponent { @@ -23,12 +22,11 @@ default void drawTooltipText(TextRenderData text) { } @Override - default void drawItems(TextRenderer textRenderer, int x, int y, DrawContext raw) { + default void drawItems(TextRenderer textRenderer, int x, int y, MatrixStack raw, ItemRenderer itemRenderer) { EmiDrawContext context = EmiDrawContext.wrap(raw); context.push(); context.matrices().translate(x, y, 0); - MinecraftClient client = MinecraftClient.getInstance(); - drawTooltip(context, new TooltipRenderData(textRenderer, client.getItemRenderer(), x, y)); + drawTooltip(context, new TooltipRenderData(textRenderer, itemRenderer, x, y)); context.pop(); } diff --git a/xplat/src/main/java/dev/emi/emi/screen/widget/EmiSearchWidget.java b/xplat/src/main/java/dev/emi/emi/screen/widget/EmiSearchWidget.java index dae7e998..44088cf1 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/widget/EmiSearchWidget.java +++ b/xplat/src/main/java/dev/emi/emi/screen/widget/EmiSearchWidget.java @@ -16,7 +16,6 @@ import dev.emi.emi.search.EmiSearch; import dev.emi.emi.search.QueryType; import net.minecraft.client.font.TextRenderer; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.widget.TextFieldWidget; import net.minecraft.client.resource.language.I18n; import net.minecraft.client.util.math.MatrixStack; @@ -199,7 +198,7 @@ public boolean keyPressed(int keyCode, int scanCode, int modifiers) { } @Override - public void render(DrawContext raw, int mouseX, int mouseY, float delta) { + public void render(MatrixStack raw, int mouseX, int mouseY, float delta) { EmiDrawContext context = EmiDrawContext.wrap(raw); this.setEditable(EmiConfig.enabled); String lower = getText().toLowerCase(); diff --git a/xplat/src/main/java/dev/emi/emi/screen/widget/ResolutionButtonWidget.java b/xplat/src/main/java/dev/emi/emi/screen/widget/ResolutionButtonWidget.java index fb5cb982..d47684ef 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/widget/ResolutionButtonWidget.java +++ b/xplat/src/main/java/dev/emi/emi/screen/widget/ResolutionButtonWidget.java @@ -14,8 +14,8 @@ import dev.emi.emi.runtime.EmiHistory; import dev.emi.emi.widget.RecipeDefaultButtonWidget; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.util.math.MatrixStack; public class ResolutionButtonWidget extends ButtonWidget { public Supplier hoveredWidget; @@ -31,11 +31,11 @@ public ResolutionButtonWidget(int x, int y, int width, int height, EmiIngredient } @Override - public void render(DrawContext raw, int mouseX, int mouseY, float delta) { + public void render(MatrixStack raw, int mouseX, int mouseY, float delta) { super.render(raw, mouseX, mouseY, delta); if (this.isHovered()) { MinecraftClient client = MinecraftClient.getInstance(); - raw.drawTooltip(client.textRenderer, List.of( + client.currentScreen.renderTooltip(raw, List.of( EmiPort.translatable("tooltip.emi.resolution"), EmiPort.translatable("tooltip.emi.select_resolution"), EmiPort.translatable("tooltip.emi.default_resolution"), @@ -46,7 +46,7 @@ public void render(DrawContext raw, int mouseX, int mouseY, float delta) { } @Override - public void renderButton(DrawContext raw, int mouseX, int mouseY, float delta) { + public void renderButton(MatrixStack raw, int mouseX, int mouseY, float delta) { EmiDrawContext context = EmiDrawContext.wrap(raw); int u = 0; if (this.isHovered()) { diff --git a/xplat/src/main/java/dev/emi/emi/screen/widget/SizedButtonWidget.java b/xplat/src/main/java/dev/emi/emi/screen/widget/SizedButtonWidget.java index 590190f1..d4d0da3c 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/widget/SizedButtonWidget.java +++ b/xplat/src/main/java/dev/emi/emi/screen/widget/SizedButtonWidget.java @@ -11,9 +11,9 @@ import dev.emi.emi.EmiRenderHelper; import dev.emi.emi.runtime.EmiDrawContext; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.tooltip.TooltipComponent; import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.Text; import net.minecraft.util.Identifier; @@ -64,7 +64,7 @@ protected int getV(int mouseX, int mouseY) { } @Override - public void renderButton(DrawContext raw, int mouseX, int mouseY, float delta) { + public void renderButton(MatrixStack raw, int mouseX, int mouseY, float delta) { EmiDrawContext context = EmiDrawContext.wrap(raw); RenderSystem.enableDepthTest(); context.drawTexture(texture, this.x, this.y, getU(mouseX, mouseY), getV(mouseX, mouseY), this.width, this.height); diff --git a/xplat/src/main/java/dev/emi/emi/screen/widget/config/ConfigEntryWidget.java b/xplat/src/main/java/dev/emi/emi/screen/widget/config/ConfigEntryWidget.java index 0cdb5ca1..1d44c173 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/widget/config/ConfigEntryWidget.java +++ b/xplat/src/main/java/dev/emi/emi/screen/widget/config/ConfigEntryWidget.java @@ -8,10 +8,10 @@ import dev.emi.emi.config.EmiConfig.ConfigGroup; import dev.emi.emi.runtime.EmiDrawContext; import dev.emi.emi.screen.widget.config.ListWidget.Entry; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.Drawable; import net.minecraft.client.gui.Element; import net.minecraft.client.gui.tooltip.TooltipComponent; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.Text; public abstract class ConfigEntryWidget extends Entry { @@ -39,7 +39,7 @@ public void update(int y, int x, int width, int height) { } @Override - public void render(DrawContext raw, int index, int y, int x, int width, int height, int mouseX, int mouseY, + public void render(MatrixStack raw, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean hovered, float delta) { EmiDrawContext context = EmiDrawContext.wrap(raw); if (group != null) { diff --git a/xplat/src/main/java/dev/emi/emi/screen/widget/config/ConfigJumpButton.java b/xplat/src/main/java/dev/emi/emi/screen/widget/config/ConfigJumpButton.java index 5767a1c9..10437d8d 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/widget/config/ConfigJumpButton.java +++ b/xplat/src/main/java/dev/emi/emi/screen/widget/config/ConfigJumpButton.java @@ -6,7 +6,7 @@ import dev.emi.emi.EmiRenderHelper; import dev.emi.emi.screen.widget.SizedButtonWidget; -import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.Text; public class ConfigJumpButton extends SizedButtonWidget { @@ -22,7 +22,7 @@ protected int getV(int mouseX, int mouseY) { } @Override - public void renderButton(DrawContext raw, int mouseX, int mouseY, float delta) { + public void renderButton(MatrixStack raw, int mouseX, int mouseY, float delta) { if (this.isMouseOver(mouseX, mouseY)) { RenderSystem.setShaderColor(0.5f, 0.6f, 1f, 1f); } diff --git a/xplat/src/main/java/dev/emi/emi/screen/widget/config/EmiNameWidget.java b/xplat/src/main/java/dev/emi/emi/screen/widget/config/EmiNameWidget.java index 60fa621d..09078a8f 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/widget/config/EmiNameWidget.java +++ b/xplat/src/main/java/dev/emi/emi/screen/widget/config/EmiNameWidget.java @@ -13,8 +13,8 @@ import it.unimi.dsi.fastutil.ints.IntSet; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.Drawable; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.Style; public class EmiNameWidget implements Drawable { @@ -99,7 +99,7 @@ public String transformString(Random rand, String string, float progress) { return ret; } - public void render(DrawContext raw, int mouseX, int mouseY, float delta) { + public void render(MatrixStack raw, int mouseX, int mouseY, float delta) { EmiDrawContext context = EmiDrawContext.wrap(raw); long time = System.currentTimeMillis(); long progress = time % 5_000; diff --git a/xplat/src/main/java/dev/emi/emi/screen/widget/config/GroupNameWidget.java b/xplat/src/main/java/dev/emi/emi/screen/widget/config/GroupNameWidget.java index f97636da..67425cb3 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/widget/config/GroupNameWidget.java +++ b/xplat/src/main/java/dev/emi/emi/screen/widget/config/GroupNameWidget.java @@ -8,9 +8,9 @@ import dev.emi.emi.runtime.EmiDrawContext; import dev.emi.emi.screen.widget.config.ListWidget.Entry; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.Element; import net.minecraft.client.sound.PositionedSoundInstance; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.sound.SoundEvents; import net.minecraft.text.Text; @@ -27,7 +27,7 @@ public GroupNameWidget(String id, Text text) { } @Override - public void render(DrawContext raw, int index, int y, int x, int width, int height, int mouseX, int mouseY, + public void render(MatrixStack raw, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean hovered, float delta) { EmiDrawContext context = EmiDrawContext.wrap(raw); context.drawCenteredTextWithShadow(text, x + width / 2, y + 3, -1); diff --git a/xplat/src/main/java/dev/emi/emi/screen/widget/config/ListWidget.java b/xplat/src/main/java/dev/emi/emi/screen/widget/config/ListWidget.java index e5d91646..ba7d1261 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/widget/config/ListWidget.java +++ b/xplat/src/main/java/dev/emi/emi/screen/widget/config/ListWidget.java @@ -14,11 +14,10 @@ import dev.emi.emi.EmiPort; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.AbstractParentElement; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.Drawable; +import net.minecraft.client.gui.DrawableHelper; import net.minecraft.client.gui.Element; import net.minecraft.client.gui.Selectable; -import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; import net.minecraft.client.gui.screen.narration.NarrationPart; import net.minecraft.client.gui.tooltip.TooltipComponent; @@ -28,6 +27,7 @@ import net.minecraft.client.render.Tessellator; import net.minecraft.client.render.VertexFormat; import net.minecraft.client.render.VertexFormats; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.Text; import net.minecraft.util.math.MathHelper; @@ -152,7 +152,7 @@ protected int getMaxPosition() { } @Override - public void render(DrawContext draw, int mouseX, int mouseY, float delta) { + public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { int o; int n; int m; @@ -164,7 +164,7 @@ public void render(DrawContext draw, int mouseX, int mouseY, float delta) { this.hoveredEntry = this.isMouseOver(mouseX, mouseY) ? this.getEntryAtPosition(mouseX, mouseY) : null; { // Render background - RenderSystem.setShaderTexture(0, Screen.OPTIONS_BACKGROUND_TEXTURE); + RenderSystem.setShaderTexture(0, DrawableHelper.OPTIONS_BACKGROUND_TEXTURE); RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); bufferBuilder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR); bufferBuilder.vertex((double)this.left, (double)this.bottom, 0.0) @@ -188,12 +188,12 @@ public void render(DrawContext draw, int mouseX, int mouseY, float delta) { int k = this.getRowLeft(); int l = this.top + 4 - (int)this.getScrollAmount(); - this.renderList(draw, k, l, mouseX, mouseY, delta); + this.renderList(matrices, k, l, mouseX, mouseY, delta); { // Render horizontal shadows RenderSystem.setShader(GameRenderer::getPositionTexColorProgram); - RenderSystem.setShaderTexture(0, Screen.OPTIONS_BACKGROUND_TEXTURE); + RenderSystem.setShaderTexture(0, DrawableHelper.OPTIONS_BACKGROUND_TEXTURE); RenderSystem.enableDepthTest(); RenderSystem.depthFunc(519); bufferBuilder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR); @@ -449,7 +449,7 @@ public boolean isMouseOver(double mouseX, double mouseY) { return mouseY >= (double)this.top && mouseY <= (double)this.bottom && mouseX >= (double)this.left && mouseX <= (double)this.right; } - protected void renderList(DrawContext draw, int x, int y, int mouseX, int mouseY, float delta) { + protected void renderList(MatrixStack matrices, int x, int y, int mouseX, int mouseY, float delta) { int i = this.getEntryCount(); Tessellator tessellator = Tessellator.getInstance(); BufferBuilder bufferBuilder = tessellator.getBuffer(); @@ -487,7 +487,7 @@ protected void renderList(DrawContext draw, int x, int y, int mouseX, int mouseY tessellator.draw(); } p = this.getRowLeft(); - ((Entry)entry).render(draw, j, k, p, o - 3, n, mouseX, mouseY, Objects.equals(this.hoveredEntry, entry), delta); + ((Entry)entry).render(matrices, j, k, p, o - 3, n, mouseX, mouseY, Objects.equals(this.hoveredEntry, entry), delta); } } @@ -573,7 +573,7 @@ public void appendNarrations(NarrationMessageBuilder var1) { public static abstract class Entry extends AbstractParentElement { public ListWidget parentList; - public abstract void render(DrawContext draw, int index, int y, int x, int width, int height, int mouseX, int mouseY, + public abstract void render(MatrixStack matrices, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean hovered, float delta); @Override diff --git a/xplat/src/main/java/dev/emi/emi/screen/widget/config/SubGroupNameWidget.java b/xplat/src/main/java/dev/emi/emi/screen/widget/config/SubGroupNameWidget.java index 64a16f0b..5b12c241 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/widget/config/SubGroupNameWidget.java +++ b/xplat/src/main/java/dev/emi/emi/screen/widget/config/SubGroupNameWidget.java @@ -2,7 +2,7 @@ import dev.emi.emi.EmiPort; import dev.emi.emi.runtime.EmiDrawContext; -import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.Text; public class SubGroupNameWidget extends GroupNameWidget { @@ -13,7 +13,7 @@ public SubGroupNameWidget(String id, Text text) { } @Override - public void render(DrawContext raw, int index, int y, int x, int width, int height, int mouseX, int mouseY, + public void render(MatrixStack raw, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean hovered, float delta) { EmiDrawContext context = EmiDrawContext.wrap(raw); context.drawTextWithShadow(text, x + 20, y + 3); diff --git a/xplat/src/main/java/dev/emi/emi/widget/RecipeBackground.java b/xplat/src/main/java/dev/emi/emi/widget/RecipeBackground.java index 239cccac..2e99a814 100644 --- a/xplat/src/main/java/dev/emi/emi/widget/RecipeBackground.java +++ b/xplat/src/main/java/dev/emi/emi/widget/RecipeBackground.java @@ -4,7 +4,7 @@ import dev.emi.emi.api.widget.Bounds; import dev.emi.emi.api.widget.Widget; import dev.emi.emi.runtime.EmiDrawContext; -import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.util.Identifier; public class RecipeBackground extends Widget { @@ -24,7 +24,7 @@ public Bounds getBounds() { } @Override - public void render(DrawContext raw, int mouseX, int mouseY, float delta) { + public void render(MatrixStack raw, int mouseX, int mouseY, float delta) { EmiDrawContext context = EmiDrawContext.wrap(raw); EmiRenderHelper.drawNinePatch(context, TEXTURE, x, y, width, height, 27, 0, 4, 1); } diff --git a/xplat/src/main/java/dev/emi/emi/widget/RecipeButtonWidget.java b/xplat/src/main/java/dev/emi/emi/widget/RecipeButtonWidget.java index b050e9f6..4ad3cd13 100644 --- a/xplat/src/main/java/dev/emi/emi/widget/RecipeButtonWidget.java +++ b/xplat/src/main/java/dev/emi/emi/widget/RecipeButtonWidget.java @@ -6,8 +6,8 @@ import dev.emi.emi.api.widget.Widget; import dev.emi.emi.runtime.EmiDrawContext; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.sound.PositionedSoundInstance; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.sound.SoundEvents; public class RecipeButtonWidget extends Widget { @@ -40,7 +40,7 @@ public Bounds getBounds() { } @Override - public void render(DrawContext raw, int mouseX, int mouseY, float delta) { + public void render(MatrixStack raw, int mouseX, int mouseY, float delta) { EmiDrawContext context = EmiDrawContext.wrap(raw); context.resetColor(); context.drawTexture(EmiRenderHelper.BUTTONS, x, y, 12, 12, u, v + getTextureOffset(mouseX, mouseY), 12, 12, 256, 256); diff --git a/xplat/src/main/java/dev/emi/emi/widget/RecipeScreenshotButtonWidget.java b/xplat/src/main/java/dev/emi/emi/widget/RecipeScreenshotButtonWidget.java index d29c5946..7cf63304 100644 --- a/xplat/src/main/java/dev/emi/emi/widget/RecipeScreenshotButtonWidget.java +++ b/xplat/src/main/java/dev/emi/emi/widget/RecipeScreenshotButtonWidget.java @@ -7,9 +7,8 @@ import dev.emi.emi.api.recipe.EmiRecipe; import dev.emi.emi.runtime.EmiDrawContext; import dev.emi.emi.runtime.EmiScreenshotRecorder; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.tooltip.TooltipComponent; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.util.Identifier; public class RecipeScreenshotButtonWidget extends RecipeButtonWidget { @@ -38,10 +37,8 @@ public boolean mouseClicked(int mouseX, int mouseY, int button) { int width = recipe.getDisplayWidth() + 8; int height = recipe.getDisplayHeight() + 8; - MinecraftClient client = MinecraftClient.getInstance(); - DrawContext context = new DrawContext(client, client.getBufferBuilders().getEntityVertexConsumers()); EmiScreenshotRecorder.saveScreenshot("emi/recipes/" + path, width, height, - () -> EmiRenderHelper.renderRecipe(recipe, EmiDrawContext.wrap(context), 0, 0, false, -1)); + () -> EmiRenderHelper.renderRecipe(recipe, EmiDrawContext.wrap(new MatrixStack()), 0, 0, false, -1)); return true; } diff --git a/xplat/src/main/resources/assets/emi/lang/en_us.json b/xplat/src/main/resources/assets/emi/lang/en_us.json index a054f255..50d9e96d 100644 --- a/xplat/src/main/resources/assets/emi/lang/en_us.json +++ b/xplat/src/main/resources/assets/emi/lang/en_us.json @@ -375,20 +375,6 @@ "tag.item.minecraft.smelts_to_glass": "Smelts to Glass", "tag.item.minecraft.swords": "Swords", "tag.item.minecraft.tools": "Tools", - "tag.item.minecraft.bamboo_blocks": "Bamboo Blocks", - "tag.item.minecraft.bookshelf_books": "Bookshelf Books", - "tag.item.minecraft.breaks_decorated_pots": "Breaks Decorated Pots", - "tag.item.minecraft.cherry_logs": "Cherry Logs", - "tag.item.minecraft.decorated_pot_ingredients": "Decorated Pot Ingredients", - "tag.item.minecraft.decorated_pot_sherds": "Decorated Pot Sherds", - "tag.item.minecraft.hanging_signs": "Hanging Signs", - "tag.item.minecraft.noteblock_top_instruments": "Noteblock Top Instruments", - "tag.item.minecraft.sniffer_food": "Sniffer Food", - "tag.item.minecraft.stone_buttons": "Stone Buttons", - "tag.item.minecraft.trim_materials": "Trim Materials", - "tag.item.minecraft.trim_templates": "Trim Templates", - "tag.item.minecraft.trimmable_armor": "Trimmable Armor", - "tag.item.minecraft.villager_plantable_seeds": "Villager Plantable Seeds", "tag.fluid.minecraft.water": "Water", "tag.fluid.minecraft.lava": "Lava", diff --git a/xplat/src/main/resources/emi.mixins.json b/xplat/src/main/resources/emi.mixins.json index 12b40d74..40847db1 100644 --- a/xplat/src/main/resources/emi.mixins.json +++ b/xplat/src/main/resources/emi.mixins.json @@ -7,18 +7,16 @@ "accessor.AxeItemAccessor", "accessor.BakedModelManagerAccessor", "accessor.CraftingResultSlotAccessor", - "accessor.DrawContextAccessor", "accessor.HandledScreenAccessor", "accessor.HoeItemAccessor", "accessor.ItemRendererAccessor", + "accessor.LegacySmithingRecipeAccessor", "accessor.OrderedTextTooltipComponentAccessor", + "accessor.ScreenAccessor", "accessor.ShovelItemAccessor", - "accessor.SmithingTransformRecipeAccessor", - "accessor.SmithingTrimRecipeAccessor", "jei.PluginCallerMixin", "AbstractInventoryScreenMixin", "CraftingResultSlotMixin", - "DrawContextMixin", "HandledScreenMixin", "HoeItemMixin", "ItemStackMixin", @@ -26,6 +24,7 @@ "MinecraftClientMixin", "MouseMixin", "RecipeBookWidgetMixin", + "ScreenMixin", "ToastManagerMixin" ], "mixins": [ From f56cf317db459e96e33e8db0ff256d9b24783d10 Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Tue, 13 Jun 2023 19:09:45 -0500 Subject: [PATCH 10/67] Revert "1.20 specific bugs" This reverts commit ed788a52150c70d2377534907c8fefec2317cd42. --- .../main/java/dev/emi/emi/screen/widget/EmiSearchWidget.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/xplat/src/main/java/dev/emi/emi/screen/widget/EmiSearchWidget.java b/xplat/src/main/java/dev/emi/emi/screen/widget/EmiSearchWidget.java index 44088cf1..d6774e28 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/widget/EmiSearchWidget.java +++ b/xplat/src/main/java/dev/emi/emi/screen/widget/EmiSearchWidget.java @@ -145,7 +145,6 @@ public void swap() { @Override public void setFocused(boolean focused) { isFocused = focused; - super.setFocused(focused); } @Override @@ -160,9 +159,6 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { return false; } else { boolean b = super.mouseClicked(mouseX, mouseY, button == 1 ? 0 : button); - if (isMouseOver(mouseX, mouseY)) { - setFocused(true); - } if (this.isFocused()) { if (button == 0) { if (System.currentTimeMillis() - lastClick < 500) { From 594553f0f20a698aba118bef63495234185f1d2e Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Tue, 20 Jun 2023 19:00:52 -0500 Subject: [PATCH 11/67] Fabric legacy tooltip components --- .../java/dev/emi/emi/screen/FakeScreen.java | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/fabric/src/main/java/dev/emi/emi/screen/FakeScreen.java b/fabric/src/main/java/dev/emi/emi/screen/FakeScreen.java index 3c685652..558b5c1a 100644 --- a/fabric/src/main/java/dev/emi/emi/screen/FakeScreen.java +++ b/fabric/src/main/java/dev/emi/emi/screen/FakeScreen.java @@ -1,10 +1,14 @@ package dev.emi.emi.screen; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.reflect.Method; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; import dev.emi.emi.EmiPort; +import net.fabricmc.loader.api.FabricLoader; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.tooltip.TooltipComponent; @@ -13,6 +17,20 @@ public class FakeScreen extends Screen { public static final FakeScreen INSTANCE = new FakeScreen(); + private static MethodHandle handle; + + static { + try { + String name = FabricLoader.getInstance().getMappingResolver() + .mapMethodName("intermediary", "net.minecraft.class_437", "method_32635", + "(Ljava/util/List;Lnet/minecraft/class_5632;)V"); + Method m = Screen.class.getDeclaredMethod(name, List.class, TooltipData.class); + m.setAccessible(true); + handle = MethodHandles.lookup().unreflect(m); + } catch (Throwable e) { + e.printStackTrace(); + } + } protected FakeScreen() { super(EmiPort.literal("")); @@ -29,7 +47,7 @@ public List getTooltipComponentListFromItem(ItemStack stack) { Optional data = stack.getTooltipData(); if (data.isPresent()) { try { - list.add(TooltipComponent.of(data.get())); + handle.invokeWithArguments(list, data.get()); } catch (Throwable e) { e.printStackTrace(); } From 070d026dd859775fdb8fcb9107f2933b26e33469 Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Tue, 20 Jun 2023 19:09:28 -0500 Subject: [PATCH 12/67] Fix tooltip method for 1.19.4 --- .../main/java/dev/emi/emi/platform/forge/EmiAgnosForge.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/forge/src/main/java/dev/emi/emi/platform/forge/EmiAgnosForge.java b/forge/src/main/java/dev/emi/emi/platform/forge/EmiAgnosForge.java index 6e051477..cc2c7e72 100644 --- a/forge/src/main/java/dev/emi/emi/platform/forge/EmiAgnosForge.java +++ b/forge/src/main/java/dev/emi/emi/platform/forge/EmiAgnosForge.java @@ -26,8 +26,8 @@ import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.tooltip.TooltipComponent; +import net.minecraft.client.item.TooltipContext; import net.minecraft.client.render.item.ItemRenderer; import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.render.model.BasicBakedModel; @@ -216,7 +216,8 @@ protected List getAllModAuthorsAgnos() { @Override protected List getItemTooltipAgnos(ItemStack stack) { MinecraftClient client = MinecraftClient.getInstance(); - return ForgeHooksClient.gatherTooltipComponents(stack, Screen.getTooltipFromItem(client, stack), stack.getTooltipData(), 0, Integer.MAX_VALUE, Integer.MAX_VALUE, client.textRenderer); + List text = stack.getTooltip(client.player, client.options.advancedItemTooltips ? TooltipContext.Default.ADVANCED : TooltipContext.Default.BASIC);; + return ForgeHooksClient.gatherTooltipComponents(stack, text, stack.getTooltipData(), 0, Integer.MAX_VALUE, Integer.MAX_VALUE, null, client.textRenderer); } @Override From 8b9e2ec944cb0b341652d1e6091a9237b4f6c1a7 Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Tue, 20 Jun 2023 19:24:51 -0500 Subject: [PATCH 13/67] Remove tooltip view offset --- .../src/main/java/dev/emi/emi/screen/EmiScreenManager.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/xplat/src/main/java/dev/emi/emi/screen/EmiScreenManager.java b/xplat/src/main/java/dev/emi/emi/screen/EmiScreenManager.java index c74b9b9b..a78b0dbb 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/EmiScreenManager.java +++ b/xplat/src/main/java/dev/emi/emi/screen/EmiScreenManager.java @@ -696,10 +696,6 @@ private static void renderCurrentTooltip(EmiDrawContext context, int mouseX, int } if (cursor.isEmpty() && draggedStack.isEmpty()) { client.getProfiler().swap("hover"); - MatrixStack view = RenderSystem.getModelViewStack(); - view.push(); - view.translate(0, 0, 200); - RenderSystem.applyModelViewMatrix(); EmiIngredient hov = EmiStack.EMPTY; SidebarType sidebar = SidebarType.NONE; if (getHoveredStack(mouseX, mouseY, false) instanceof SidebarEmiStackInteraction sesi) { @@ -723,8 +719,6 @@ private static void renderCurrentTooltip(EmiDrawContext context, int mouseX, int } else { EmiRenderHelper.drawTooltip(screen, context, list, mouseX, mouseY); } - view.pop(); - RenderSystem.applyModelViewMatrix(); client.getProfiler().pop(); } lastStackTooltipRendered = null; From 3883b978cd65f71124c87b9b3b72ae4329d1a53a Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Thu, 13 Jul 2023 19:27:59 -0500 Subject: [PATCH 14/67] Revert "1.20 Tag render fix" This reverts commit 801e1aafadcd9ee4794b54f8f34069cda78a46b7. --- .../emi/emi/api/stack/TagEmiIngredient.java | 32 +++++++++++-------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/xplat/src/main/java/dev/emi/emi/api/stack/TagEmiIngredient.java b/xplat/src/main/java/dev/emi/emi/api/stack/TagEmiIngredient.java index 4500a22c..ec2a7f09 100644 --- a/xplat/src/main/java/dev/emi/emi/api/stack/TagEmiIngredient.java +++ b/xplat/src/main/java/dev/emi/emi/api/stack/TagEmiIngredient.java @@ -3,9 +3,9 @@ import java.util.List; import org.jetbrains.annotations.ApiStatus; -import org.joml.Matrix4f; import com.google.common.collect.Lists; +import com.mojang.blaze3d.systems.RenderSystem; import dev.emi.emi.EmiPort; import dev.emi.emi.EmiRenderHelper; @@ -28,6 +28,7 @@ import net.minecraft.client.render.item.ItemRenderer; import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.render.model.json.ModelTransformationMode; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.item.ItemStack; import net.minecraft.registry.tag.TagKey; import net.minecraft.util.Formatting; @@ -111,32 +112,37 @@ public void render(MatrixStack matrices, int x, int y, float delta, int flags) { } else { BakedModel model = ((BakedModelManagerAccessor) client.getBakedModelManager()).getModels() .getOrDefault(EmiTags.getCustomModel(key), client.getBakedModelManager().getMissingModel()); - - context.matrices().push(); - context.matrices().translate(x + 8, y + 8, 150); - context.matrices().multiplyPositionMatrix(new Matrix4f().scaling(1.0f, -1.0f, 1.0f)); - context.matrices().scale(16.0f, 16.0f, 16.0f); + + MatrixStack vs = RenderSystem.getModelViewStack(); + vs.push(); + vs.multiplyPositionMatrix(context.matrices().peek().getPositionMatrix()); + vs.translate(x, y, 100.0f); + vs.translate(8.0, 8.0, 0.0); + vs.scale(1.0f, -1.0f, 1.0f); + vs.scale(16.0f, 16.0f, 16.0f); + RenderSystem.applyModelViewMatrix(); - model.getTransformation().getTransformation(ModelTransformationMode.GUI).apply(false, context.matrices()); - context.matrices().translate(-0.5f, -0.5f, -0.5f); + MatrixStack ms = new MatrixStack(); + model.getTransformation().getTransformation(ModelTransformationMode.GUI).apply(false, ms); + ms.translate(-0.5, -0.5, -0.5); if (!model.isSideLit()) { DiffuseLighting.disableGuiDepthLighting(); } - VertexConsumerProvider.Immediate immediate = context.raw().getVertexConsumers(); - + VertexConsumerProvider.Immediate immediate = client.getBufferBuilders().getEntityVertexConsumers(); ((ItemRendererAccessor) client.getItemRenderer()) .invokeRenderBakedItemModel(model, - ItemStack.EMPTY, LightmapTextureManager.MAX_LIGHT_COORDINATE, OverlayTexture.DEFAULT_UV, context.matrices(), + ItemStack.EMPTY, LightmapTextureManager.MAX_LIGHT_COORDINATE, OverlayTexture.DEFAULT_UV, ms, ItemRenderer.getDirectItemGlintConsumer(immediate, TexturedRenderLayers.getItemEntityTranslucentCull(), true, false)); immediate.draw(); - + if (!model.isSideLit()) { DiffuseLighting.enableGuiDepthLighting(); } - context.matrices().pop(); + vs.pop(); + RenderSystem.applyModelViewMatrix(); } } if ((flags & RENDER_AMOUNT) != 0 && !key.registry().equals(EmiPort.getFluidRegistry().getKey())) { From a286bcca8247821464a9efe0429514ceda536810 Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Sat, 30 Sep 2023 19:21:10 -0500 Subject: [PATCH 15/67] Revert "Update to 1.20.2" This reverts commit 8b5e74bea47546045f9e3b1a25cad90bb4a2cc18. --- .../mixin/ClientPlayNetworkHandlerMixin.java | 8 ++- .../emi/platform/fabric/EmiClientFabric.java | 15 +---- .../emi/platform/forge/EmiClientForge.java | 2 +- .../dev/emi/emi/platform/forge/EmiForge.java | 2 +- .../emi/platform/forge/EmiPacketHandler.java | 56 +++++++++---------- gradle.properties | 12 ++-- xplat/src/main/java/dev/emi/emi/EmiPort.java | 7 +-- .../main/java/dev/emi/emi/VanillaPlugin.java | 2 +- .../handler/StonecuttingRecipeHandler.java | 3 +- .../java/dev/emi/emi/jemi/JemiPlugin.java | 4 +- .../dev/emi/emi/jemi/JemiRecipeHandler.java | 5 +- .../emi/mixin/CraftingResultSlotMixin.java | 3 +- .../dev/emi/emi/mixin/HandledScreenMixin.java | 19 +++++-- .../emi/emi/mixin/MinecraftClientMixin.java | 5 +- .../java/dev/emi/emi/mixin/MouseMixin.java | 2 +- .../dev/emi/emi/recipe/EmiCookingRecipe.java | 4 +- .../special/EmiSuspiciousStewRecipe.java | 2 +- .../java/dev/emi/emi/registry/EmiRecipes.java | 16 ------ .../emi/emi/registry/EmiStackProviders.java | 4 +- .../dev/emi/emi/runtime/EmiDrawContext.java | 4 +- .../java/dev/emi/emi/screen/BoMScreen.java | 2 +- .../dev/emi/emi/screen/ConfigEnumScreen.java | 5 -- .../emi/emi/screen/ConfigPresetScreen.java | 5 -- .../java/dev/emi/emi/screen/ConfigScreen.java | 5 -- .../dev/emi/emi/screen/DisabledToast.java | 4 +- .../java/dev/emi/emi/screen/RecipeScreen.java | 11 +--- .../emi/screen/widget/config/ListWidget.java | 2 +- 27 files changed, 81 insertions(+), 128 deletions(-) diff --git a/fabric/src/main/java/dev/emi/emi/mixin/ClientPlayNetworkHandlerMixin.java b/fabric/src/main/java/dev/emi/emi/mixin/ClientPlayNetworkHandlerMixin.java index 0b57dc57..57a7188d 100644 --- a/fabric/src/main/java/dev/emi/emi/mixin/ClientPlayNetworkHandlerMixin.java +++ b/fabric/src/main/java/dev/emi/emi/mixin/ClientPlayNetworkHandlerMixin.java @@ -3,14 +3,15 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.At.Shift; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.At.Shift; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import dev.emi.emi.runtime.EmiLog; import dev.emi.emi.runtime.EmiReloadManager; import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.network.packet.s2c.play.SynchronizeRecipesS2CPacket; +import net.minecraft.network.packet.s2c.play.SynchronizeTagsS2CPacket; /** * This entire mixin assumes that no one will modify how recipes and tags are synced. @@ -29,8 +30,9 @@ private void onSynchronizeRecipes(SynchronizeRecipesS2CPacket packet, CallbackIn EmiReloadManager.reloadRecipes(); } - @Inject(at = @At("RETURN"), method = "refreshTagBasedData") - private void refreshTagBasedData(CallbackInfo info) { + @Inject(at = @At(value = "INVOKE", target = "java/util/Map.forEach(Ljava/util/function/BiConsumer;)V", + shift = Shift.AFTER), method = "onSynchronizeTags") + private void onSynchronizeTags(SynchronizeTagsS2CPacket packet, CallbackInfo info) { EmiReloadManager.reloadTags(); } diff --git a/fabric/src/main/java/dev/emi/emi/platform/fabric/EmiClientFabric.java b/fabric/src/main/java/dev/emi/emi/platform/fabric/EmiClientFabric.java index 6b340ff9..de2a3aad 100644 --- a/fabric/src/main/java/dev/emi/emi/platform/fabric/EmiClientFabric.java +++ b/fabric/src/main/java/dev/emi/emi/platform/fabric/EmiClientFabric.java @@ -1,12 +1,9 @@ package dev.emi.emi.platform.fabric; -import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; import java.util.function.Function; -import com.google.common.collect.Lists; - import dev.emi.emi.data.EmiData; import dev.emi.emi.network.CommandS2CPacket; import dev.emi.emi.network.EmiChessPacket; @@ -17,7 +14,7 @@ import dev.emi.emi.registry.EmiTags; import io.netty.buffer.Unpooled; import net.fabricmc.api.ClientModInitializer; -import net.fabricmc.fabric.api.client.model.loading.v1.PreparableModelLoadingPlugin; +import net.fabricmc.fabric.api.client.model.ModelLoadingRegistry; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener; import net.fabricmc.fabric.api.resource.ResourceManagerHelper; @@ -53,14 +50,8 @@ public Identifier getFabricId() { }); }); - PreparableModelLoadingPlugin.>register((manager, executor) -> { - return CompletableFuture.supplyAsync(() -> { - List ids = Lists.newArrayList(); - EmiTags.registerTagModels(manager, id -> ids.add(id)); - return ids; - }, executor); - }, (ids, context) -> { - context.addModels(ids); + ModelLoadingRegistry.INSTANCE.registerModelProvider((manager, consumer) -> { + EmiTags.registerTagModels(manager, consumer); }); EmiNetwork.initClient(packet -> { diff --git a/forge/src/main/java/dev/emi/emi/platform/forge/EmiClientForge.java b/forge/src/main/java/dev/emi/emi/platform/forge/EmiClientForge.java index 6718155a..191c8e4a 100644 --- a/forge/src/main/java/dev/emi/emi/platform/forge/EmiClientForge.java +++ b/forge/src/main/java/dev/emi/emi/platform/forge/EmiClientForge.java @@ -36,7 +36,7 @@ public class EmiClientForge { public static void clientInit(FMLClientSetupEvent event) { StackBatcher.EXTRA_RENDER_LAYERS.addAll(Arrays.stream(ForgeRenderTypes.values()).map(f -> f.get()).toList()); EmiClient.init(); - EmiNetwork.initClient(packet -> EmiPacketHandler.CHANNEL.send(packet, MinecraftClient.getInstance().getNetworkHandler().getConnection())); + EmiNetwork.initClient(packet -> EmiPacketHandler.CHANNEL.sendToServer(packet)); MinecraftForge.EVENT_BUS.addListener(EmiClientForge::recipesReloaded); MinecraftForge.EVENT_BUS.addListener(EmiClientForge::tagsReloaded); MinecraftForge.EVENT_BUS.addListener(EmiClientForge::renderScreenForeground); diff --git a/forge/src/main/java/dev/emi/emi/platform/forge/EmiForge.java b/forge/src/main/java/dev/emi/emi/platform/forge/EmiForge.java index 0a5f4859..2ce7bcf9 100644 --- a/forge/src/main/java/dev/emi/emi/platform/forge/EmiForge.java +++ b/forge/src/main/java/dev/emi/emi/platform/forge/EmiForge.java @@ -18,7 +18,7 @@ public EmiForge() { EmiMain.init(); EmiPacketHandler.init(); EmiNetwork.initServer((player, packet) -> { - EmiPacketHandler.CHANNEL.send(packet, PacketDistributor.PLAYER.with(player)); + EmiPacketHandler.CHANNEL.send(PacketDistributor.PLAYER.with(() -> player), packet); }); MinecraftForge.EVENT_BUS.addListener(this::registerCommands); MinecraftForge.EVENT_BUS.addListener(this::playerConnect); diff --git a/forge/src/main/java/dev/emi/emi/platform/forge/EmiPacketHandler.java b/forge/src/main/java/dev/emi/emi/platform/forge/EmiPacketHandler.java index 080354a4..fafd7522 100644 --- a/forge/src/main/java/dev/emi/emi/platform/forge/EmiPacketHandler.java +++ b/forge/src/main/java/dev/emi/emi/platform/forge/EmiPacketHandler.java @@ -1,6 +1,8 @@ package dev.emi.emi.platform.forge; +import java.util.Optional; import java.util.function.BiConsumer; +import java.util.function.Supplier; import dev.emi.emi.network.CommandS2CPacket; import dev.emi.emi.network.CreateItemC2SPacket; @@ -10,50 +12,46 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.util.Identifier; -import net.minecraftforge.event.network.CustomPayloadEvent; -import net.minecraftforge.network.ChannelBuilder; import net.minecraftforge.network.NetworkDirection; -import net.minecraftforge.network.SimpleChannel; +import net.minecraftforge.network.NetworkEvent; +import net.minecraftforge.network.NetworkRegistry; +import net.minecraftforge.network.simple.SimpleChannel; public class EmiPacketHandler { - public static final SimpleChannel CHANNEL = ChannelBuilder.named(new Identifier("emi:emi")) - .acceptedVersions((status, version) -> true).simpleChannel(); + public static final SimpleChannel CHANNEL = NetworkRegistry.newSimpleChannel( + new Identifier("emi:emi"), () -> "0", NetworkRegistry.acceptMissingOr("0"), NetworkRegistry.acceptMissingOr("0")); public static void init() { int i = 0; - CHANNEL.messageBuilder(FillRecipeC2SPacket.class, i++, NetworkDirection.PLAY_TO_SERVER) - .encoder(FillRecipeC2SPacket::write).decoder(FillRecipeC2SPacket::new) - .consumerMainThread(serverHandler(FillRecipeC2SPacket::apply)).add(); - CHANNEL.messageBuilder(CreateItemC2SPacket.class, i++, NetworkDirection.PLAY_TO_SERVER) - .encoder(CreateItemC2SPacket::write).decoder(CreateItemC2SPacket::new) - .consumerMainThread(serverHandler(CreateItemC2SPacket::apply)).add(); - CHANNEL.messageBuilder(EmiChessPacket.C2S.class, i++, NetworkDirection.PLAY_TO_SERVER) - .encoder(EmiChessPacket.C2S::write).decoder(EmiChessPacket.C2S::new) - .consumerMainThread(serverHandler(EmiChessPacket.C2S::apply)).add(); + CHANNEL.registerMessage(i++, FillRecipeC2SPacket.class, FillRecipeC2SPacket::write, FillRecipeC2SPacket::new, + serverHandler(FillRecipeC2SPacket::apply), Optional.of(NetworkDirection.PLAY_TO_SERVER)); + CHANNEL.registerMessage(i++, CreateItemC2SPacket.class, CreateItemC2SPacket::write, CreateItemC2SPacket::new, + serverHandler(CreateItemC2SPacket::apply), Optional.of(NetworkDirection.PLAY_TO_SERVER)); + CHANNEL.registerMessage(i++, EmiChessPacket.C2S.class, EmiChessPacket.C2S::write, EmiChessPacket.C2S::new, + serverHandler(EmiChessPacket.C2S::apply), Optional.of(NetworkDirection.PLAY_TO_SERVER)); - CHANNEL.messageBuilder(PingS2CPacket.class, i++, NetworkDirection.PLAY_TO_CLIENT) - .encoder(PingS2CPacket::write).decoder(PingS2CPacket::new) - .consumerMainThread(clientHandler(PingS2CPacket::apply)).add(); - CHANNEL.messageBuilder(CommandS2CPacket.class, i++, NetworkDirection.PLAY_TO_CLIENT) - .encoder(CommandS2CPacket::write).decoder(CommandS2CPacket::new) - .consumerMainThread(clientHandler(CommandS2CPacket::apply)).add(); - CHANNEL.messageBuilder(EmiChessPacket.S2C.class, i++, NetworkDirection.PLAY_TO_CLIENT) - .encoder(EmiChessPacket.S2C::write).decoder(EmiChessPacket.S2C::new) - .consumerMainThread(clientHandler(EmiChessPacket.S2C::apply)).add(); + CHANNEL.registerMessage(i++, PingS2CPacket.class, PingS2CPacket::write, PingS2CPacket::new, + clientHandler(PingS2CPacket::apply), Optional.of(NetworkDirection.PLAY_TO_CLIENT)); + CHANNEL.registerMessage(i++, CommandS2CPacket.class, CommandS2CPacket::write, CommandS2CPacket::new, + clientHandler(CommandS2CPacket::apply), Optional.of(NetworkDirection.PLAY_TO_CLIENT)); + CHANNEL.registerMessage(i++, EmiChessPacket.S2C.class, EmiChessPacket.S2C::write, EmiChessPacket.S2C::new, + clientHandler(EmiChessPacket.S2C::apply), Optional.of(NetworkDirection.PLAY_TO_CLIENT)); } - private static BiConsumer serverHandler(BiConsumer handler) { + private static BiConsumer> serverHandler(BiConsumer handler) { return (t, context) -> { - handler.accept(t, context.getSender()); - context.setPacketHandled(true); + handler.accept(t, context.get().getSender()); + context.get().setPacketHandled(true); }; } - private static BiConsumer clientHandler(BiConsumer handler) { + private static BiConsumer> clientHandler(BiConsumer handler) { return (t, context) -> { MinecraftClient client = MinecraftClient.getInstance(); - handler.accept(t, client.player); - context.setPacketHandled(true); + client.execute(() -> { + handler.accept(t, client.player); + }); + context.get().setPacketHandled(true); }; } } diff --git a/gradle.properties b/gradle.properties index c9c30cff..0e17fcb2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ org.gradle.jvmargs=-Xmx2048M -minecraft_version=1.20.2 +minecraft_version=1.20.1 enabled_platforms=fabric,forge archives_base_name=emi @@ -9,11 +9,11 @@ maven_group=dev.emi architectury_version=4.9.83 -yarn_mappings=1.20.2+build.2 +yarn_mappings=1.20.1+build.2 -fabric_loader_version=0.14.22 -fabric_api_version=0.89.2+1.20.2 +fabric_loader_version=0.14.21 +fabric_api_version=0.83.1+1.20.1 -forge_version=1.20.2-48.0.1 +forge_version=1.20.1-47.0.1 -jei_version=jei-1.20.2-fabric:16.0.0.28 +jei_version=jei-1.20-fabric:14.0.0.5 diff --git a/xplat/src/main/java/dev/emi/emi/EmiPort.java b/xplat/src/main/java/dev/emi/emi/EmiPort.java index 44a15f1d..19adee3f 100644 --- a/xplat/src/main/java/dev/emi/emi/EmiPort.java +++ b/xplat/src/main/java/dev/emi/emi/EmiPort.java @@ -11,7 +11,6 @@ import com.mojang.blaze3d.systems.RenderSystem; -import dev.emi.emi.registry.EmiRecipes; import net.minecraft.block.Block; import net.minecraft.block.TallFlowerBlock; import net.minecraft.block.entity.BannerPattern; @@ -105,7 +104,7 @@ public static BannerPattern.Patterns addRandomBanner(BannerPattern.Patterns patt public static boolean canTallFlowerDuplicate(TallFlowerBlock tallFlowerBlock) { try { - return tallFlowerBlock.isFertilizable(null, null, null) && tallFlowerBlock.canGrow(null, null, null, null); + return tallFlowerBlock.isFertilizable(null, null, null, true) && tallFlowerBlock.canGrow(null, null, null, null); } catch(Exception e) { return false; } @@ -167,7 +166,7 @@ public static ButtonWidget newButton(int x, int y, int w, int h, Text name, Pres public static ItemStack getOutput(Recipe recipe) { MinecraftClient client = MinecraftClient.getInstance(); - return recipe.getResult(client.world.getRegistryManager()); + return recipe.getOutput(client.world.getRegistryManager()); } public static void focus(TextFieldWidget widget, boolean focused) { @@ -181,6 +180,6 @@ public static Stream getDisabledItems() { } public static Identifier getId(Recipe recipe) { - return EmiRecipes.recipeIds.get(recipe); + return recipe.getId(); } } diff --git a/xplat/src/main/java/dev/emi/emi/VanillaPlugin.java b/xplat/src/main/java/dev/emi/emi/VanillaPlugin.java index e87f23f5..b8c7d596 100644 --- a/xplat/src/main/java/dev/emi/emi/VanillaPlugin.java +++ b/xplat/src/main/java/dev/emi/emi/VanillaPlugin.java @@ -809,7 +809,7 @@ private static Identifier synthetic(String type, String name) { } private static > Iterable getRecipes(EmiRegistry registry, RecipeType type) { - return registry.getRecipeManager().listAllOfType(type).stream().map(e -> e.value())::iterator; + return registry.getRecipeManager().listAllOfType(type).stream()::iterator; } private static void safely(String name, Runnable runnable) { diff --git a/xplat/src/main/java/dev/emi/emi/handler/StonecuttingRecipeHandler.java b/xplat/src/main/java/dev/emi/emi/handler/StonecuttingRecipeHandler.java index 793ad09f..d0913e9d 100644 --- a/xplat/src/main/java/dev/emi/emi/handler/StonecuttingRecipeHandler.java +++ b/xplat/src/main/java/dev/emi/emi/handler/StonecuttingRecipeHandler.java @@ -14,7 +14,6 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.inventory.Inventory; import net.minecraft.inventory.SimpleInventory; -import net.minecraft.recipe.RecipeEntry; import net.minecraft.recipe.RecipeType; import net.minecraft.recipe.StonecuttingRecipe; import net.minecraft.screen.StonecutterScreenHandler; @@ -56,7 +55,7 @@ public boolean craft(EmiRecipe recipe, EmiCraftContext MinecraftClient client = MinecraftClient.getInstance(); World world = client.world; Inventory inv = new SimpleInventory(recipe.getInputs().get(0).getEmiStacks().get(0).getItemStack()); - List recipes = world.getRecipeManager().getAllMatches(RecipeType.STONECUTTING, inv, world).stream().map(RecipeEntry::value).toList(); + List recipes = world.getRecipeManager().getAllMatches(RecipeType.STONECUTTING, inv, world); for (int i = 0; i < recipes.size(); i++) { if (EmiPort.getId(recipes.get(i)) != null && EmiPort.getId(recipes.get(i)).equals(recipe.getId())) { StonecutterScreenHandler sh = context.getScreenHandler(); diff --git a/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java b/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java index cd7bdb4a..f3a6f9ec 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java @@ -68,7 +68,6 @@ import net.minecraft.fluid.Fluid; import net.minecraft.item.Item; import net.minecraft.recipe.CraftingRecipe; -import net.minecraft.recipe.RecipeEntry; import net.minecraft.screen.ScreenHandler; import net.minecraft.text.MutableText; import net.minecraft.text.StringVisitable; @@ -304,8 +303,7 @@ private void addInfoRecipes(EmiRegistry registry, IRecipeCategory category) { Set replaced = Sets.newHashSet(); Set replacements = Sets.newHashSet(); - for (RecipeEntry entry : registry.getRecipeManager().listAllOfType(net.minecraft.recipe.RecipeType.CRAFTING)) { - CraftingRecipe recipe = entry.value(); + for (CraftingRecipe recipe : registry.getRecipeManager().listAllOfType(net.minecraft.recipe.RecipeType.CRAFTING)) { try { if (category.isHandled(recipe)) { JemiRecipeLayoutBuilder builder = new JemiRecipeLayoutBuilder(); diff --git a/xplat/src/main/java/dev/emi/emi/jemi/JemiRecipeHandler.java b/xplat/src/main/java/dev/emi/emi/jemi/JemiRecipeHandler.java index 8b1eb4e8..9387dd24 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/JemiRecipeHandler.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/JemiRecipeHandler.java @@ -28,7 +28,6 @@ import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.recipe.Recipe; -import net.minecraft.recipe.RecipeEntry; import net.minecraft.recipe.RecipeManager; import net.minecraft.screen.ScreenHandler; @@ -158,7 +157,7 @@ private R getRawRecipe(EmiRecipe recipe) { } } if (manager != null) { - Optional> opt = manager.get(recipe.getId()).map(RecipeEntry::value); + Optional> opt = manager.get(recipe.getId()); if (opt.isPresent()) { Recipe r = opt.get(); if (type.getRecipeClass().isAssignableFrom(r.getClass())) { @@ -168,7 +167,7 @@ private R getRawRecipe(EmiRecipe recipe) { } } if (manager != null) { - Optional> opt = manager.get(recipe.getId()).map(RecipeEntry::value); + Optional> opt = manager.get(recipe.getId()); if (opt.isPresent()) { return (R) opt.get(); } diff --git a/xplat/src/main/java/dev/emi/emi/mixin/CraftingResultSlotMixin.java b/xplat/src/main/java/dev/emi/emi/mixin/CraftingResultSlotMixin.java index c68d5e62..05fe9f72 100644 --- a/xplat/src/main/java/dev/emi/emi/mixin/CraftingResultSlotMixin.java +++ b/xplat/src/main/java/dev/emi/emi/mixin/CraftingResultSlotMixin.java @@ -17,7 +17,6 @@ import net.minecraft.inventory.RecipeInputInventory; import net.minecraft.item.ItemStack; import net.minecraft.recipe.CraftingRecipe; -import net.minecraft.recipe.RecipeEntry; import net.minecraft.recipe.RecipeType; import net.minecraft.screen.slot.CraftingResultSlot; import net.minecraft.world.World; @@ -33,7 +32,7 @@ public class CraftingResultSlotMixin { private void onCrafted(ItemStack stack, CallbackInfo info) { World world = player.getWorld(); if (world.isClient) { - Optional opt = world.getRecipeManager().getFirstMatch(RecipeType.CRAFTING, input, world).map(RecipeEntry::value); + Optional opt = world.getRecipeManager().getFirstMatch(RecipeType.CRAFTING, input, world); if (opt.isPresent()) { EmiRecipe recipe = EmiApi.getRecipeManager().getRecipe(EmiPort.getId(opt.get())); if (recipe != null) { diff --git a/xplat/src/main/java/dev/emi/emi/mixin/HandledScreenMixin.java b/xplat/src/main/java/dev/emi/emi/mixin/HandledScreenMixin.java index 6007a367..9abf3723 100644 --- a/xplat/src/main/java/dev/emi/emi/mixin/HandledScreenMixin.java +++ b/xplat/src/main/java/dev/emi/emi/mixin/HandledScreenMixin.java @@ -1,6 +1,7 @@ package dev.emi.emi.mixin; import org.spongepowered.asm.mixin.Dynamic; +import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -17,6 +18,7 @@ import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.client.gui.screen.recipebook.RecipeBookProvider; +import net.minecraft.client.util.Window; @Mixin(HandledScreen.class) public abstract class HandledScreenMixin extends Screen implements EmiScreen { @@ -25,14 +27,19 @@ public abstract class HandledScreenMixin extends Screen implements EmiScreen { private HandledScreenMixin() { super(null); } + @Intrinsic @Override + public void renderBackground(DrawContext raw) { + super.renderBackground(raw); + } + @Dynamic - @Inject(at = @At(value = "INVOKE", - target = "net/minecraft/client/gui/screen/Screen.renderBackground(Lnet/minecraft/client/gui/DrawContext;IIF)V", - shift = Shift.AFTER), - method = "renderBackground(Lnet/minecraft/client/gui/DrawContext;IIF)V") - private void renderBackground(DrawContext raw, int mouseX, int mouseY, float delta, CallbackInfo info) { + @Inject(at = @At("RETURN"), method = "renderBackground(Lnet/minecraft/client/gui/DrawContext;)V") + private void renderBackground(DrawContext raw, CallbackInfo info) { EmiDrawContext context = EmiDrawContext.wrap(raw); - EmiScreenManager.drawBackground(context, mouseX, mouseY, delta); + Window window = client.getWindow(); + int mouseX = (int) (client.mouse.getX() * window.getScaledWidth() / window.getWidth()); + int mouseY = (int) (client.mouse.getY() * window.getScaledHeight() / window.getHeight()); + EmiScreenManager.drawBackground(context, mouseX, mouseY, client.getTickDelta()); } @Inject(at = @At(value = "INVOKE", diff --git a/xplat/src/main/java/dev/emi/emi/mixin/MinecraftClientMixin.java b/xplat/src/main/java/dev/emi/emi/mixin/MinecraftClientMixin.java index b17151e0..0aa0c312 100644 --- a/xplat/src/main/java/dev/emi/emi/mixin/MinecraftClientMixin.java +++ b/xplat/src/main/java/dev/emi/emi/mixin/MinecraftClientMixin.java @@ -6,7 +6,6 @@ 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.Coerce; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @@ -22,8 +21,8 @@ public class MinecraftClientMixin { @Shadow public ClientWorld world; - @Inject(at = @At("RETURN"), method = "reloadResources(ZLnet/minecraft/client/MinecraftClient$LoadingContext;)Ljava/util/concurrent/CompletableFuture;") - private void reloadResources(boolean force, @Coerce Object loadingContext, CallbackInfoReturnable> info) { + @Inject(at = @At("RETURN"), method = "reloadResources(Z)Ljava/util/concurrent/CompletableFuture;") + private void reloadResources(boolean force, CallbackInfoReturnable> info) { CompletableFuture future = info.getReturnValue(); if (future != null) { future.thenRunAsync(() -> { diff --git a/xplat/src/main/java/dev/emi/emi/mixin/MouseMixin.java b/xplat/src/main/java/dev/emi/emi/mixin/MouseMixin.java index 9f135e59..a3655b27 100644 --- a/xplat/src/main/java/dev/emi/emi/mixin/MouseMixin.java +++ b/xplat/src/main/java/dev/emi/emi/mixin/MouseMixin.java @@ -81,7 +81,7 @@ private void onMouseDragged(long window, double x, double y, CallbackInfo info) } @Inject(at = @At(value = "INVOKE", target = - "net/minecraft/client/gui/screen/Screen.mouseScrolled(DDDD)Z"), + "net/minecraft/client/gui/screen/Screen.mouseScrolled(DDD)Z"), method = "onMouseScroll(JDD)V", cancellable = true) private void onMouseScrolled(long window, double horizontal, double vertical, CallbackInfo info) { try { diff --git a/xplat/src/main/java/dev/emi/emi/recipe/EmiCookingRecipe.java b/xplat/src/main/java/dev/emi/emi/recipe/EmiCookingRecipe.java index 6b0cc173..0d4b5de6 100644 --- a/xplat/src/main/java/dev/emi/emi/recipe/EmiCookingRecipe.java +++ b/xplat/src/main/java/dev/emi/emi/recipe/EmiCookingRecipe.java @@ -70,8 +70,8 @@ public int getDisplayHeight() { @Override public void addWidgets(WidgetHolder widgets) { - widgets.addFillingArrow(24, 5, 50 * recipe.getCookingTime()).tooltip((mx, my) -> { - return List.of(TooltipComponent.of(EmiPort.ordered(EmiPort.translatable("emi.cooking.time", recipe.getCookingTime() / 20f)))); + widgets.addFillingArrow(24, 5, 50 * recipe.getCookTime()).tooltip((mx, my) -> { + return List.of(TooltipComponent.of(EmiPort.ordered(EmiPort.translatable("emi.cooking.time", recipe.getCookTime() / 20f)))); }); if (infiniBurn) { widgets.addTexture(EmiTexture.FULL_FLAME, 1, 24); diff --git a/xplat/src/main/java/dev/emi/emi/recipe/special/EmiSuspiciousStewRecipe.java b/xplat/src/main/java/dev/emi/emi/recipe/special/EmiSuspiciousStewRecipe.java index 351b2b21..7b8a9b91 100644 --- a/xplat/src/main/java/dev/emi/emi/recipe/special/EmiSuspiciousStewRecipe.java +++ b/xplat/src/main/java/dev/emi/emi/recipe/special/EmiSuspiciousStewRecipe.java @@ -50,7 +50,7 @@ public SlotWidget getOutputWidget(int x, int y) { return new GeneratedSlotWidget(r -> { FlowerBlock block = (FlowerBlock) ((BlockItem) getFlower(r)).getBlock(); ItemStack stack = new ItemStack(Items.SUSPICIOUS_STEW); - SuspiciousStewItem.addEffectsToStew(stack, block.getStewEffects()); + SuspiciousStewItem.addEffectToStew(stack, block.getEffectInStew(), block.getEffectInStewDuration()); return EmiStack.of(stack); }, unique, x, y); } diff --git a/xplat/src/main/java/dev/emi/emi/registry/EmiRecipes.java b/xplat/src/main/java/dev/emi/emi/registry/EmiRecipes.java index a2446694..57663bb8 100644 --- a/xplat/src/main/java/dev/emi/emi/registry/EmiRecipes.java +++ b/xplat/src/main/java/dev/emi/emi/registry/EmiRecipes.java @@ -34,11 +34,7 @@ import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap; import it.unimi.dsi.fastutil.objects.ObjectArraySet; -import net.minecraft.client.MinecraftClient; import net.minecraft.client.resource.language.I18n; -import net.minecraft.recipe.Recipe; -import net.minecraft.recipe.RecipeEntry; -import net.minecraft.recipe.RecipeManager; import net.minecraft.util.Identifier; public class EmiRecipes { @@ -51,8 +47,6 @@ public class EmiRecipes { private static List recipes = Lists.newArrayList(); public static Map> byWorkstation = Maps.newHashMap(); - - public static Map, Identifier> recipeIds = Map.of(); public static void clear() { lateRecipes.clear(); @@ -62,16 +56,6 @@ public static void clear() { recipes.clear(); byWorkstation.clear(); manager = Manager.EMPTY; - MinecraftClient client = MinecraftClient.getInstance(); - if (client.world != null) { - RecipeManager manager = client.world.getRecipeManager(); - recipeIds = Maps.newIdentityHashMap(); - if (manager != null) { - for (RecipeEntry entry : manager.values()) { - recipeIds.put(entry.value(), entry.id()); - } - } - } } public static void bake() { diff --git a/xplat/src/main/java/dev/emi/emi/registry/EmiStackProviders.java b/xplat/src/main/java/dev/emi/emi/registry/EmiStackProviders.java index f5855015..c5dc976b 100644 --- a/xplat/src/main/java/dev/emi/emi/registry/EmiStackProviders.java +++ b/xplat/src/main/java/dev/emi/emi/registry/EmiStackProviders.java @@ -19,7 +19,6 @@ import net.minecraft.inventory.RecipeInputInventory; import net.minecraft.item.ItemStack; import net.minecraft.recipe.CraftingRecipe; -import net.minecraft.recipe.RecipeEntry; import net.minecraft.recipe.RecipeType; import net.minecraft.screen.slot.CraftingResultSlot; import net.minecraft.screen.slot.Slot; @@ -61,8 +60,7 @@ public static EmiStackInteraction getStackAt(Screen screen, int x, int y, boolea RecipeInputInventory inv = ((CraftingResultSlotAccessor) craf).getInput(); MinecraftClient client = MinecraftClient.getInstance(); List list - = client.world.getRecipeManager().getAllMatches(RecipeType.CRAFTING, inv, client.world) - .stream().map(RecipeEntry::value).toList(); + = client.world.getRecipeManager().getAllMatches(RecipeType.CRAFTING, inv, client.world); if (!list.isEmpty()) { Identifier id = EmiPort.getId(list.get(0)); EmiRecipe recipe = EmiApi.getRecipeManager().getRecipe(id); diff --git a/xplat/src/main/java/dev/emi/emi/runtime/EmiDrawContext.java b/xplat/src/main/java/dev/emi/emi/runtime/EmiDrawContext.java index 1280976b..ad77952e 100644 --- a/xplat/src/main/java/dev/emi/emi/runtime/EmiDrawContext.java +++ b/xplat/src/main/java/dev/emi/emi/runtime/EmiDrawContext.java @@ -1,5 +1,7 @@ package dev.emi.emi.runtime; +import com.mojang.blaze3d.systems.RenderSystem; + import dev.emi.emi.EmiPort; import dev.emi.emi.api.stack.EmiIngredient; import net.minecraft.client.MinecraftClient; @@ -108,7 +110,7 @@ public void setColor(float r, float g, float b) { } public void setColor(float r, float g, float b, float a) { - raw().setShaderColor(r, g, b, a); + RenderSystem.setShaderColor(r, g, b, a); } public void drawStack(EmiIngredient stack, int x, int y) { diff --git a/xplat/src/main/java/dev/emi/emi/screen/BoMScreen.java b/xplat/src/main/java/dev/emi/emi/screen/BoMScreen.java index 75af77cb..2bef1dc8 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/BoMScreen.java +++ b/xplat/src/main/java/dev/emi/emi/screen/BoMScreen.java @@ -496,7 +496,7 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { } @Override - public boolean mouseScrolled(double mouseX, double mouseY, double horizontal, double amount) { + public boolean mouseScrolled(double mouseX, double mouseY, double amount) { scrollAcc += amount; amount = (int) scrollAcc; scrollAcc %= 1; diff --git a/xplat/src/main/java/dev/emi/emi/screen/ConfigEnumScreen.java b/xplat/src/main/java/dev/emi/emi/screen/ConfigEnumScreen.java index c894bf99..d58103ff 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/ConfigEnumScreen.java +++ b/xplat/src/main/java/dev/emi/emi/screen/ConfigEnumScreen.java @@ -62,11 +62,6 @@ public void render(DrawContext raw, int mouseX, int mouseY, float delta) { } } - @Override - public void renderBackground(DrawContext context, int mouseX, int mouseY, float delta) { - // Prevent double background draw - } - @Override public void close() { MinecraftClient.getInstance().setScreen(last); diff --git a/xplat/src/main/java/dev/emi/emi/screen/ConfigPresetScreen.java b/xplat/src/main/java/dev/emi/emi/screen/ConfigPresetScreen.java index 985cec15..1a2fae30 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/ConfigPresetScreen.java +++ b/xplat/src/main/java/dev/emi/emi/screen/ConfigPresetScreen.java @@ -84,11 +84,6 @@ public void render(DrawContext raw, int mouseX, int mouseY, float delta) { } } - @Override - public void renderBackground(DrawContext context, int mouseX, int mouseY, float delta) { - // Prevent double background draw - } - @Override public void close() { MinecraftClient.getInstance().setScreen(last); diff --git a/xplat/src/main/java/dev/emi/emi/screen/ConfigScreen.java b/xplat/src/main/java/dev/emi/emi/screen/ConfigScreen.java index de776c98..0c85588e 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/ConfigScreen.java +++ b/xplat/src/main/java/dev/emi/emi/screen/ConfigScreen.java @@ -373,11 +373,6 @@ public void render(DrawContext raw, int mouseX, int mouseY, float delta) { EmiRenderHelper.drawTooltip(this, context, list.getHoveredEntry().getTooltip(mouseX, mouseY), mouseX, mouseY, Math.min(width / 2 - 16, maxWidth)); } } - - @Override - public void renderBackground(DrawContext context, int mouseX, int mouseY, float delta) { - // Prevent double background draw - } @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { diff --git a/xplat/src/main/java/dev/emi/emi/screen/DisabledToast.java b/xplat/src/main/java/dev/emi/emi/screen/DisabledToast.java index a1b15e3e..c9cf5a4f 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/DisabledToast.java +++ b/xplat/src/main/java/dev/emi/emi/screen/DisabledToast.java @@ -6,16 +6,14 @@ import net.minecraft.client.gui.DrawContext; import net.minecraft.client.toast.Toast; import net.minecraft.client.toast.ToastManager; -import net.minecraft.util.Identifier; public class DisabledToast implements Toast { - private static final Identifier TEXTURE = new Identifier("toast/advancement"); @Override public Visibility draw(DrawContext raw, ToastManager manager, long time) { EmiDrawContext context = EmiDrawContext.wrap(raw); context.resetColor(); - raw.drawGuiTexture(TEXTURE, 0, 0, this.getWidth(), this.getHeight()); + context.drawTexture(TEXTURE, 0, 0, 0, 0, this.getWidth(), this.getHeight()); context.drawCenteredText(EmiPort.translatable("emi.disabled"), getWidth() / 2, 7); context.drawCenteredText(EmiConfig.toggleVisibility.getBindText(), getWidth() / 2, 18); if (time > 8_000 || EmiConfig.enabled) { diff --git a/xplat/src/main/java/dev/emi/emi/screen/RecipeScreen.java b/xplat/src/main/java/dev/emi/emi/screen/RecipeScreen.java index 352288cd..361762f4 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/RecipeScreen.java +++ b/xplat/src/main/java/dev/emi/emi/screen/RecipeScreen.java @@ -166,7 +166,7 @@ private void setRecipePageWidth(int width) { @Override public void render(DrawContext raw, int mouseX, int mouseY, float delta) { EmiDrawContext context = EmiDrawContext.wrap(raw); - this.renderInGameBackground(context.raw()); + this.renderBackground(context.raw()); context.resetColor(); EmiRenderHelper.drawNinePatch(context, TEXTURE, x, y, backgroundWidth, backgroundHeight, 0, 0, 4, 1); @@ -283,11 +283,6 @@ public void render(DrawContext raw, int mouseX, int mouseY, float delta) { } } - @Override - public void renderBackground(DrawContext context, int mouseX, int mouseY, float delta) { - // Prevent double background draw - } - public EmiIngredient getHoveredStack() { if (hoveredWidget instanceof SlotWidget slot) { return slot.getStack(); @@ -499,7 +494,7 @@ public boolean mouseDragged(double mouseX, double mouseY, int button, double del } @Override - public boolean mouseScrolled(double mouseX, double mouseY, double horizontal, double amount) { + public boolean mouseScrolled(double mouseX, double mouseY, double amount) { if (EmiScreenManager.mouseScrolled(mouseX, mouseY, amount)) { return true; } else if (mouseX > x && mouseX < x + backgroundWidth && mouseY < x + backgroundHeight) { @@ -512,7 +507,7 @@ public boolean mouseScrolled(double mouseX, double mouseY, double horizontal, do setPage(tabPage, tab, page - sa); } } - return super.mouseScrolled(mouseX, mouseY, horizontal, amount); + return super.mouseScrolled(mouseX, mouseY, amount); } @Override diff --git a/xplat/src/main/java/dev/emi/emi/screen/widget/config/ListWidget.java b/xplat/src/main/java/dev/emi/emi/screen/widget/config/ListWidget.java index e922ff4b..e63412a1 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/widget/config/ListWidget.java +++ b/xplat/src/main/java/dev/emi/emi/screen/widget/config/ListWidget.java @@ -388,7 +388,7 @@ public boolean mouseDragged(double mouseX, double mouseY, int button, double del } @Override - public boolean mouseScrolled(double mouseX, double mouseY, double horizontal, double amount) { + public boolean mouseScrolled(double mouseX, double mouseY, double amount) { this.setScrollAmount(this.getScrollAmount() - amount * 22); return true; } From a784227641ebac70ae3840a16c0692ba2fb54d0b Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Sat, 7 Oct 2023 23:05:35 -0500 Subject: [PATCH 16/67] Revert 1.20.2 specific change --- .../dev/emi/emi/mixin/SynchronizeRecipesS2CPacketMixin.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/fabric/src/main/java/dev/emi/emi/mixin/SynchronizeRecipesS2CPacketMixin.java b/fabric/src/main/java/dev/emi/emi/mixin/SynchronizeRecipesS2CPacketMixin.java index 8c66f6f9..704bca94 100644 --- a/fabric/src/main/java/dev/emi/emi/mixin/SynchronizeRecipesS2CPacketMixin.java +++ b/fabric/src/main/java/dev/emi/emi/mixin/SynchronizeRecipesS2CPacketMixin.java @@ -10,15 +10,14 @@ import net.minecraft.network.PacketByteBuf; import net.minecraft.network.packet.s2c.play.SynchronizeRecipesS2CPacket; import net.minecraft.recipe.Recipe; -import net.minecraft.recipe.RecipeEntry; import net.minecraft.util.Identifier; @Mixin(SynchronizeRecipesS2CPacket.class) public class SynchronizeRecipesS2CPacketMixin { @Inject(at = @At("RETURN"), method = "readRecipe", locals = LocalCapture.CAPTURE_FAILHARD) - private static void readRecipe(PacketByteBuf buf, CallbackInfoReturnable>> info, Identifier serializer, Identifier id) { - RecipeEntry> recipe = info.getReturnValue(); + private static void readRecipe(PacketByteBuf buf, CallbackInfoReturnable> info, Identifier serializer, Identifier id) { + Recipe recipe = info.getReturnValue(); if (recipe == null) { EmiLog.error("Recipe " + id + " was deserialized as null using recipe serializer " + serializer + ", this is breaking vanilla recipe sync, and will prevent EMI from loading recipes"); From 73158862940e42de83dfca3f5d01c80522727816 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BE=8A=E7=BE=BD=E3=81=A1=E3=82=83=E3=82=93?= <108245985+u7f8au7fbd@users.noreply.github.com> Date: Tue, 24 Oct 2023 13:07:23 +0900 Subject: [PATCH 17/67] Add ja_jp.lang (#335) --- .../main/resources/assets/emi/lang/ja_jp.json | 656 ++++++++++++++++++ 1 file changed, 656 insertions(+) create mode 100644 xplat/src/main/resources/assets/emi/lang/ja_jp.json diff --git a/xplat/src/main/resources/assets/emi/lang/ja_jp.json b/xplat/src/main/resources/assets/emi/lang/ja_jp.json new file mode 100644 index 00000000..11e2043f --- /dev/null +++ b/xplat/src/main/resources/assets/emi/lang/ja_jp.json @@ -0,0 +1,656 @@ +{ + "key.keyboard.control": "Ctrl", + "key.keyboard.alt": "Alt", + "key.keyboard.shift": "Shift", + "key.emi.toggle_visibility": "表示の切り替え", + "key.emi.focus_search": "検索欄にフォーカス", + "key.emi.clear_search": "検索履歴をクリア", + "key.emi.view_recipes": "レシピを表示", + "key.emi.view_uses": "用途を表示", + "key.emi.favorite": "お気に入り", + "key.emi.set_default": "デフォルトに設定", + "key.emi.default_stack": "デフォルトのスタック", + "key.emi.view_stack_tree": "スタックツリーの表示", + "key.emi.view_tree": "レシピツリーの表示", + "key.emi.back": "戻る", + "key.emi.forward": "次へ", + "key.emi.craft_one": "1つクラフトする", + "key.emi.craft_all": "最大個数クラフトする", + "key.emi.craft_one_to_inventory": "1つをインベントリにクラフト", + "key.emi.craft_all_to_inventory": "最大個数をインベントリにクラフト", + "key.emi.craft_one_to_cursor": "カーソルに1つクラフトする", + "key.emi.show_craft": "クラフトを表示", + "key.emi.cheat_one_to_inventory": "チートから1つインベントリへ", + "key.emi.cheat_stack_to_inventory": "チートから1スタックインベントリへ", + "key.emi.cheat_one_to_cursor": "チートからカーソルへ", + "key.emi.cheat_stack_to_cursor": "チートから1スタックインベントリへ", + "key.emi.delete_cursor_stack": "カーソルから1スタック削除", + "key.emi.hide_stack": "スタックを非表示", + "key.emi.hide_stack_by_id": "スタックIDの非表示", + "emi.help_level.verbose": "詳細", + "emi.help_level.normal": "通常", + "emi.help_level.none": "無し", + "emi.align.horizontal.left": "左", + "emi.align.horizontal.center": "中央", + "emi.align.horizontal.right": "右", + "emi.align.vertical.top": "上", + "emi.align.vertical.center": "中央", + "emi.align.vertical.bottom": "下", + "emi.sidebar.type.none": "無し", + "emi.sidebar.type.index": "インデックス", + "emi.sidebar.type.craftables": "クラフト可能", + "emi.sidebar.type.favorites": "お気に入り", + "emi.sidebar.type.lookup_history": "検索履歴", + "emi.sidebar.type.craft_history": "クラフト履歴", + "emi.sidebar.type.chess": "チェス", + "emi.sidebar.theme.transparent": "透明度", + "emi.sidebar.theme.vanilla": "バニラ", + "emi.sidebar.theme.modern": "モダン", + "emi.header.visible": "可視", + "emi.header.invisible": "不可視", + "emi.sidebar.size.columns": "列", + "emi.sidebar.size.rows": "行", + "emi.sidebar.margins.top": "上", + "emi.sidebar.margins.right": "右", + "emi.sidebar.margins.bottom": "下", + "emi.sidebar.margins.left": "左", + "emi.sidebar.none": "無し", + "emi.sidebar.left": "左", + "emi.sidebar.right": "右", + "emi.sidebar.top": "上", + "emi.sidebar.bottom": "下", + "emi.effect_location.top": "上", + "emi.effect_location.left_compressed": "左(圧縮済み)", + "emi.effect_location.right_compressed": "右(圧縮済み)", + "emi.effect_location.left": "左", + "emi.effect_location.right": "右", + "emi.recipe_book_action.default": "デフォルト", + "emi.recipe_book_action.toggle_craftables": "作業台の切り替え", + "emi.recipe_book_action.toggle_visibility": "表示の切り替え", + "config.emi.group.general": "一般", + "config.emi.group.general.search": "検索", + "config.emi.group.ui": "UI", + "config.emi.group.ui.mod_id": "Mod ID", + "config.emi.group.ui.recipe_screen": "レシピ画面", + "config.emi.group.ui.recipe_buttons": "レシピボタン", + "config.emi.group.ui.left_sidebar": "左サイドバー", + "config.emi.group.ui.right_sidebar": "右サイドバー", + "config.emi.group.ui.top_sidebar": "上サイドバー", + "config.emi.group.ui.bottom_sidebar": "下サイドバー", + "config.emi.group.binds": "結合", + "config.emi.group.dev": "開発者", + "config.emi.group.binds.crafts": "クラフト", + "config.emi.group.binds.cheats": "チート", + "config.emi.general.enabled": "有効", + "config.emi.general.cheat_mode": "チートモード", + "config.emi.general.help_level": "ヘルプレベル", + "config.emi.general.search_tooltip_by_default": "デフォルトでツールチップを検索", + "config.emi.general.search_mod_name_by_default": "デフォルトでMod名を検索", + "config.emi.general.search_tags_by_default": "デフォルトでタグを検索", + "config.emi.ui.effect_location": "効果の場所", + "config.emi.ui.center_search_bar": "中央検索バー", + "config.emi.ui.show_hover_overlay": "ボタン判定の表示", + "config.emi.ui.append_mod_id": "Mod IDをつけ添える", + "config.emi.ui.append_item_mod_id": "アイテムIDを付け添える", + "config.emi.ui.recipe_book_action": "レシピ本の動作", + "config.emi.ui.search_sidebar_focus": "サイドバーフォーカスを検索", + "config.emi.ui.empty_search_sidebar_focus": "空の検索サイドバーをフォーカス", + "config.emi.ui.left_sidebar_pages": "ページ", + "config.emi.ui.left_sidebar_subpanels": "サブパネル", + "config.emi.ui.left_sidebar_size": "サイズ", + "config.emi.ui.left_sidebar_margins": "マージン", + "config.emi.ui.left_sidebar_align": "配置", + "config.emi.ui.left_sidebar_header": "ヘッダー", + "config.emi.ui.left_sidebar_theme": "テーマ", + "config.emi.ui.right_sidebar_pages": "ページ", + "config.emi.ui.right_sidebar_subpanels": "サブパネル", + "config.emi.ui.right_sidebar_size": "サイズ", + "config.emi.ui.right_sidebar_margins": "マージン", + "config.emi.ui.right_sidebar_align": "配置", + "config.emi.ui.right_sidebar_header": "ヘッダー", + "config.emi.ui.right_sidebar_theme": "テーマ", + "config.emi.ui.top_sidebar_pages": "ページ", + "config.emi.ui.top_sidebar_subpanels": "サブパネル", + "config.emi.ui.top_sidebar_size": "サイズ", + "config.emi.ui.top_sidebar_margins": "マージン", + "config.emi.ui.top_sidebar_align": "配置", + "config.emi.ui.top_sidebar_header": "ヘッダー", + "config.emi.ui.top_sidebar_theme": "テーマ", + "config.emi.ui.bottom_sidebar_pages": "ページ", + "config.emi.ui.bottom_sidebar_subpanels": "サブパネル", + "config.emi.ui.bottom_sidebar_size": "サイズ", + "config.emi.ui.bottom_sidebar_margins": "マージン", + "config.emi.ui.bottom_sidebar_align": "配置", + "config.emi.ui.bottom_sidebar_header": "ヘッダー", + "config.emi.ui.bottom_sidebar_theme": "テーマ", + "config.emi.ui.vertical_margin": "垂直マージン", + "config.emi.ui.minimum_recipe_screen_width": "最小のレシピ画面幅", + "config.emi.ui.workstation_location": "ワークステーションの場所", + "config.emi.ui.miscraft_prevention": "誤クラフト防止", + "config.emi.ui.fluid_unit": "流体ユニット", + "config.emi.ui.show_cost_per_batch": "バッチごとのコストを表示", + "config.emi.ui.recipe_default_button": "レシピのデフォルトボタン", + "config.emi.ui.recipe_tree_button": "レシピツリーボタン", + "config.emi.ui.recipe_fill_button": "レシピのデフォルトボタン", + "config.emi.ui.recipe_screenshot_button": "レシピスクリーンショットボタン", + "config.emi.ui.recipe_screenshot_scale": "レシピのスクリーンショットスケール", + "config.emi.ui.use_batched_renderer": "バッチレンダラーを使用", + "config.emi.dev.dev_mode": "開発者モード", + "config.emi.dev.edit_mode": "編集モード", + "config.emi.dev.log_untranslated_tags": "未翻訳のタグをログ", + "config.emi.dev.log_non_tag_ingredients": "タグのついていない材料を記録する", + "config.emi.dev.show_recipe_ids": "レシピIDを表示", + "config.emi.dev.highlight_defaulted": "デフォルトでハイライト表示", + "config.emi.dev.highlight_exclusion_areas": "除外エリアを強調表示", + "config.emi.presets.sidebars": "サイドバー", + "config.emi.presets.binds": "バインド", + "config.emi.presets.restore": "戻す", + "config.emi.presets.productive": "生産的", + "config.emi.presets.recipe_book_plus": "レシピ本プラス", + "config.emi.presets.empty_search_craftable": "空の検索クラフト可能", + "config.emi.presets.author_binds": "著者のバインド", + "config.emi.presets.backup": "バックアップから復元", + "config.emi.presets.defaults": "初期設定に戻す", + "emi.unit.liters": "リットル", + "emi.unit.millibuckets": "ミリバケツ", + "emi.unit.droplets": "水滴", + "emi.fluid.amount.liters": "%s L", + "emi.fluid.amount.millibuckets": "%smB", + "emi.fluid.amount.droplets": "%d日%s", + "emi.disabled": "EMIが無効化されました!", + "emi.reloading": "EMIを再読み込みしています...", + "emi.reloading.waiting": "EMIがサーバからレシピデータを待っています...", + "emi.reloading.error": "§cEMIは再読み込み中に重大な例外が発生しました. ログをチェックしてください.", + "emi.reloading.worry": "§c体験の遅延は大丈夫ですか?", + "emi.search": "EMIを検索中...", + "emi.search_config": "設定を検索中...", + "emi.delete_stack": "§c保持スタックを削除する", + "emi.inapplicable": "現在のワークステーションはレシピをサポートしていません", + "emi.not_enough_ingredients": "クラフトに必要な材料が足りません", + "emi.too_small": "材料に合わせるにはグリッドが小さすぎます。", + "emi.favorite_recipe": "%s を押してレシピをお気に入りにする", + "emi.resolve.resolve": "%s を押してこのレシピツリーに使用します", + "emi.resolve.default": "%s を押してすべてのツリーのデフォルトを設定します", + "emi.page": "%s /%s ページ", + "emi.page.short": "%s/%s", + "emi.total_cost": "総コスト", + "emi.cost_per": "バッチあたりのコスト:", + "emi.leftovers": "残り物", + "emi.view_all_recipes": "クリックしてすべてのレシピを表示", + "emi.tree_welcome": "%sへようこそ", + "emi.no_tree": "まだレシピツリーが設定されていません...", + "emi.random_tree": "ランダムなものを見たいですか?", + "emi.random_tree_input": "§6[ctrl + r] を押す", + "emi.edit_mode.hide_one": "%s を押してスタックを非常時", + "emi.edit_mode.hide_all": "%s を押してIDでスタックを非表示", + "tooltip.emi.chance.consume": "消耗率: %s%%", + "tooltip.emi.chance.produce": "生産確率: %s%%", + "tooltip.emi.accepts": "承認:", + "tooltip.emi.fill_recipe": "レシピの入力", + "tooltip.emi.fill_recipe_no_server": "サーバー上でEMIなしでレシピを入力することはできません", + "tooltip.emi.set_default": "デフォルトのレシピとして設定", + "tooltip.emi.current_defaults": "現在のデフォルトのレシピ:", + "tooltip.emi.unset_default": "デフォルトのレシピから削除", + "tooltip.emi.set_default_stack": "出力で %s を押して、そのスタックのデフォルトレシピを設定します", + "tooltip.emi.view_tree": "レシピツリーを表示", + "tooltip.emi.recipe_screenshot": "レシピのスクリーンショットを撮る", + "tooltip.emi.resolution": "材料のレシピツリーを分解中", + "tooltip.emi.select_resolution": "レシピツリーを割り当てるには、§6レシピ出力§rをクリックしてください", + "tooltip.emi.default_resolution": "§6レシピのデフォルトボタン§rをクリックして, §aall§rレシピツリーに割り当てます.", + "tooltip.emi.clear_resolution": "§6ここ§rをクリックして解像度を§cクリア", + "tooltip.emi.config": "設定: %s", + "tooltip.emi.recipe_tree": "レシピツリー", + "tooltip.emi.config.global": "ゲームインスタンスごとに個別の設定ではなく, すべてのゲームインスタンス間でグローバルEMI設定を使用するかどうかを切り替える.", + "tooltip.emi.synfav.uncraftable": "§cany§r バッチを作成できません", + "tooltip.emi.synfav.partially_craftable": "§d誰か§rバッチを作成することができます", + "tooltip.emi.synfav.fully_craftable": "%s§rバッチを§aすべて作成できます", + "tooltip.emi.synfav.craft_some": "%s を押してできるだけ多くのものをクラフトする", + "tooltip.emi.synfav.craft_all": "%s を押して§9%s§rバッチを作成します", + "tooltip.emi.bom.batch_size": "バッチサイズ: %s\nスクロールして調整します\n§6[shift]§r を押したままにして16ずつ調整します", + "tooltip.emi.bom.batch_size.ideal": "%s を押して残り物を最小限にする", + "tooltip.emi.bom.mode.view": "§6閲覧中§r レシピツリー", + "tooltip.emi.bom.mode.craft": "§6クラフト§rレシピツリー\n進捗をレシピツリー\n§b合成お気に入り§rをサイドバーに追加しました", + "tooltip.emi.bom.help": "レシピ ツリーには, レシピのプロセスと基本コストが表示されます.\n表示は垂直移動と平行移動, ズームが可能です.\n\nノードを左クリックして, それに割り当てるレシピを選択します.\n§6[shift]§r を押し続けると, 在庫に基づいて自動的に選択されます.\n\nレシピノードを右クリックして一時的に折りたため,\n§6[shift]§r を押し続けるとレシピをクリアできます.\n\nツリーの初期状態はデフォルトのレシピによって制御されます.\nレシピの横にあるボタンでデフォルトのレシピ設定を設定できます.\n\n総コストによる切り替えは, レシピ ツリーの作成に役立ちます.\n製作中は収集が必要な素材が表示されます.\n§b合成お気に入り§r は, お気に入りサイドバーに追加されます.\n不完全な手順が表示され, クラフトに使用できます.", + "tooltip.emi.fluid_interaction.basalt.soul_soil": "溶岩の下", + "tooltip.emi.fluid_interaction.basalt.blue_ice": "溶岩に隣接しています", + "screen.emi.recipe": "レシピ", + "screen.emi.config": "設定", + "screen.emi.presets": "設定のプリセット", + "screen.emi.config.reset": "%s の変更を元に戻す(s)", + "emi.error.recipe.initialize": "初期化エラー", + "emi.error.recipe.render": "レンダリングエラー", + "emi.chess.piece.white_pawn": "ホワイトポーン", + "emi.chess.piece.white_rook": "ホワイトルーク", + "emi.chess.piece.white_knight": "ホワイトナイト", + "emi.chess.piece.white_bishop": "ホワイトビショップ", + "emi.chess.piece.white_queen": "ホワイトクイーン", + "emi.chess.piece.white_king": "ホワイトキング", + "emi.chess.piece.black_pawn": "ブラックポーン", + "emi.chess.piece.black_rook": "ブラックルーク", + "emi.chess.piece.black_knight": "ブラックナイト", + "emi.chess.piece.black_bishop": "ブラックビショップ", + "emi.chess.piece.black_queen": "ブラッククイーン", + "emi.chess.piece.black_king": "ブラックキング", + "emi.chess.tooltip.invite": "検索バーにいるプレイヤーを招待してチェスをする", + "emi.chess.tooltip.accept": "%sのチェスの招待を受け入れる", + "emi.chess.tooltip.decline": "右クリックで %sのチェス招待を拒否する", + "emi.chess.tooltip.restart": "右クリックで再起動", + "emi.chess.multiplayer.invited": "%s があなたをチェスに招待しました", + "emi.chess.multiplayer.accepted": "%s がチェスの招待を承認しました", + "emi.chess.multiplayer.cancelled": "%s がチェスの試合をキャンセルしました", + "emi.chess.multiplayer.unavailable": "%s はチェスができません", + "emi.cooking.experience": "%s XP", + "emi.cooking.time": "%s 秒", + "emi.grinding.experience": "%s - %s XP", + "emi.fuel_time.items": "%s アイテムを精錬する(s)", + "emi.category.minecraft.crafting": "クラフト", + "emi.category.minecraft.smelting": "精錬", + "emi.category.minecraft.blasting": "溶鉱炉を使う", + "emi.category.minecraft.smoking": "燻製器を遣う", + "emi.category.minecraft.campfire_cooking": "焚火を使う", + "emi.category.minecraft.stonecutting": "ストーンカッターを使う", + "emi.category.minecraft.smithing": "鍛冶台を使う", + "emi.category.emi.anvil_repairing": "金床を使う", + "emi.category.minecraft.brewing": "醸造台を使う", + "emi.category.emi.grinding": "砥石を使う", + "emi.category.emi.world_interaction": "ワールドの相互作用", + "emi.category.emi.fuel": "燃料", + "emi.category.emi.composting": "コンポスターを使う", + "emi.category.emi.info": "情報", + "emi.category.emi.tag": "タグ", + "emi.category.emi.ingredient": "材料", + "alias.emi.workbench": "作業台", + "tag.item.minecraft.logs": "ログ", + "tag.item.minecraft.oak_logs": "オークの原木", + "tag.item.minecraft.birch_logs": "シラカバの原木", + "tag.item.minecraft.spruce_logs": "トウヒの原木", + "tag.item.minecraft.jungle_logs": "ジャングルの原木", + "tag.item.minecraft.dark_oak_logs": "ダークオークの原木", + "tag.item.minecraft.crimson_stems": "真紅の幹", + "tag.item.minecraft.warped_stems": "歪んだ幹", + "tag.item.minecraft.acacia_logs": "アカシアの原木", + "tag.item.minecraft.logs_that_burn": "可燃性の原木", + "tag.item.minecraft.planks": "板材", + "tag.item.minecraft.non_flammable_wood": "不燃性の木材", + "tag.item.minecraft.coal_ores": "石炭鉱石", + "tag.item.minecraft.copper_ores": "銅鉱石", + "tag.item.minecraft.diamond_ores": "ダイアモンド鉱石", + "tag.item.minecraft.emerald_ores": "エメラルド鉱石", + "tag.item.minecraft.gold_ores": "金鉱石", + "tag.item.minecraft.iron_ores": "鉄鉱石", + "tag.item.minecraft.lapis_ores": "ラピスラズリ鉱石", + "tag.item.minecraft.redstone_ores": "レッドストーン鉱石", + "tag.item.minecraft.anvil": "金床", + "tag.item.minecraft.arrows": "矢", + "tag.item.minecraft.axolotl_tempt_items": "ウーパールーパーへの温度影響", + "tag.item.minecraft.banners": "旗", + "tag.item.minecraft.beacon_payment_items": "ビーコンを作動させる材料", + "tag.item.minecraft.beds": "ベッド", + "tag.item.minecraft.boats": "ボート", + "tag.item.minecraft.buttons": "ボタン", + "tag.item.minecraft.candles": "ロウソク", + "tag.item.minecraft.carpets": "カーペット", + "tag.item.minecraft.coals": "石炭", + "tag.item.minecraft.creeper_drop_music_discs": "クリーパーからレコードをドロップ", + "tag.item.minecraft.creeper_igniters": "クリーパーへの着火", + "tag.item.minecraft.dirt": "土", + "tag.item.minecraft.doors": "ドア", + "tag.item.minecraft.fences": "フェンス", + "tag.item.minecraft.fence_gates": "フェンスゲート", + "tag.item.minecraft.fishes": "魚", + "tag.item.minecraft.flowers": "花", + "tag.item.minecraft.fox_food": "キツネの食べ物", + "tag.item.minecraft.freeze_immune_wearables": "免疫装備を固定する", + "tag.item.minecraft.ignored_by_piglin_babies": "子供ピグリンによって無視された", + "tag.item.minecraft.leaves": "葉", + "tag.item.minecraft.lectern_books": "書見台", + "tag.item.minecraft.music_discs": "レコード", + "tag.item.minecraft.occludes_vibration_signals": "スカルクセンサーの反応を回避する", + "tag.item.minecraft.piglin_food": "ピグリンの食品", + "tag.item.minecraft.piglin_loved": "ピグリンからの愛", + "tag.item.minecraft.piglin_repellents": "ピグリン避け", + "tag.item.minecraft.rails": "レール", + "tag.item.minecraft.sand": "砂", + "tag.item.minecraft.saplings": "苗木", + "tag.item.minecraft.signs": "看板", + "tag.item.minecraft.slabs": "ハーフブロック", + "tag.item.minecraft.small_flowers": "小さい花", + "tag.item.minecraft.soul_fire_base_blocks": "青い炎", + "tag.item.minecraft.stairs": "階段", + "tag.item.minecraft.stone_bricks": "石レンガ", + "tag.item.minecraft.stone_crafting_materials": "石造りの素材", + "tag.item.minecraft.stone_tool_materials": "石ツールの素材", + "tag.item.minecraft.tall_flowers": "背の高い花", + "tag.item.minecraft.terracotta": "テラコッタ", + "tag.item.minecraft.trapdoors": "トラップドア", + "tag.item.minecraft.walls": "壁", + "tag.item.minecraft.wooden_buttons": "木のボタン", + "tag.item.minecraft.wooden_doors": "木のドア", + "tag.item.minecraft.wooden_fences": "木のフェンス", + "tag.item.minecraft.wooden_pressure_plates": "木の感圧板", + "tag.item.minecraft.wooden_slabs": "木材ハーフブロック", + "tag.item.minecraft.wooden_stairs": "木の階段", + "tag.item.minecraft.wooden_trapdoors": "木材のトラップドア", + "tag.item.minecraft.wool": "羊毛", + "tag.item.minecraft.wart_blocks": "ネザーウォートブロック", + "tag.item.minecraft.wool_carpets": "羊毛のカーペット", + "tag.item.minecraft.mangrove_logs": "マングローブの原木", + "tag.item.minecraft.compasses": "コンパス", + "tag.item.minecraft.chest_boats": "チェストボート", + "tag.item.minecraft.overworld_natural_logs": "オーバーワールドに群生する原木", + "tag.item.minecraft.axes": "斧", + "tag.item.minecraft.hoes": "クワ", + "tag.item.minecraft.pickaxes": "ツルハシ", + "tag.item.minecraft.shovels": "シャベル", + "tag.item.minecraft.smelts_to_glass": "精錬してガラスにする", + "tag.item.minecraft.swords": "剣", + "tag.item.minecraft.tools": "道具", + "tag.item.minecraft.bamboo_blocks": "竹ブロック", + "tag.item.minecraft.bookshelf_books": "本棚の本", + "tag.item.minecraft.breaks_decorated_pots": "壊れた飾り壺", + "tag.item.minecraft.cherry_logs": "サクラの原木", + "tag.item.minecraft.decorated_pot_ingredients": "飾り壺の材料", + "tag.item.minecraft.decorated_pot_sherds": "壺の欠片", + "tag.item.minecraft.hanging_signs": "吊り看板", + "tag.item.minecraft.noteblock_top_instruments": "音符ブロックでの楽器", + "tag.item.minecraft.sniffer_food": "スニファーの餌", + "tag.item.minecraft.stone_buttons": "石のボタン", + "tag.item.minecraft.trim_materials": "材料を切り取り", + "tag.item.minecraft.trim_templates": "切り取りテンプレート", + "tag.item.minecraft.trimmable_armor": "切り取り可能な装備", + "tag.item.minecraft.villager_plantable_seeds": "村人の植物種", + "tag.fluid.minecraft.water": "水", + "tag.fluid.minecraft.lava": "溶岩", + "tag.fluid.c.water": "水", + "tag.fluid.c.lava": "溶岩", + "tag.fluid.c.milk": "牛乳", + "tag.item.c.stone": "石", + "tag.item.c.cobblestone": "丸石", + "tag.item.c.cobblestone.deepslate": "深層岩の丸石", + "tag.item.c.cobblestone.infested": "虫食い丸石", + "tag.item.c.cobblestone.mossy": "苔むした丸石", + "tag.item.c.cobblestone.normal": "丸石", + "tag.item.c.sandstone": "砂岩", + "tag.item.c.glass_blocks": "ガラスブロック", + "tag.item.c.stained_glass": "色付きガラス", + "tag.item.c.stained_glass_panes": "色付きガラス板", + "tag.item.c.glass": "ガラス", + "tag.item.c.glass.colorless": "無色のガラス", + "tag.item.c.glass.silica": "シリカガラス", + "tag.item.c.quartz_blocks": "クォーツブロック", + "tag.item.c.glass_panes": "ガラス板", + "tag.item.c.glass.tinted": "遮光ガラス", + "tag.item.c.glass_panes.colorless": "透明のガラス板", + "tag.item.c.raw_materials": "原材料", + "tag.item.c.rods": "ロッド", + "tag.item.c.ores": "鉱石", + "tag.item.c.nuggets": "鉱石の塊", + "tag.item.c.ingots": "インゴット", + "tag.item.c.gems": "宝石", + "tag.item.c.plates": "プレート", + "tag.item.c.dusts": "ダスト", + "tag.item.c.storage_blocks": "ストレージブロック", + "tag.item.c.seeds": "種", + "tag.item.c.crops": "作物", + "tag.item.c.heads": "ヘッド", + "tag.item.c.dyes": "染料", + "tag.item.c.mushrooms": "キノコ", + "tag.item.c.fence_gates": "フェンスゲート", + "tag.item.c.fence_gates.wooden": "木のフェンスゲート", + "tag.item.c.chests": "チェスト", + "tag.item.c.wooden_chests": "木のチェスト", + "tag.item.c.ores_in_ground.stone": "石 鉱石", + "tag.item.c.ores_in_ground.deepslate": "深層岩 鉱石", + "tag.item.c.ores_in_ground.netherrack": "ネザーラック 鉱石", + "tag.item.c.chest": "チェスト", + "tag.item.c.coal": "石炭", + "tag.item.c.sand": "砂", + "tag.item.c.glass_pane": "ガラス板", + "tag.item.c.beacon_payment": "ビーコンを作動させる材料", + "tag.item.c.fences": "フェンス", + "tag.item.c.fences.wooden": "木のフェンス", + "tag.item.c.ores.coal": "石炭鉱石", + "tag.item.c.ores.copper": "銅鉱石", + "tag.item.c.ores.iron": "鉄鉱石", + "tag.item.c.ores.gold": "金鉱石", + "tag.item.c.ores.redstone": "レッドストーン鉱石", + "tag.item.c.ores.lapis": "ラピスラズリ鉱石", + "tag.item.c.ores.emerald": "エメラルド鉱石", + "tag.item.c.ores.diamond": "ダイヤモンド鉱石", + "tag.item.c.storage_blocks.coal": "銅のストレージブロック", + "tag.item.c.raw_materials.copper": "銅の原石", + "tag.item.c.copper_dusts": "銅の粉", + "tag.item.c.dusts.copper": "銅の粉", + "tag.item.c.copper_ingots": "銅インゴット", + "tag.item.c.ingots.copper": "銅インゴット", + "tag.item.c.copper_nuggets": "銅塊", + "tag.item.c.nuggets.copper": "銅塊", + "tag.item.c.plates.copper": "銅プレート", + "tag.item.c.raw_copper_ores": "銅の原石", + "tag.item.c.raw_copper_blocks": "銅の原石ブロック", + "tag.item.c.copper_blocks": "銅ブロック", + "tag.item.c.storage_blocks.raw_copper": "銅のストレージブロック", + "tag.item.c.storage_blocks.copper": "銅のストレージブロック", + "tag.item.c.raw_materials.iron": "鉄の原石", + "tag.item.c.iron_dusts": "鉄の粉", + "tag.item.c.dusts.iron": "鉄の粉", + "tag.item.c.iron_ingots": "鉄インゴット", + "tag.item.c.ingots.iron": "鉄インゴット", + "tag.item.c.iron_nuggets": "鉄塊", + "tag.item.c.nuggets.iron": "鉄塊", + "tag.item.c.plates.iron": "鉄のプレート", + "tag.item.c.raw_iron_ores": "鉄鉱石", + "tag.item.c.raw_iron_blocks": "鉄の原石ブロック", + "tag.item.c.iron_blocks": "鉄ブロック", + "tag.item.c.storage_blocks.raw_iron": "鉄の原石のストレージブロック", + "tag.item.c.storage_blocks.iron": "鉄の原石のストレージブロック", + "tag.item.c.raw_materials.gold": "金の原石", + "tag.item.c.gold_dusts": "金の粉", + "tag.item.c.dusts.gold": "金の粉", + "tag.item.c.gold_ingots": "金インゴット", + "tag.item.c.ingots.gold": "金インゴット", + "tag.item.c.gold_nuggets": "金塊", + "tag.item.c.nuggets.gold": "金塊", + "tag.item.c.plates.gold": "金のプレート", + "tag.item.c.raw_gold_ores": "金の原石", + "tag.item.c.raw_gold_blocks": "金の原石ブロック", + "tag.item.c.gold_blocks": "金ブロック", + "tag.item.c.storage_blocks.gold": "金のストレージブロック", + "tag.item.c.storage_blocks.raw_gold": "金原石のストレージブロック", + "tag.item.c.gems.amethyst": "アメジスト", + "tag.item.c.amethyst_dusts": "アメジストダスト", + "tag.item.c.storage_blocks.amethyst": "アメジストのストレージブロック", + "tag.item.c.storage_blocks.diamond": "ダイヤのストレージブロック", + "tag.item.c.storage_blocks.emerald": "エメラルドのストレージブロック", + "tag.item.c.storage_blocks.lapis": "ラピスラズリのストレージブロック", + "tag.item.c.storage_blocks.netherite": "ネザーライトのストレージブロック", + "tag.item.c.storage_blocks.quartz": "クォーツのストレージブロック", + "tag.item.c.storage_blocks.redstone": "レッドストーンのストレージブロック", + "tag.item.c.redstone_dusts": "レッドストーンダスト", + "tag.item.c.redstone_ores": "レッドストーン鉱石", + "tag.item.c.quartz": "クオーツ", + "tag.item.c.quartz_ores": "クォーツ鉱石", + "tag.item.c.diamond_dusts": "ダイヤモンドの粉", + "tag.item.c.diamonds": "ダイヤモンド", + "tag.item.c.dusts.glowstone": "グロウストーンダスト", + "tag.item.c.dusts.prismarine": "プリズマリンダスト", + "tag.item.c.dusts.redstone": "レッドストーンダスト", + "tag.item.c.emeralds": "エメラルド", + "tag.item.c.ender_pearl_dusts": "エンダーパールダスト", + "tag.item.c.ender_pearls": "エンダーパール", + "tag.item.c.gems.diamond": "ダイヤモンド", + "tag.item.c.gems.emerald": "エメラルド", + "tag.item.c.gems.lapis": "ラピスラズリ", + "tag.item.c.gems.prismarine": "プリズマリン", + "tag.item.c.gems.quartz": "クオーツ", + "tag.item.c.ingots.brick": "レンガ", + "tag.item.c.ingots.nether_brick": "ネザーレンガ", + "tag.item.c.ingots.netherite": "ネザライトインゴット", + "tag.item.c.lapis": "ラピスラズリ", + "tag.item.c.nether_quartz_dusts": "ネザークォーツダスト", + "tag.item.c.netherite_ingots": "ネザライトインゴット", + "tag.item.c.netherite_scrap_dusts": "ネザータイトスクラップダスト", + "tag.item.c.ores.netherite_scrap": "ネザーライトスクラップ鉱石", + "tag.item.c.ores.quartz": "クォーツ鉱石", + "tag.item.c.spears": "スピア", + "tag.item.c.axes": "斧", + "tag.item.c.barrels": "樽", + "tag.item.c.barrels.wooden": "木の樽", + "tag.item.c.white_dyes": "白色の染料", + "tag.item.c.orange_dyes": "橙色の染料", + "tag.item.c.magenta_dyes": "赤紫の染料", + "tag.item.c.light_blue_dyes": "空色の染料", + "tag.item.c.yellow_dyes": "黄色の染料", + "tag.item.c.lime_dyes": "黄緑色の染料", + "tag.item.c.pink_dyes": "桃色の染料", + "tag.item.c.gray_dyes": "灰色の染料", + "tag.item.c.light_gray_dyes": "薄灰色の染料", + "tag.item.c.cyan_dyes": "青緑色の染料", + "tag.item.c.purple_dyes": "紫色の染料", + "tag.item.c.blue_dyes": "青色の染料", + "tag.item.c.brown_dyes": "茶色の染料", + "tag.item.c.green_dyes": "緑色の染料", + "tag.item.c.red_dyes": "赤色の染料", + "tag.item.c.black_dyes": "黒色の染料", + "tag.item.c.dyes.white": "白色の染料", + "tag.item.c.dyes.orange": "橙色の染料", + "tag.item.c.dyes.magenta": "赤紫の染料", + "tag.item.c.dyes.light_blue": "空色の染料", + "tag.item.c.dyes.yellow": "黄色の染料", + "tag.item.c.dyes.lime": "黄緑色の染料", + "tag.item.c.dyes.pink": "桃色の染料", + "tag.item.c.dyes.gray": "灰色の染料", + "tag.item.c.dyes.light_gray": "薄灰色の染料", + "tag.item.c.dyes.cyan": "青緑色の染料", + "tag.item.c.dyes.purple": "紫色の染料", + "tag.item.c.dyes.blue": "青色の染料", + "tag.item.c.dyes.brown": "茶色の染料", + "tag.item.c.dyes.green": "緑色の染料", + "tag.item.c.dyes.red": "赤色の染料", + "tag.item.c.dyes.black": "黒色の染料", + "tag.item.c.glass.white": "白色の色付きガラス", + "tag.item.c.glass.orange": "橙色の色付きガラス", + "tag.item.c.glass.magenta": "赤紫色の色付きガラス", + "tag.item.c.glass.light_blue": "空色の染料", + "tag.item.c.glass.yellow": "黄色の色付きガラス", + "tag.item.c.glass.lime": "黄緑色の色付きガラス", + "tag.item.c.glass.pink": "桃色の色付きガラス", + "tag.item.c.glass.gray": "灰色の色付きガラス", + "tag.item.c.glass.light_gray": "空色の染料", + "tag.item.c.glass.cyan": "青緑色の色付きガラス", + "tag.item.c.glass.purple": "紫色の色付きガラス", + "tag.item.c.glass.blue": "青色の色付きガラス", + "tag.item.c.glass.brown": "茶色の色付きガラス", + "tag.item.c.glass.green": "緑色の色付きガラス", + "tag.item.c.glass.red": "赤色の色付きガラス", + "tag.item.c.glass.black": "黒色の色付きガラス", + "tag.item.c.glass_panes.white": "白色の色付きガラス板", + "tag.item.c.glass_panes.orange": "橙色の色付きガラス板", + "tag.item.c.glass_panes.magenta": "赤紫色の色付きガラス板", + "tag.item.c.glass_panes.light_blue": "空色の色付きガラス板", + "tag.item.c.glass_panes.yellow": "黄色の色付きガラス板", + "tag.item.c.glass_panes.lime": "黄緑色の色付きガラス板", + "tag.item.c.glass_panes.pink": "桃色の色付きガラス板", + "tag.item.c.glass_panes.gray": "灰色の色付きガラス板", + "tag.item.c.glass_panes.light_gray": "薄灰色の色付きガラス板", + "tag.item.c.glass_panes.cyan": "青緑色の色付きガラス板", + "tag.item.c.glass_panes.purple": "紫色の色付きガラス板", + "tag.item.c.glass_panes.blue": "青色の色付きガラス板", + "tag.item.c.glass_panes.brown": "茶色の色付きガラス板", + "tag.item.c.glass_panes.green": "緑色の色付きガラス板", + "tag.item.c.glass_panes.red": "赤色の色付きガラス板", + "tag.item.c.glass_panes.black": "黒色の色付きガラス板", + "tag.item.c.bones": "骨", + "tag.item.c.bookshelves": "本棚", + "tag.item.c.bows": "弓", + "tag.item.c.buckets.honey": "ハチミツ入りバケツ", + "tag.item.c.chests.ender": "エンダーチェスト", + "tag.item.c.chests.trapped": "トラップチェスト", + "tag.item.c.chests.wooden": "木のチェスト", + "tag.item.c.circuits": "回路", + "tag.item.c.crops.beetroot": "ビートルート", + "tag.item.c.crops.carrot": "ニンジン", + "tag.item.c.crops.nether_wart": "ネザーウォート", + "tag.item.c.crops.potato": "ジャガイモ", + "tag.item.c.crops.wheat": "小麦", + "tag.item.c.eggs": "卵", + "tag.item.c.empty_buckets": "空のバケツ", + "tag.item.c.enchanting_fuels": "エンチャントの燃料", + "tag.item.c.end_stones": "エンドストーン", + "tag.item.c.feathers": "羽", + "tag.item.c.fences.nether_brick": "ネザーレンガのフェンス", + "tag.item.c.foods": "食べ物", + "tag.item.c.gravel": "砂利", + "tag.item.c.gunpowder": "火薬", + "tag.item.c.hoes": "クワ", + "tag.item.c.lava_buckets": "溶岩入りバケツ", + "tag.item.c.leather": "革", + "tag.item.c.milk_bottles": "ミルク入りの瓶", + "tag.item.c.milk_buckets": "牛乳入りバケツ", + "tag.item.c.nether_stars": "ネザースター", + "tag.item.c.netherrack": "ネザーラック", + "tag.item.c.obsidian": "黒曜石", + "tag.item.c.pickaxes": "ツルハシ", + "tag.item.c.potions": "ポーション", + "tag.item.c.red_sandstone": "赤い砂岩", + "tag.item.c.red_sandstone_slabs": "赤い砂岩のハーフブロック", + "tag.item.c.red_sandstone_stairs": "赤い砂岩の階段", + "tag.item.c.rods.blaze": "ブレイズロッド", + "tag.item.c.rods.wooden": "木のドア", + "tag.item.c.sand.colorless": "無色の砂", + "tag.item.c.sand.red": "赤砂", + "tag.item.c.sandstone_slabs": "砂岩のハーフブロック", + "tag.item.c.sandstone_stairs": "砂岩の階段", + "tag.item.c.seeds.beetroot": "ビートルートの種", + "tag.item.c.seeds.melon": "スイカの種", + "tag.item.c.seeds.pumpkin": "カボチャの種", + "tag.item.c.seeds.wheat": "小麦の種", + "tag.item.c.shears": "ハサミ", + "tag.item.c.shields": "盾", + "tag.item.c.shovels": "シャベル", + "tag.item.c.shulker_boxes": "シュルカーボックス", + "tag.item.c.skulls": "スカル", + "tag.item.c.slime_balls": "スライムボール", + "tag.item.c.slimeballs": "スライムボール", + "tag.item.c.stone_dusts": "石のダスト", + "tag.item.c.stones": "石", + "tag.item.c.string": "糸", + "tag.item.c.strings": "String", + "tag.item.c.swords": "剣", + "tag.item.c.water_buckets": "水入りバケツ", + "tag.item.c.wrenches": "レンチ", + "tag.item.c.budding_blocks": "芽吹いたブロック", + "tag.item.c.buds": "つぼみ", + "tag.item.c.clusters": "クラスター", + "tag.item.c.entity_water_buckets": "エンティティの水入りバケツ", + "tag.item.c.raw_ores": "鉱石", + "tag.item.c.red_sandstone_blocks": "赤い砂岩ブロック", + "tag.item.c.sandstone_blocks": "砂岩ブロック", + "tag.item.c.uncolored_sandstone_blocks": "無色な砂岩ブロック", + "tag.item.c.uncolored_sandstone_slabs": "無色な砂岩のハーフブロック", + "tag.item.c.uncolored_sandstone_stairs": "無色な砂岩の階段ブロック", + "tag.item.c.villager_job_sites": "村人の作業場所", + "tag.item.c.wooden_barrels": "木の樽", + "tag.item.c.armors": "アーマー", + "tag.item.c.armors.boots": "ブーツ", + "tag.item.c.armors.chestplates": "チェストプレート", + "tag.item.c.armors.helmets": "ヘルメット", + "tag.item.c.armors.leggings": "レギンス", + "tag.item.c.tools": "ツール", + "tag.item.c.tools.axes": "斧", + "tag.item.c.tools.bows": "弓", + "tag.item.c.tools.crossbows": "クロスボウ", + "tag.item.c.tools.fishing_rods": "釣竿", + "tag.item.c.tools.hoes": "クワ", + "tag.item.c.tools.pickaxes": "ツルハシ", + "tag.item.c.tools.shields": "盾", + "tag.item.c.tools.shovels": "シャベル", + "tag.item.c.tools.swords": "剣", + "tag.item.c.tools.tridents": "トライデント", + "tag.item.fabric.pickaxes": "ツルハシ", + "tag.item.fabric.axes": "斧", + "tag.item.fabric.shovels": "シャベル", + "tag.item.fabric.hoes": "クワ", + "tag.item.fabric.swords": "剣", + "tag.item.fabric.shears": "ハサミ" +} From 6d3904ebbf764f7c4152a922c9195021590db178 Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Sun, 5 Nov 2023 19:36:05 -0600 Subject: [PATCH 18/67] 1.0.24 --- CHANGELOG.md | 8 +++++--- gradle.properties | 2 +- xplat/src/main/java/dev/emi/emi/VanillaPlugin.java | 7 ------- .../src/main/java/dev/emi/emi/jemi/JemiPlugin.java | 2 +- .../main/java/dev/emi/emi/registry/EmiRecipes.java | 9 ++++++++- .../java/dev/emi/emi/runtime/EmiReloadManager.java | 14 +++++++++++++- 6 files changed, 28 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1cd57786..38a57538 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ +### Tweaks +* Disabled stacks no longer appear as workstations #323 + ### Fixes -* Fixed JEMI tooltips #330 -* Fixed slot highlight misalignment #328 -* Fixed slot highlight for mod search \ No newline at end of file +* Fixed "exception deserializing stack" and related resource oddities with a temporary workaround #257 +* Fixed typo in log #341 \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 2a8abc39..225ff4cd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,7 +4,7 @@ minecraft_version=1.20.1 enabled_platforms=fabric,forge archives_base_name=emi -mod_version=1.0.23 +mod_version=1.0.24 maven_group=dev.emi architectury_version=4.9.83 diff --git a/xplat/src/main/java/dev/emi/emi/VanillaPlugin.java b/xplat/src/main/java/dev/emi/emi/VanillaPlugin.java index b8c7d596..f4956670 100644 --- a/xplat/src/main/java/dev/emi/emi/VanillaPlugin.java +++ b/xplat/src/main/java/dev/emi/emi/VanillaPlugin.java @@ -92,9 +92,6 @@ import dev.emi.emi.runtime.EmiDrawContext; import dev.emi.emi.runtime.EmiLog; import dev.emi.emi.runtime.EmiReloadLog; -import dev.emi.emi.stack.serializer.FluidEmiStackSerializer; -import dev.emi.emi.stack.serializer.ItemEmiStackSerializer; -import dev.emi.emi.stack.serializer.TagEmiIngredientSerializer; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; @@ -205,10 +202,6 @@ public class VanillaPlugin implements EmiPlugin { @Override public void register(EmiRegistry registry) { - registry.addIngredientSerializer(ItemEmiStack.class, new ItemEmiStackSerializer()); - registry.addIngredientSerializer(FluidEmiStack.class, new FluidEmiStackSerializer()); - registry.addIngredientSerializer(TagEmiIngredient.class, new TagEmiIngredientSerializer()); - registry.addCategory(CRAFTING); registry.addCategory(SMELTING); registry.addCategory(BLASTING); diff --git a/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java b/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java index f3a6f9ec..87bfd656 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java @@ -217,7 +217,7 @@ public void register(EmiRegistry registry) { List> categories = runtime.getRecipeManager().createRecipeCategoryLookup().includeHidden().get().toList(); for (IRecipeCategory c : categories) { - EmiLog.info("[JEMI] Collecing data for " + c.getTitle().getString()); + EmiLog.info("[JEMI] Collecting data for " + c.getTitle().getString()); EmiReloadManager.step(EmiPort.literal("Loading JEI data for ").append(c.getTitle()), 5_000); try { RecipeType type = c.getRecipeType(); diff --git a/xplat/src/main/java/dev/emi/emi/registry/EmiRecipes.java b/xplat/src/main/java/dev/emi/emi/registry/EmiRecipes.java index 57663bb8..84407b71 100644 --- a/xplat/src/main/java/dev/emi/emi/registry/EmiRecipes.java +++ b/xplat/src/main/java/dev/emi/emi/registry/EmiRecipes.java @@ -81,7 +81,14 @@ public static void bake() { } return true; }).toList(); - manager = new Manager(categories, workstations, filtered); + Map> filteredWorkstations = Maps.newHashMap(); + for (Map.Entry> entry : workstations.entrySet()) { + List w = entry.getValue().stream().filter(s -> !EmiHidden.isDisabled(s)).toList(); + if (!w.isEmpty()) { + filteredWorkstations.put(entry.getKey(), w); + } + } + manager = new Manager(categories, filteredWorkstations, filtered); EmiLog.info("Baked " + recipes.size() + " recipes in " + (System.currentTimeMillis() - start) + "ms"); } diff --git a/xplat/src/main/java/dev/emi/emi/runtime/EmiReloadManager.java b/xplat/src/main/java/dev/emi/emi/runtime/EmiReloadManager.java index c0ce7745..f7975624 100644 --- a/xplat/src/main/java/dev/emi/emi/runtime/EmiReloadManager.java +++ b/xplat/src/main/java/dev/emi/emi/runtime/EmiReloadManager.java @@ -9,6 +9,9 @@ import dev.emi.emi.EmiPort; import dev.emi.emi.api.EmiRegistry; import dev.emi.emi.api.recipe.EmiRecipe; +import dev.emi.emi.api.stack.FluidEmiStack; +import dev.emi.emi.api.stack.ItemEmiStack; +import dev.emi.emi.api.stack.TagEmiIngredient; import dev.emi.emi.bom.BoM; import dev.emi.emi.jemi.JemiPlugin; import dev.emi.emi.platform.EmiAgnos; @@ -25,6 +28,9 @@ import dev.emi.emi.registry.EmiTags; import dev.emi.emi.screen.EmiScreenManager; import dev.emi.emi.search.EmiSearch; +import dev.emi.emi.stack.serializer.FluidEmiStackSerializer; +import dev.emi.emi.stack.serializer.ItemEmiStackSerializer; +import dev.emi.emi.stack.serializer.TagEmiIngredientSerializer; import net.minecraft.client.MinecraftClient; import net.minecraft.text.Text; @@ -137,7 +143,13 @@ public void run() { EmiReloadLog.warn("Recipe Manager is null"); break; } - + { + // TODO temporary fix + EmiRegistry registry = new EmiRegistryImpl(); + registry.addIngredientSerializer(ItemEmiStack.class, new ItemEmiStackSerializer()); + registry.addIngredientSerializer(FluidEmiStack.class, new FluidEmiStackSerializer()); + registry.addIngredientSerializer(TagEmiIngredient.class, new TagEmiIngredientSerializer()); + } EmiHidden.reload(); step(EmiPort.literal("Processing tags")); From 56a4ef5cd7d0bebe1dd45703f3f103c2f74984f8 Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Sat, 16 Dec 2023 02:18:29 -0600 Subject: [PATCH 19/67] Reapply the potion recipe name change --- .../emi/emi/platform/forge/EmiAgnosForge.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/forge/src/main/java/dev/emi/emi/platform/forge/EmiAgnosForge.java b/forge/src/main/java/dev/emi/emi/platform/forge/EmiAgnosForge.java index de5862ed..167243a7 100644 --- a/forge/src/main/java/dev/emi/emi/platform/forge/EmiAgnosForge.java +++ b/forge/src/main/java/dev/emi/emi/platform/forge/EmiAgnosForge.java @@ -139,11 +139,11 @@ protected void addBrewingRecipesAgnos(EmiRegistry registry) { if (recipe.ingredient.getMatchingStacks().length > 0) { Identifier id = new Identifier("emi", "/brewing/" + pid + "/" + EmiUtil.subId(recipe.ingredient.getMatchingStacks()[0].getItem()) - + "/" + EmiUtil.subId(EmiPort.getPotionRegistry().getId(recipe.f_43532_.get())) - + "/" + EmiUtil.subId(EmiPort.getPotionRegistry().getId(recipe.f_43534_.get()))); + + "/" + EmiUtil.subId(EmiPort.getPotionRegistry().getId(recipe.input.get())) + + "/" + EmiUtil.subId(EmiPort.getPotionRegistry().getId(recipe.output.get()))); registry.addRecipe(new EmiBrewingRecipe( - EmiStack.of(PotionUtil.setPotion(stack.copy(), recipe.f_43532_.get())), EmiIngredient.of(recipe.ingredient), - EmiStack.of(PotionUtil.setPotion(stack.copy(), recipe.f_43534_.get())), id)); + EmiStack.of(PotionUtil.setPotion(stack.copy(), recipe.input.get())), EmiIngredient.of(recipe.ingredient), + EmiStack.of(PotionUtil.setPotion(stack.copy(), recipe.output.get())), id)); } } catch (Exception e) { e.printStackTrace(); @@ -156,8 +156,8 @@ protected void addBrewingRecipesAgnos(EmiRegistry registry) { try { if (recipe.ingredient.getMatchingStacks().length > 0) { String gid = EmiUtil.subId(recipe.ingredient.getMatchingStacks()[0].getItem()); - String iid = EmiUtil.subId(recipe.f_43532_.get()); - String oid = EmiUtil.subId(recipe.f_43534_.get()); + String iid = EmiUtil.subId(recipe.input.get()); + String oid = EmiUtil.subId(recipe.output.get()); Consumer> potionRecipeGen = entry -> { Potion potion = entry.value(); if (potion == Potions.EMPTY) { @@ -167,11 +167,11 @@ protected void addBrewingRecipesAgnos(EmiRegistry registry) { Identifier id = new Identifier("emi", "brewing/item/" + EmiUtil.subId(entry.getKey().get().getValue()) + "/" + gid + "/" + iid + "/" + oid); registry.addRecipe(new EmiBrewingRecipe( - EmiStack.of(PotionUtil.setPotion(new ItemStack(recipe.f_43532_.get()), potion)), EmiIngredient.of(recipe.ingredient), - EmiStack.of(PotionUtil.setPotion(new ItemStack(recipe.f_43534_.get()), potion)), id)); + EmiStack.of(PotionUtil.setPotion(new ItemStack(recipe.input.get()), potion)), EmiIngredient.of(recipe.ingredient), + EmiStack.of(PotionUtil.setPotion(new ItemStack(recipe.output.get()), potion)), id)); } }; - if ((recipe.f_43532_.get() instanceof PotionItem)) { + if ((recipe.input.get() instanceof PotionItem)) { EmiPort.getPotionRegistry().streamEntries().forEach(potionRecipeGen); } else { potionRecipeGen.accept(EmiPort.getPotionRegistry().getEntry(Potions.AWKWARD)); From 5ada56cdb7a8e453b4c9e91c374daffebee5c5df Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Tue, 26 Dec 2023 17:50:37 -0600 Subject: [PATCH 20/67] Revert "1.20.4 CI" This reverts commit 9d4aec8b488813ae0bacb6fc593306846d20865e. --- .github/workflows/build.yml | 10 +++------- .github/workflows/release.yml | 11 ----------- 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c23031ee..aaff95fe 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,11 +29,8 @@ jobs: - name: Build Fabric run: ./gradlew :fabric:build - - name: Build NeoForge - run: ./gradlew :neoforge:build - -# - name: Build Forge -# run: ./gradlew :forge:build + - name: Build Forge + run: ./gradlew :forge:build - name: Upload Artifacts uses: actions/upload-artifact@v2 @@ -41,5 +38,4 @@ jobs: name: Artifacts path: | fabric/build/libs/ - neoforge/build/libs/ -# forge/build/libs/ \ No newline at end of file + forge/build/libs/ \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1b7ab436..5330ab59 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -84,17 +84,6 @@ jobs: asset_name: emi-${{ steps.composite_version.outputs.composite_version }}+fabric.jar asset_content_type: application/java-archive - - name: Upload NeoForge Release Asset - id: upload_neoforge_release_asset - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./neoforge/build/libs/emi-${{ steps.composite_version.outputs.composite_version }}+neoforge.jar - asset_name: emi-${{ steps.composite_version.outputs.composite_version }}+neoforge.jar - asset_content_type: application/java-archive - # - name: Upload Forge Release Asset # id: upload_forge_release_asset # uses: actions/upload-release-asset@v1 From bfa92e675765b998fa9af36020d69e61fd606c2f Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Tue, 26 Dec 2023 17:50:48 -0600 Subject: [PATCH 21/67] Revert "Use 1.20.4 focus APIs to ensure the currently focused element in the Screen is unfocused when EMI changes focus. (#389)" This reverts commit a287388d989c3d99e4411e5c68c2d120cdbb30e2. --- xplat/src/main/java/dev/emi/emi/EmiPort.java | 10 ---------- .../dev/emi/emi/screen/widget/EmiSearchWidget.java | 11 ++++++----- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/xplat/src/main/java/dev/emi/emi/EmiPort.java b/xplat/src/main/java/dev/emi/emi/EmiPort.java index 2d92d617..44a15f1d 100644 --- a/xplat/src/main/java/dev/emi/emi/EmiPort.java +++ b/xplat/src/main/java/dev/emi/emi/EmiPort.java @@ -7,8 +7,6 @@ import java.util.function.Predicate; import java.util.stream.Stream; -import net.minecraft.client.gui.Element; -import net.minecraft.client.gui.screen.Screen; import org.joml.Matrix4f; import com.mojang.blaze3d.systems.RenderSystem; @@ -173,14 +171,6 @@ public static ItemStack getOutput(Recipe recipe) { } public static void focus(TextFieldWidget widget, boolean focused) { - // Also ensure a current focus-element in the screen is cleared if it changes - MinecraftClient client = MinecraftClient.getInstance(); - if (client != null && client.currentScreen != null) { - var currentFocus = client.currentScreen.getFocused(); - if (!focused && currentFocus == widget || focused && currentFocus != widget) { - client.currentScreen.focusOn(null); - } - } widget.setFocused(focused); } diff --git a/xplat/src/main/java/dev/emi/emi/screen/widget/EmiSearchWidget.java b/xplat/src/main/java/dev/emi/emi/screen/widget/EmiSearchWidget.java index 9de8af71..a0e20bf3 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/widget/EmiSearchWidget.java +++ b/xplat/src/main/java/dev/emi/emi/screen/widget/EmiSearchWidget.java @@ -153,16 +153,16 @@ public void setFocused(boolean focused) { public boolean isFocused() { return isFocused; } - + @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { if (!isMouseOver(mouseX, mouseY) || !EmiConfig.enabled) { - EmiPort.focus(this, false); + setFocused(false); return false; } else { boolean b = super.mouseClicked(mouseX, mouseY, button == 1 ? 0 : button); if (isMouseOver(mouseX, mouseY)) { - EmiPort.focus(this, true); + setFocused(true); } if (this.isFocused()) { if (button == 0) { @@ -174,7 +174,7 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { } } else if (button == 1) { this.setText(""); - EmiPort.focus(this, true); + this.setFocused(true); } } return b; @@ -190,7 +190,8 @@ public boolean keyPressed(int keyCode, int scanCode, int modifiers) { } if ((EmiConfig.focusSearch.matchesKey(keyCode, scanCode) || keyCode == GLFW.GLFW_KEY_ENTER || keyCode == GLFW.GLFW_KEY_ESCAPE)) { - EmiPort.focus(this, false); + this.setFocused(false); + this.setFocused(false); return true; } } From cdd7f276277b71050022c512ec0175b641409827 Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Tue, 26 Dec 2023 17:50:49 -0600 Subject: [PATCH 22/67] Revert "NeoForge 1.20.4 (#386)" This reverts commit 2a7e6837e2768eb47e5ff6a38b3424aa10a4f91a. --- .github/workflows/release.yml | 5 - README.md | 4 - gradle.properties | 4 +- neoforge/build.gradle | 197 ------------ neoforge/gradle.properties | 1 - .../emi/api/neoforge/NeoForgeEmiStack.java | 11 - .../platform/neoforge/EmiAgnosNeoForge.java | 285 ------------------ .../platform/neoforge/EmiClientNeoForge.java | 80 ----- .../emi/platform/neoforge/EmiNeoForge.java | 36 --- .../platform/neoforge/EmiPacketHandler.java | 62 ---- .../resources/META-INF/accesstransformer.cfg | 10 - .../src/main/resources/META-INF/mods.toml | 20 -- .../main/resources/emi-neoforge.mixins.json | 13 - neoforge/src/main/resources/pack.mcmeta | 6 - settings.gradle | 1 - .../java/dev/emi/emi/platform/EmiAgnos.java | 4 - 16 files changed, 1 insertion(+), 738 deletions(-) delete mode 100644 neoforge/build.gradle delete mode 100644 neoforge/gradle.properties delete mode 100644 neoforge/src/main/java/dev/emi/emi/api/neoforge/NeoForgeEmiStack.java delete mode 100644 neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiAgnosNeoForge.java delete mode 100644 neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiClientNeoForge.java delete mode 100644 neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiNeoForge.java delete mode 100644 neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiPacketHandler.java delete mode 100644 neoforge/src/main/resources/META-INF/accesstransformer.cfg delete mode 100644 neoforge/src/main/resources/META-INF/mods.toml delete mode 100644 neoforge/src/main/resources/emi-neoforge.mixins.json delete mode 100644 neoforge/src/main/resources/pack.mcmeta diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5330ab59..c87e55d3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -49,11 +49,6 @@ jobs: # RELEASE: true # run: ./gradlew :forge:build - - name: Build NeoForge - env: - RELEASE: true - run: ./gradlew :neoforge:build - - name: Publish env: MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }} diff --git a/README.md b/README.md index 719e9ef6..b19a5f05 100644 --- a/README.md +++ b/README.md @@ -30,10 +30,6 @@ dependencies { compileOnly fg.deobf("dev.emi:emi-forge:${emi_version}:api") runtimeOnly fg.deobf("dev.emi:emi-forge:${emi_version}") - // NeoForge - compileOnly "dev.emi:emi-neoforge:${emi_version}:api" - runtimeOnly dev.emi:emi-neoforge:${emi_version}" - // Architectury modCompileOnly "dev.emi:emi-xplat-intermediary:${emi_version}:api" diff --git a/gradle.properties b/gradle.properties index 8facc92c..0eb60165 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ org.gradle.jvmargs=-Xmx2048M minecraft_version=1.20.4 -enabled_platforms=fabric,neoforge +enabled_platforms=fabric archives_base_name=emi mod_version=1.0.29 @@ -16,6 +16,4 @@ fabric_api_version=0.91.3+1.20.4 forge_version=1.20.4-49.0.9 -neoforge_version=20.4.56-beta - jei_version=jei-1.20.2-fabric:16.0.0.28 diff --git a/neoforge/build.gradle b/neoforge/build.gradle deleted file mode 100644 index 6d0799db..00000000 --- a/neoforge/build.gradle +++ /dev/null @@ -1,197 +0,0 @@ -buildscript { - repositories { - mavenCentral() - gradlePluginPortal() - } - dependencies { - classpath 'com.modrinth.minotaur:Minotaur:2.4.3' - classpath 'gradle.plugin.com.matthewprenger:CurseGradle:1.4.0' - } -} - -plugins { - id "dev.architectury.loom" - id "com.github.johnrengelman.shadow" version "7.1.2" -} -if (System.getenv("MODRINTH_TOKEN")) { - apply plugin: "com.modrinth.minotaur" -} -if (System.getenv("CURSEFORGE_TOKEN")) { - apply plugin: "com.matthewprenger.cursegradle" -} -evaluationDependsOn ':xplat' - -architectury { - platformSetupLoomIde() - neoForge() -} - -loom { - accessWidenerPath = project(":xplat").loom.accessWidenerPath - - mods { - main { - sourceSet project(':xplat').sourceSets.main - } - } -} - -repositories { - maven { - url "https://maven.neoforged.net/releases/" - content { - includeGroupAndSubgroups "net.neoforged" - includeGroupAndSubgroups "cpw.mods" - } - } -} - -configurations { - common - shadowCommon - compileClasspath.extendsFrom common - runtimeClasspath.extendsFrom common - developmentNeoForge.extendsFrom common -} - -dependencies { - minecraft "com.mojang:minecraft:${rootProject.minecraft_version}" - mappings "net.fabricmc:yarn:${rootProject.yarn_mappings}:v2" - - neoForge "net.neoforged:neoforge:${rootProject.neoforge_version}" - - common(project(path: ":xplat", configuration: "namedElements")) { transitive = false } - shadowCommon(project(path: ":xplat", configuration: "transformProductionNeoForge")) { transitive = false } -} - -processResources { - inputs.property "version", project.version - - filesMatching("META-INF/mods.toml") { - expand "version": project.version - } -} - -shadowJar { - exclude "fabric.mod.json" - exclude "architectury.common.json" - - configurations = [project.configurations.shadowCommon] - archiveClassifier = "dev-shadow" -} - -remapJar { - input.set shadowJar.archiveFile - dependsOn shadowJar -} - -sourcesJar { - def commonSources = project(":xplat").sourcesJar - dependsOn commonSources - from commonSources.archiveFile.map { zipTree(it) } -} - -task filteredSourcesJar(type: Jar) { - archiveClassifier = 'filtered-sources' - dependsOn remapSourcesJar - from zipTree(remapSourcesJar.archivePath) - exclude 'dev/emi/emi/jemi/**' -} - -task apiJar(type: Jar) { - archiveClassifier = 'api' - dependsOn remapJar - from zipTree(remapJar.archivePath) - include 'emi.mixins.json' - include 'emi-neoforge.mixins.json' - include 'emi.accesswidener' - include 'dev/emi/emi/api/**' - exclude 'dev/emi/emi/api/EmiRecipeHandler**' - exclude 'dev/emi/emi/api/stack/FluidEmiStack**' - exclude 'dev/emi/emi/api/stack/ItemEmiStack**' - exclude 'dev/emi/emi/api/stack/EmptyEmiStack**' - exclude 'dev/emi/emi/api/stack/TagEmiIngredient**' - exclude 'dev/emi/emi/api/stack/ListEmiIngredient**' -} - -build.dependsOn filteredSourcesJar -build.dependsOn apiJar - -components.java { - withVariantsFromConfiguration(project.configurations.shadowRuntimeElements) { - skip() - } -} - -publishing { - publications { - maven(MavenPublication) { - artifactId = "${rootProject.name}-${project.name}" - version = project.ext.mavenVersion - artifact(remapJar) { - builtBy remapJar - classifier '' - } - artifact(filteredSourcesJar) { - builtBy filteredSourcesJar - classifier 'sources' - } - artifact(apiJar) { - builtBy apiJar - classifier 'api' - } - } - } - setupRepositories(repositories) -} - -void setupRepositories(RepositoryHandler repositories) { - if (project.hasProperty("mavenUrl")) { - repositories.maven { - url project.mavenUrl - credentials { - username project.mavenUsername - password project.mavenPassword - } - } - } -} - -if (System.getenv("MODRINTH_TOKEN")) { - modrinth { - token = System.getenv("MODRINTH_TOKEN") - projectId = 'emi' - versionNumber = project.version - versionName = project.version - versionType = 'release' - uploadFile = remapJar - gameVersions = [rootProject.minecraft_version] - loaders = ['neoforge'] - detectLoaders = false - changelog = file('../CHANGELOG.md').text - } -} - -if (System.getenv("CURSEFORGE_TOKEN")) { - curseforge { - apiKey = System.getenv("CURSEFORGE_TOKEN") - project { - id = '580555' - releaseType = 'release' - changelogType = 'markdown' - changelog = file('../CHANGELOG.md') - - addGameVersion rootProject.minecraft_version - addGameVersion 'NeoForge' - - mainArtifact(remapJar) { - displayName = 'emi-' + project.version - } - } - options { - javaIntegration = false - forgeGradleIntegration = false - javaVersionAutoDetect = false - } - } -} diff --git a/neoforge/gradle.properties b/neoforge/gradle.properties deleted file mode 100644 index 2914393d..00000000 --- a/neoforge/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -loom.platform=neoforge \ No newline at end of file diff --git a/neoforge/src/main/java/dev/emi/emi/api/neoforge/NeoForgeEmiStack.java b/neoforge/src/main/java/dev/emi/emi/api/neoforge/NeoForgeEmiStack.java deleted file mode 100644 index 7e5823c8..00000000 --- a/neoforge/src/main/java/dev/emi/emi/api/neoforge/NeoForgeEmiStack.java +++ /dev/null @@ -1,11 +0,0 @@ -package dev.emi.emi.api.neoforge; - -import dev.emi.emi.api.stack.EmiStack; -import net.neoforged.neoforge.fluids.FluidStack; - -public final class NeoForgeEmiStack { - - public static EmiStack of(FluidStack stack) { - return EmiStack.of(stack.getFluid(), stack.getTag(), stack.getAmount()); - } -} diff --git a/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiAgnosNeoForge.java b/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiAgnosNeoForge.java deleted file mode 100644 index c8329210..00000000 --- a/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiAgnosNeoForge.java +++ /dev/null @@ -1,285 +0,0 @@ -package dev.emi.emi.platform.neoforge; - -import java.nio.file.Path; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.function.Consumer; -import java.util.stream.Stream; - -import net.minecraft.item.PotionItem; -import net.minecraft.registry.entry.RegistryEntry; -import net.neoforged.neoforge.client.ClientHooks; -import net.neoforged.neoforge.common.CommonHooks; -import org.objectweb.asm.Type; - -import com.google.common.collect.Lists; - -import dev.emi.emi.EmiPort; -import dev.emi.emi.EmiRenderHelper; -import dev.emi.emi.EmiUtil; -import dev.emi.emi.api.EmiEntrypoint; -import dev.emi.emi.api.EmiPlugin; -import dev.emi.emi.api.EmiRegistry; -import dev.emi.emi.api.stack.EmiIngredient; -import dev.emi.emi.api.stack.EmiStack; -import dev.emi.emi.api.stack.FluidEmiStack; -import dev.emi.emi.platform.EmiAgnos; -import dev.emi.emi.recipe.EmiBrewingRecipe; -import dev.emi.emi.registry.EmiPluginContainer; -import dev.emi.emi.runtime.EmiLog; -import it.unimi.dsi.fastutil.objects.Object2IntMap; -import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.tooltip.TooltipComponent; -import net.minecraft.client.render.item.ItemRenderer; -import net.minecraft.client.render.model.BakedModel; -import net.minecraft.client.render.model.BasicBakedModel; -import net.minecraft.client.texture.Sprite; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.fluid.Fluid; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.potion.Potion; -import net.minecraft.potion.PotionUtil; -import net.minecraft.potion.Potions; -import net.minecraft.recipe.BrewingRecipeRegistry; -import net.minecraft.recipe.Ingredient; -import net.minecraft.screen.PlayerScreenHandler; -import net.minecraft.text.Text; -import net.minecraft.util.Identifier; -import net.neoforged.neoforge.client.extensions.common.IClientFluidTypeExtensions; -import net.neoforged.neoforge.common.brewing.BrewingRecipe; -import net.neoforged.neoforge.common.brewing.IBrewingRecipe; -import net.neoforged.neoforge.fluids.FluidStack; -import net.neoforged.fml.ModContainer; -import net.neoforged.fml.ModList; -import net.neoforged.fml.loading.FMLLoader; -import net.neoforged.fml.loading.FMLPaths; -import net.neoforged.neoforgespi.language.ModFileScanData; - -public class EmiAgnosNeoForge extends EmiAgnos { - static { - EmiAgnos.delegate = new EmiAgnosNeoForge(); - } - - @Override - protected boolean isForgeAgnos() { - return true; - } - - @Override - protected String getModNameAgnos(String namespace) { - if (namespace.equals("c")) { - return "Common"; - } - Optional container = ModList.get().getModContainerById(namespace); - if (container.isPresent()) { - return container.get().getModInfo().getDisplayName(); - } - return namespace; - } - - @Override - protected Path getConfigDirectoryAgnos() { - return FMLPaths.CONFIGDIR.get(); - } - - @Override - protected boolean isDevelopmentEnvironmentAgnos() { - return !FMLLoader.isProduction(); - } - - @Override - protected boolean isModLoadedAgnos(String id) { - return ModList.get().isLoaded(id); - } - - @Override - protected List getAllModNamesAgnos() { - return ModList.get().getMods().stream().map(m -> m.getDisplayName()).toList(); - } - - @Override - protected List getPluginsAgnos() { - List containers = Lists.newArrayList(); - Type entrypointType = Type.getType(EmiEntrypoint.class); - for (ModFileScanData data : ModList.get().getAllScanData()) { - for (ModFileScanData.AnnotationData annot : data.getAnnotations()) { - try { - if (entrypointType.equals(annot.annotationType())) { - Class clazz = Class.forName(annot.memberName()); - if (EmiPlugin.class.isAssignableFrom(clazz)) { - Class pluginClass = clazz.asSubclass(EmiPlugin.class); - EmiPlugin plugin = pluginClass.getConstructor().newInstance(); - String id = data.getIModInfoData().get(0).getMods().get(0).getModId(); - containers.add(new EmiPluginContainer(plugin, id)); - } else { - EmiLog.error("EmiEntrypoint " + annot.memberName() + " does not implement EmiPlugin"); - } - } - } catch (Throwable t) { - EmiLog.error("Exception constructing entrypoint:"); - t.printStackTrace(); - } - } - } - return containers; - } - - @Override - protected void addBrewingRecipesAgnos(EmiRegistry registry) { - for (Ingredient ingredient : BrewingRecipeRegistry.POTION_TYPES) { - for (ItemStack stack : ingredient.getMatchingStacks()) { - String pid = EmiUtil.subId(stack.getItem()); - for (BrewingRecipeRegistry.Recipe recipe : BrewingRecipeRegistry.POTION_RECIPES) { - try { - if (recipe.ingredient.getMatchingStacks().length > 0) { - Identifier id = new Identifier("emi", "/brewing/" + pid - + "/" + EmiUtil.subId(recipe.ingredient.getMatchingStacks()[0].getItem()) - + "/" + EmiUtil.subId(EmiPort.getPotionRegistry().getId(recipe.input)) - + "/" + EmiUtil.subId(EmiPort.getPotionRegistry().getId(recipe.output))); - registry.addRecipe(new EmiBrewingRecipe( - EmiStack.of(PotionUtil.setPotion(stack.copy(), recipe.input)), EmiIngredient.of(recipe.ingredient), - EmiStack.of(PotionUtil.setPotion(stack.copy(), recipe.output)), id)); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - } - } - - for (BrewingRecipeRegistry.Recipe recipe : BrewingRecipeRegistry.ITEM_RECIPES) { - try { - if (recipe.ingredient.getMatchingStacks().length > 0) { - String gid = EmiUtil.subId(recipe.ingredient.getMatchingStacks()[0].getItem()); - String iid = EmiUtil.subId(recipe.input); - String oid = EmiUtil.subId(recipe.output); - Consumer> potionRecipeGen = entry -> { - Potion potion = entry.value(); - if (potion == Potions.EMPTY) { - return; - } - if (BrewingRecipeRegistry.isBrewable(potion)) { - Identifier id = new Identifier("emi", "brewing/item/" - + EmiUtil.subId(entry.getKey().get().getValue()) + "/" + gid + "/" + iid + "/" + oid); - registry.addRecipe(new EmiBrewingRecipe( - EmiStack.of(PotionUtil.setPotion(new ItemStack(recipe.input), potion)), EmiIngredient.of(recipe.ingredient), - EmiStack.of(PotionUtil.setPotion(new ItemStack(recipe.output), potion)), id)); - } - }; - if ((recipe.input instanceof PotionItem)) { - EmiPort.getPotionRegistry().streamEntries().forEach(potionRecipeGen); - } else { - potionRecipeGen.accept(EmiPort.getPotionRegistry().getEntry(Potions.AWKWARD)); - } - - } - } catch (Exception e) { - e.printStackTrace(); - } - } - for (IBrewingRecipe ibr : net.neoforged.neoforge.common.brewing.BrewingRecipeRegistry.getRecipes()) { - try { - if (ibr instanceof BrewingRecipe recipe) { - for (ItemStack is : recipe.getInput().getMatchingStacks()) { - EmiStack input = EmiStack.of(is); - EmiIngredient ingredient = EmiIngredient.of(recipe.getIngredient()); - EmiStack output = EmiStack.of(recipe.getOutput(is, recipe.getIngredient().getMatchingStacks()[0])); - Identifier id = new Identifier("emi", "brewing/neoforge/" - + EmiUtil.subId(input.getId()) + "/" - + EmiUtil.subId(ingredient.getEmiStacks().get(0).getId()) + "/" - + EmiUtil.subId(output.getId())); - registry.addRecipe(new EmiBrewingRecipe(input, ingredient, output, id)); - } - } - } catch (Exception e) { - e.printStackTrace(); - } - } - } - - @Override - @SuppressWarnings("unchecked") - protected List getAllModAuthorsAgnos() { - return ModList.get().getMods().stream().flatMap(m -> { - Optional opt = m.getConfig().getConfigElement("authors"); - if (opt.isPresent()) { - Object obj = opt.get(); - if (obj instanceof String authors) { - return Lists.newArrayList(authors.split("\\,")).stream().map(s -> s.trim()); - } else if (obj instanceof List list) { - if (list.size() > 0 && list.get(0) instanceof String) { - List authors = (List) list; - return authors.stream(); - } - } - } - return Stream.empty(); - }).distinct().toList(); - } - - @Override - protected List getItemTooltipAgnos(ItemStack stack) { - MinecraftClient client = MinecraftClient.getInstance(); - return ClientHooks.gatherTooltipComponents(stack, Screen.getTooltipFromItem(client, stack), stack.getTooltipData(), 0, Integer.MAX_VALUE, Integer.MAX_VALUE, client.textRenderer); - } - - @Override - protected Text getFluidNameAgnos(Fluid fluid, NbtCompound nbt) { - return new FluidStack(fluid, 1000, nbt).getDisplayName(); - } - - @Override - protected List getFluidTooltipAgnos(Fluid fluid, NbtCompound nbt) { - return List.of(getFluidName(fluid, nbt)); - } - - @Override - protected boolean isFloatyFluidAgnos(FluidEmiStack stack) { - FluidStack fs = new FluidStack(stack.getKeyOfType(Fluid.class), 1000, stack.getNbt()); - return fs.getFluid().getFluidType().isLighterThanAir(); - } - - @Override - protected void renderFluidAgnos(FluidEmiStack stack, MatrixStack matrices, int x, int y, float delta, int xOff, int yOff, int width, int height) { - FluidStack fs = new FluidStack(stack.getKeyOfType(Fluid.class), 1000, stack.getNbt()); - IClientFluidTypeExtensions ext = IClientFluidTypeExtensions.of(fs.getFluid()); - Identifier texture = ext.getStillTexture(fs); - int color = ext.getTintColor(fs); - MinecraftClient client = MinecraftClient.getInstance(); - Sprite sprite = client.getSpriteAtlas(PlayerScreenHandler.BLOCK_ATLAS_TEXTURE).apply(texture); - EmiRenderHelper.drawTintedSprite(matrices, sprite, color, x, y, xOff, yOff, width, height); - } - - @Override - protected EmiStack createFluidStackAgnos(Object object) { - if (object instanceof FluidStack f) { - return EmiStack.of(f.getFluid(), f.getTag(), f.getAmount()); - } - return EmiStack.EMPTY; - } - - @Override - protected boolean canBatchAgnos(ItemStack stack) { - MinecraftClient client = MinecraftClient.getInstance(); - ItemRenderer ir = client.getItemRenderer(); - BakedModel model = ir.getModel(stack, client.world, null, 0); - return model != null && model.getClass() == BasicBakedModel.class; - } - - @Override - protected Map getFuelMapAgnos() { - Object2IntMap fuelMap = new Object2IntOpenHashMap<>(); - for (Item item : EmiPort.getItemRegistry()) { - int time = CommonHooks.getBurnTime(item.getDefaultStack(), null); - if (time > 0) { - fuelMap.put(item, time); - } - } - return fuelMap; - } -} diff --git a/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiClientNeoForge.java b/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiClientNeoForge.java deleted file mode 100644 index e2510f31..00000000 --- a/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiClientNeoForge.java +++ /dev/null @@ -1,80 +0,0 @@ -package dev.emi.emi.platform.neoforge; - -import java.util.Arrays; - -import dev.emi.emi.EmiPort; -import dev.emi.emi.data.EmiData; -import dev.emi.emi.network.EmiNetwork; -import dev.emi.emi.platform.EmiClient; -import dev.emi.emi.registry.EmiTags; -import dev.emi.emi.runtime.EmiDrawContext; -import dev.emi.emi.runtime.EmiReloadManager; -import dev.emi.emi.screen.ConfigScreen; -import dev.emi.emi.screen.EmiScreen; -import dev.emi.emi.screen.EmiScreenManager; -import dev.emi.emi.screen.StackBatcher; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.ingame.HandledScreen; -import net.neoforged.api.distmarker.Dist; -import net.neoforged.bus.api.SubscribeEvent; -import net.neoforged.neoforge.client.ConfigScreenHandler; -import net.neoforged.neoforge.client.NeoForgeRenderTypes; -import net.neoforged.neoforge.client.event.ContainerScreenEvent; -import net.neoforged.neoforge.client.event.ModelEvent; -import net.neoforged.neoforge.client.event.RecipesUpdatedEvent; -import net.neoforged.neoforge.client.event.RegisterClientReloadListenersEvent; -import net.neoforged.neoforge.common.NeoForge; -import net.neoforged.neoforge.event.TagsUpdatedEvent; -import net.neoforged.fml.ModLoadingContext; -import net.neoforged.fml.common.Mod; -import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent; -import net.neoforged.neoforge.network.PacketDistributor; - -@Mod.EventBusSubscriber(modid = "emi", bus = Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT) -public class EmiClientNeoForge { - - @SubscribeEvent - public static void clientInit(FMLClientSetupEvent event) { - StackBatcher.EXTRA_RENDER_LAYERS.addAll(Arrays.stream(NeoForgeRenderTypes.values()).map(f -> f.get()).toList()); - EmiClient.init(); - EmiNetwork.initClient(packet -> EmiPacketHandler.CHANNEL.send(PacketDistributor.SERVER.noArg(), packet)); - NeoForge.EVENT_BUS.addListener(EmiClientNeoForge::recipesReloaded); - NeoForge.EVENT_BUS.addListener(EmiClientNeoForge::tagsReloaded); - NeoForge.EVENT_BUS.addListener(EmiClientNeoForge::renderScreenForeground); - ModLoadingContext.get().registerExtensionPoint(ConfigScreenHandler.ConfigScreenFactory.class, - () -> new ConfigScreenHandler.ConfigScreenFactory((client, last) -> new ConfigScreen(last))); - } - - @SubscribeEvent - public static void registerAdditionalModels(ModelEvent.RegisterAdditional event) { - MinecraftClient client = MinecraftClient.getInstance(); - EmiTags.registerTagModels(client.getResourceManager(), event::register); - } - - @SubscribeEvent - public static void registerResourceReloaders(RegisterClientReloadListenersEvent event) { - EmiData.init(reloader -> event.registerReloadListener(reloader)); - } - - public static void recipesReloaded(RecipesUpdatedEvent event) { - EmiReloadManager.reloadRecipes(); - } - - public static void tagsReloaded(TagsUpdatedEvent event) { - EmiReloadManager.reloadTags(); - } - - public static void renderScreenForeground(ContainerScreenEvent.Render.Foreground event) { - EmiDrawContext context = EmiDrawContext.wrap(event.getGuiGraphics()); - HandledScreen screen = event.getContainerScreen(); - if (screen instanceof EmiScreen emi) { - MinecraftClient client = MinecraftClient.getInstance(); - context.push(); - context.matrices().translate(-emi.emi$getLeft(), -emi.emi$getTop(), 0.0); - EmiPort.setPositionTexShader(); - EmiScreenManager.render(context, event.getMouseX(), event.getMouseY(), client.getTickDelta()); - EmiScreenManager.drawForeground(context, event.getMouseX(), event.getMouseY(), client.getTickDelta()); - context.pop(); - } - } -} diff --git a/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiNeoForge.java b/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiNeoForge.java deleted file mode 100644 index e38feb1d..00000000 --- a/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiNeoForge.java +++ /dev/null @@ -1,36 +0,0 @@ -package dev.emi.emi.platform.neoforge; - -import dev.emi.emi.network.EmiNetwork; -import dev.emi.emi.network.PingS2CPacket; -import dev.emi.emi.platform.EmiMain; -import dev.emi.emi.registry.EmiCommands; -import net.minecraft.server.network.ServerPlayerEntity; -import net.neoforged.neoforge.common.NeoForge; -import net.neoforged.neoforge.event.RegisterCommandsEvent; -import net.neoforged.neoforge.event.entity.player.PlayerEvent; -import net.neoforged.fml.common.Mod; -import net.neoforged.neoforge.network.PacketDistributor; - -@Mod("emi") -public class EmiNeoForge { - - public EmiNeoForge() { - EmiMain.init(); - EmiPacketHandler.init(); - EmiNetwork.initServer((player, packet) -> { - EmiPacketHandler.CHANNEL.send(PacketDistributor.PLAYER.with(() -> player), packet); - }); - NeoForge.EVENT_BUS.addListener(this::registerCommands); - NeoForge.EVENT_BUS.addListener(this::playerConnect); - } - - public void registerCommands(RegisterCommandsEvent event) { - EmiCommands.registerCommands(event.getDispatcher()); - } - - public void playerConnect(PlayerEvent.PlayerLoggedInEvent event) { - if (event.getEntity() instanceof ServerPlayerEntity spe) { - EmiNetwork.sendToClient(spe, new PingS2CPacket()); - } - } -} diff --git a/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiPacketHandler.java b/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiPacketHandler.java deleted file mode 100644 index 4ec9855f..00000000 --- a/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiPacketHandler.java +++ /dev/null @@ -1,62 +0,0 @@ -package dev.emi.emi.platform.neoforge; - -import java.util.function.BiConsumer; - -import dev.emi.emi.network.CommandS2CPacket; -import dev.emi.emi.network.CreateItemC2SPacket; -import dev.emi.emi.network.EmiChessPacket; -import dev.emi.emi.network.FillRecipeC2SPacket; -import dev.emi.emi.network.PingS2CPacket; -import net.minecraft.client.MinecraftClient; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.util.Identifier; -import net.neoforged.neoforge.network.NetworkRegistry; -import net.neoforged.neoforge.network.PlayNetworkDirection; -import net.neoforged.neoforge.network.simple.MessageFunctions; -import net.neoforged.neoforge.network.simple.SimpleChannel; - -public class EmiPacketHandler { - public static final SimpleChannel CHANNEL = NetworkRegistry.ChannelBuilder.named(new Identifier("emi:emi")) - .networkProtocolVersion(() -> "1") - .clientAcceptedVersions((version) -> true) - .serverAcceptedVersions((version) -> true) - .simpleChannel(); - - public static void init() { - int i = 0; - CHANNEL.messageBuilder(FillRecipeC2SPacket.class, i++, PlayNetworkDirection.PLAY_TO_SERVER) - .encoder(FillRecipeC2SPacket::write).decoder(FillRecipeC2SPacket::new) - .consumerMainThread(serverHandler(FillRecipeC2SPacket::apply)).add(); - CHANNEL.messageBuilder(CreateItemC2SPacket.class, i++, PlayNetworkDirection.PLAY_TO_SERVER) - .encoder(CreateItemC2SPacket::write).decoder(CreateItemC2SPacket::new) - .consumerMainThread(serverHandler(CreateItemC2SPacket::apply)).add(); - CHANNEL.messageBuilder(EmiChessPacket.C2S.class, i++, PlayNetworkDirection.PLAY_TO_SERVER) - .encoder(EmiChessPacket.C2S::write).decoder(EmiChessPacket.C2S::new) - .consumerMainThread(serverHandler(EmiChessPacket.C2S::apply)).add(); - - CHANNEL.messageBuilder(PingS2CPacket.class, i++, PlayNetworkDirection.PLAY_TO_CLIENT) - .encoder(PingS2CPacket::write).decoder(PingS2CPacket::new) - .consumerMainThread(clientHandler(PingS2CPacket::apply)).add(); - CHANNEL.messageBuilder(CommandS2CPacket.class, i++, PlayNetworkDirection.PLAY_TO_CLIENT) - .encoder(CommandS2CPacket::write).decoder(CommandS2CPacket::new) - .consumerMainThread(clientHandler(CommandS2CPacket::apply)).add(); - CHANNEL.messageBuilder(EmiChessPacket.S2C.class, i++, PlayNetworkDirection.PLAY_TO_CLIENT) - .encoder(EmiChessPacket.S2C::write).decoder(EmiChessPacket.S2C::new) - .consumerMainThread(clientHandler(EmiChessPacket.S2C::apply)).add(); - } - - private static MessageFunctions.MessageConsumer serverHandler(BiConsumer handler) { - return (t, context) -> { - handler.accept(t, context.getSender()); - context.setPacketHandled(true); - }; - } - - private static MessageFunctions.MessageConsumer clientHandler(BiConsumer handler) { - return (t, context) -> { - MinecraftClient client = MinecraftClient.getInstance(); - handler.accept(t, client.player); - context.setPacketHandled(true); - }; - } -} diff --git a/neoforge/src/main/resources/META-INF/accesstransformer.cfg b/neoforge/src/main/resources/META-INF/accesstransformer.cfg deleted file mode 100644 index b3469b39..00000000 --- a/neoforge/src/main/resources/META-INF/accesstransformer.cfg +++ /dev/null @@ -1,10 +0,0 @@ -public net.minecraft.world.item.alchemy.PotionBrewing$Mix - -public net.minecraft.world.item.alchemy.PotionBrewing POTION_MIXES -public net.minecraft.world.item.alchemy.PotionBrewing CONTAINER_MIXES -public net.minecraft.world.item.alchemy.PotionBrewing ALLOWED_CONTAINERS - -public net.minecraft.client.gui.screens.Screen addWidget(Lnet/minecraft/client/gui/components/events/GuiEventListener;)Lnet/minecraft/client/gui/components/events/GuiEventListener; - -public net.minecraft.client.gui.components.AbstractWidget x -public net.minecraft.client.gui.components.AbstractWidget y diff --git a/neoforge/src/main/resources/META-INF/mods.toml b/neoforge/src/main/resources/META-INF/mods.toml deleted file mode 100644 index 381524b2..00000000 --- a/neoforge/src/main/resources/META-INF/mods.toml +++ /dev/null @@ -1,20 +0,0 @@ -modLoader = "javafml" -loaderVersion = "[1,)" -#issueTrackerURL = "" -license = "MIT" - -[[mixins]] -config="emi.mixins.json" - -[[mixins]] -config="emi-neoforge.mixins.json" - -[[mods]] -modId = "emi" -version = "${version}" -displayName = "EMI" -authors = "Emi" -description = ''' -A featureful and accessible item and recipe viewer -''' -logoFile = "icon.png" \ No newline at end of file diff --git a/neoforge/src/main/resources/emi-neoforge.mixins.json b/neoforge/src/main/resources/emi-neoforge.mixins.json deleted file mode 100644 index 795d9747..00000000 --- a/neoforge/src/main/resources/emi-neoforge.mixins.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "required": true, - "minVersion": "0.8", - "package": "dev.emi.emi.mixin.neoforge", - "compatibilityLevel": "JAVA_17", - "client": [ - ], - "mixins": [ - ], - "injectors": { - "defaultRequire": 1 - } -} \ No newline at end of file diff --git a/neoforge/src/main/resources/pack.mcmeta b/neoforge/src/main/resources/pack.mcmeta deleted file mode 100644 index b88925c4..00000000 --- a/neoforge/src/main/resources/pack.mcmeta +++ /dev/null @@ -1,6 +0,0 @@ -{ - "pack": { - "description": "EMI", - "pack_format": 8 - } -} diff --git a/settings.gradle b/settings.gradle index 844ea16e..678b0436 100644 --- a/settings.gradle +++ b/settings.gradle @@ -11,6 +11,5 @@ include("xplat") include("xplat:mojmap") include("fabric") //include("forge") -include("neoforge") rootProject.name = "emi" diff --git a/xplat/src/main/java/dev/emi/emi/platform/EmiAgnos.java b/xplat/src/main/java/dev/emi/emi/platform/EmiAgnos.java index b9532c8f..a6596337 100644 --- a/xplat/src/main/java/dev/emi/emi/platform/EmiAgnos.java +++ b/xplat/src/main/java/dev/emi/emi/platform/EmiAgnos.java @@ -28,10 +28,6 @@ public abstract class EmiAgnos { Class.forName("dev.emi.emi.platform.forge.EmiAgnosForge"); } catch (Throwable t) { } - try { - Class.forName("dev.emi.emi.platform.neoforge.EmiAgnosNeoForge"); - } catch (Throwable t) { - } } public static boolean isForge() { From 9b7c8ee02daeef7269cf136f5f8f2cddbe17d676 Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Tue, 26 Dec 2023 17:50:50 -0600 Subject: [PATCH 23/67] Revert "Temporarily remove more forge publishing" This reverts commit e60bfd947e122f4a768f50ec1c4481733f6083ff. --- .github/workflows/release.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c87e55d3..8997b446 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -79,13 +79,13 @@ jobs: asset_name: emi-${{ steps.composite_version.outputs.composite_version }}+fabric.jar asset_content_type: application/java-archive -# - name: Upload Forge Release Asset -# id: upload_forge_release_asset -# uses: actions/upload-release-asset@v1 -# env: -# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -# with: -# upload_url: ${{ steps.create_release.outputs.upload_url }} -# asset_path: ./forge/build/libs/emi-${{ steps.composite_version.outputs.composite_version }}+forge.jar -# asset_name: emi-${{ steps.composite_version.outputs.composite_version }}+forge.jar -# asset_content_type: application/java-archive \ No newline at end of file + - name: Upload Forge Release Asset + id: upload_forge_release_asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./forge/build/libs/emi-${{ steps.composite_version.outputs.composite_version }}+forge.jar + asset_name: emi-${{ steps.composite_version.outputs.composite_version }}+forge.jar + asset_content_type: application/java-archive \ No newline at end of file From 0c43babdaa93db41925afbee9af7e269d89652ea Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Tue, 26 Dec 2023 17:50:52 -0600 Subject: [PATCH 24/67] Revert "1.20.4 fabric" This reverts commit 52f20befdfa9a60fa3f3c12a76162b7a3ab1db3c. --- .github/workflows/release.yml | 8 +++--- gradle.properties | 12 ++++----- settings.gradle | 2 +- .../mixin/AbstractInventoryScreenMixin.java | 2 +- .../emi/emi/network/CreateItemC2SPacket.java | 4 +-- .../emi/screen/widget/EmiSearchWidget.java | 4 +-- .../screen/widget/ResolutionButtonWidget.java | 27 +++++++++++-------- .../emi/screen/widget/SizedButtonWidget.java | 2 +- .../widget/config/ConfigJumpButton.java | 4 +-- 9 files changed, 35 insertions(+), 30 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8997b446..24898b3f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -44,10 +44,10 @@ jobs: RELEASE: true run: ./gradlew :fabric:build -# - name: Build Forge -# env: -# RELEASE: true -# run: ./gradlew :forge:build + - name: Build Forge + env: + RELEASE: true + run: ./gradlew :forge:build - name: Publish env: diff --git a/gradle.properties b/gradle.properties index 0eb60165..42ae174d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ org.gradle.jvmargs=-Xmx2048M -minecraft_version=1.20.4 -enabled_platforms=fabric +minecraft_version=1.20.2 +enabled_platforms=fabric,forge archives_base_name=emi mod_version=1.0.29 @@ -9,11 +9,11 @@ maven_group=dev.emi architectury_version=4.9.83 -yarn_mappings=1.20.4+build.3 +yarn_mappings=1.20.2+build.2 -fabric_loader_version=0.15.2 -fabric_api_version=0.91.3+1.20.4 +fabric_loader_version=0.14.22 +fabric_api_version=0.89.2+1.20.2 -forge_version=1.20.4-49.0.9 +forge_version=1.20.2-48.1.0 jei_version=jei-1.20.2-fabric:16.0.0.28 diff --git a/settings.gradle b/settings.gradle index 678b0436..275074c5 100644 --- a/settings.gradle +++ b/settings.gradle @@ -10,6 +10,6 @@ pluginManagement { include("xplat") include("xplat:mojmap") include("fabric") -//include("forge") +include("forge") rootProject.name = "emi" diff --git a/xplat/src/main/java/dev/emi/emi/mixin/AbstractInventoryScreenMixin.java b/xplat/src/main/java/dev/emi/emi/mixin/AbstractInventoryScreenMixin.java index bbf83007..4c791505 100644 --- a/xplat/src/main/java/dev/emi/emi/mixin/AbstractInventoryScreenMixin.java +++ b/xplat/src/main/java/dev/emi/emi/mixin/AbstractInventoryScreenMixin.java @@ -117,7 +117,7 @@ private Collection drawStatusEffects(Collection 1) { - List list = List.of(this.getStatusEffectDescription(hovered), StatusEffectUtil.getDurationText(hovered, 1.0f, 1.0f)); + List list = List.of(this.getStatusEffectDescription(hovered), StatusEffectUtil.getDurationText(hovered, 1.0f)); context.raw().drawTooltip(client.textRenderer, list, Optional.empty(), mouseX, Math.max(mouseY, 16)); } } diff --git a/xplat/src/main/java/dev/emi/emi/network/CreateItemC2SPacket.java b/xplat/src/main/java/dev/emi/emi/network/CreateItemC2SPacket.java index 1f644313..42bf390b 100644 --- a/xplat/src/main/java/dev/emi/emi/network/CreateItemC2SPacket.java +++ b/xplat/src/main/java/dev/emi/emi/network/CreateItemC2SPacket.java @@ -30,11 +30,11 @@ public void apply(PlayerEntity player) { if ((player.hasPermissionLevel(2) || player.isCreative()) && player.currentScreenHandler != null) { if (stack.isEmpty()) { if (mode == 1 && !player.currentScreenHandler.getCursorStack().isEmpty()) { - EmiLog.info(player.getName() + " deleted " + player.currentScreenHandler.getCursorStack()); + EmiLog.info(player.getEntityName() + " deleted " + player.currentScreenHandler.getCursorStack()); player.currentScreenHandler.setCursorStack(stack); } } else { - EmiLog.info(player.getName() + " cheated in " + stack); + EmiLog.info(player.getEntityName() + " cheated in " + stack); if (mode == 0) { player.getInventory().offerOrDrop(stack); } else if (mode == 1) { diff --git a/xplat/src/main/java/dev/emi/emi/screen/widget/EmiSearchWidget.java b/xplat/src/main/java/dev/emi/emi/screen/widget/EmiSearchWidget.java index a0e20bf3..bc2efd97 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/widget/EmiSearchWidget.java +++ b/xplat/src/main/java/dev/emi/emi/screen/widget/EmiSearchWidget.java @@ -199,7 +199,7 @@ public boolean keyPressed(int keyCode, int scanCode, int modifiers) { } @Override - public void renderWidget(DrawContext raw, int mouseX, int mouseY, float delta) { + public void render(DrawContext raw, int mouseX, int mouseY, float delta) { EmiDrawContext context = EmiDrawContext.wrap(raw); this.setEditable(EmiConfig.enabled); String lower = getText().toLowerCase(); @@ -230,7 +230,7 @@ public void renderWidget(DrawContext raw, int mouseX, int mouseY, float delta) { } if (EmiConfig.enabled) { - super.renderWidget(context.raw(), mouseX, mouseY, delta); + super.render(context.raw(), mouseX, mouseY, delta); if (highlight) { int border = 0xffeeee00; context.fill(this.x - 1, this.y - 1, this.width + 2, 1, border); diff --git a/xplat/src/main/java/dev/emi/emi/screen/widget/ResolutionButtonWidget.java b/xplat/src/main/java/dev/emi/emi/screen/widget/ResolutionButtonWidget.java index e4d98a7a..fb5cb982 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/widget/ResolutionButtonWidget.java +++ b/xplat/src/main/java/dev/emi/emi/screen/widget/ResolutionButtonWidget.java @@ -29,9 +29,24 @@ public ResolutionButtonWidget(int x, int y, int width, int height, EmiIngredient this.stack = stack; this.hoveredWidget = hoveredWidget; } + + @Override + public void render(DrawContext raw, int mouseX, int mouseY, float delta) { + super.render(raw, mouseX, mouseY, delta); + if (this.isHovered()) { + MinecraftClient client = MinecraftClient.getInstance(); + raw.drawTooltip(client.textRenderer, List.of( + EmiPort.translatable("tooltip.emi.resolution"), + EmiPort.translatable("tooltip.emi.select_resolution"), + EmiPort.translatable("tooltip.emi.default_resolution"), + EmiPort.translatable("tooltip.emi.clear_resolution") + ), mouseX, mouseY); + } + stack.render(raw, x + 1, y + 1, delta); + } @Override - public void renderWidget(DrawContext raw, int mouseX, int mouseY, float delta) { + public void renderButton(DrawContext raw, int mouseX, int mouseY, float delta) { EmiDrawContext context = EmiDrawContext.wrap(raw); int u = 0; if (this.isHovered()) { @@ -45,15 +60,5 @@ public void renderWidget(DrawContext raw, int mouseX, int mouseY, float delta) { } EmiTexture.SLOT.render(context.raw(), x, y, delta); context.drawTexture(EmiRenderHelper.WIDGETS, x, y, u, 128, width, height); - if (this.isHovered()) { - MinecraftClient client = MinecraftClient.getInstance(); - raw.drawTooltip(client.textRenderer, List.of( - EmiPort.translatable("tooltip.emi.resolution"), - EmiPort.translatable("tooltip.emi.select_resolution"), - EmiPort.translatable("tooltip.emi.default_resolution"), - EmiPort.translatable("tooltip.emi.clear_resolution") - ), mouseX, mouseY); - } - stack.render(raw, x + 1, y + 1, delta); } } diff --git a/xplat/src/main/java/dev/emi/emi/screen/widget/SizedButtonWidget.java b/xplat/src/main/java/dev/emi/emi/screen/widget/SizedButtonWidget.java index d7d8b02e..590190f1 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/widget/SizedButtonWidget.java +++ b/xplat/src/main/java/dev/emi/emi/screen/widget/SizedButtonWidget.java @@ -64,7 +64,7 @@ protected int getV(int mouseX, int mouseY) { } @Override - public void renderWidget(DrawContext raw, int mouseX, int mouseY, float delta) { + public void renderButton(DrawContext raw, int mouseX, int mouseY, float delta) { EmiDrawContext context = EmiDrawContext.wrap(raw); RenderSystem.enableDepthTest(); context.drawTexture(texture, this.x, this.y, getU(mouseX, mouseY), getV(mouseX, mouseY), this.width, this.height); diff --git a/xplat/src/main/java/dev/emi/emi/screen/widget/config/ConfigJumpButton.java b/xplat/src/main/java/dev/emi/emi/screen/widget/config/ConfigJumpButton.java index bfd45560..5ff4cc8c 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/widget/config/ConfigJumpButton.java +++ b/xplat/src/main/java/dev/emi/emi/screen/widget/config/ConfigJumpButton.java @@ -21,12 +21,12 @@ protected int getV(int mouseX, int mouseY) { } @Override - public void renderWidget(DrawContext raw, int mouseX, int mouseY, float delta) { + public void renderButton(DrawContext raw, int mouseX, int mouseY, float delta) { EmiDrawContext context = EmiDrawContext.wrap(raw); if (this.isMouseOver(mouseX, mouseY)) { context.setColor(0.5f, 0.6f, 1f); } - super.renderWidget(raw, mouseX, mouseY, delta); + super.renderButton(raw, mouseX, mouseY, delta); context.resetColor(); } } From 6b94e0348d512a45ced583ba00320baa20f395ef Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Tue, 26 Dec 2023 17:57:44 -0600 Subject: [PATCH 25/67] Adjustment for older versions --- xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java b/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java index e33c00d1..fe45d3d6 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java @@ -306,7 +306,7 @@ private void addCraftingRecipes(EmiRegistry registry, IRecipeCategory replacements = Sets.newHashSet(); List recipes = Stream.concat( runtime.getRecipeManager().createRecipeLookup(category.getRecipeType()).includeHidden().get(), - registry.getRecipeManager().listAllOfType(net.minecraft.recipe.RecipeType.CRAFTING).stream().map(e -> e.value()) + registry.getRecipeManager().listAllOfType(net.minecraft.recipe.RecipeType.CRAFTING).stream() ).distinct().toList(); for (CraftingRecipe recipe : recipes) { try { From fed74ede57a6c7c3fe74724f0b07592b1eca8346 Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Sun, 14 Jan 2024 13:08:07 -0600 Subject: [PATCH 26/67] Fix forge import --- .../src/main/java/dev/emi/emi/platform/forge/EmiAgnosForge.java | 1 + 1 file changed, 1 insertion(+) diff --git a/forge/src/main/java/dev/emi/emi/platform/forge/EmiAgnosForge.java b/forge/src/main/java/dev/emi/emi/platform/forge/EmiAgnosForge.java index f377b5f3..3a2dc58d 100644 --- a/forge/src/main/java/dev/emi/emi/platform/forge/EmiAgnosForge.java +++ b/forge/src/main/java/dev/emi/emi/platform/forge/EmiAgnosForge.java @@ -59,6 +59,7 @@ import net.minecraftforge.fml.loading.FMLLoader; import net.minecraftforge.fml.loading.FMLPaths; import net.minecraftforge.forgespi.language.ModFileScanData; +import org.apache.commons.lang3.text.WordUtils; public class EmiAgnosForge extends EmiAgnos { static { From 7f4ccc435d9bf5ac42bf7734c8768872b2d05d2b Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Sat, 10 Feb 2024 13:14:23 -0600 Subject: [PATCH 27/67] Remove duplicate renderForeground in forge --- .../src/main/java/dev/emi/emi/platform/forge/EmiClientForge.java | 1 - 1 file changed, 1 deletion(-) diff --git a/forge/src/main/java/dev/emi/emi/platform/forge/EmiClientForge.java b/forge/src/main/java/dev/emi/emi/platform/forge/EmiClientForge.java index e8bb9a50..4a1574ee 100644 --- a/forge/src/main/java/dev/emi/emi/platform/forge/EmiClientForge.java +++ b/forge/src/main/java/dev/emi/emi/platform/forge/EmiClientForge.java @@ -76,7 +76,6 @@ public static void renderScreenForeground(ContainerScreenEvent.Render.Foreground context.matrices().translate(-screen.getGuiLeft(), -screen.getGuiTop(), 0.0); EmiPort.setPositionTexShader(); EmiScreenManager.render(context, event.getMouseX(), event.getMouseY(), client.getTickDelta()); - EmiScreenManager.drawForeground(context, event.getMouseX(), event.getMouseY(), client.getTickDelta()); context.pop(); } } From 0c47a29987d17ddc03442cbfb5814c94407fe496 Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Sat, 10 Feb 2024 13:26:25 -0600 Subject: [PATCH 28/67] Fix forge screen event graphics --- .../java/dev/emi/emi/platform/forge/EmiClientForge.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/forge/src/main/java/dev/emi/emi/platform/forge/EmiClientForge.java b/forge/src/main/java/dev/emi/emi/platform/forge/EmiClientForge.java index a88078bb..de43c942 100644 --- a/forge/src/main/java/dev/emi/emi/platform/forge/EmiClientForge.java +++ b/forge/src/main/java/dev/emi/emi/platform/forge/EmiClientForge.java @@ -81,12 +81,13 @@ public static void renderScreenForeground(ContainerScreenEvent.Render.Foreground RenderSystem.applyModelViewMatrix(); EmiPort.setPositionTexShader(); EmiScreenManager.render(context, event.getMouseX(), event.getMouseY(), client.getTickDelta()); - context.pop(); + viewStack.pop(); + RenderSystem.applyModelViewMatrix(); } } public static void postRenderScreen(ScreenEvent.Render.Post event) { - EmiDrawContext context = EmiDrawContext.wrap(event.getGuiGraphics()); + EmiDrawContext context = EmiDrawContext.wrap(event.getPoseStack()); Screen screen = event.getScreen(); if (!(screen instanceof HandledScreen)) { return; @@ -97,8 +98,7 @@ public static void postRenderScreen(ScreenEvent.Render.Post event) { context.push(); EmiPort.setPositionTexShader(); EmiScreenManager.drawForeground(context, event.getMouseX(), event.getMouseY(), client.getTickDelta()); - viewStack.pop(); - RenderSystem.applyModelViewMatrix(); + context.pop(); } } } From 61a653bdae47322d16013e13f57f9b5599c178cf Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Sat, 10 Feb 2024 13:26:25 -0600 Subject: [PATCH 29/67] Fix forge screen event graphics --- .../main/java/dev/emi/emi/platform/forge/EmiClientForge.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/forge/src/main/java/dev/emi/emi/platform/forge/EmiClientForge.java b/forge/src/main/java/dev/emi/emi/platform/forge/EmiClientForge.java index 80d2aefb..a3dc3250 100644 --- a/forge/src/main/java/dev/emi/emi/platform/forge/EmiClientForge.java +++ b/forge/src/main/java/dev/emi/emi/platform/forge/EmiClientForge.java @@ -76,12 +76,13 @@ public static void renderScreenForeground(ContainerScreenEvent.Render.Foreground context.matrices().translate(-screen.getGuiLeft(), -screen.getGuiTop(), 0.0); EmiPort.setPositionTexShader(); EmiScreenManager.render(context, event.getMouseX(), event.getMouseY(), client.getTickDelta()); - context.pop(); + viewStack.pop(); + RenderSystem.applyModelViewMatrix(); } } public static void postRenderScreen(ScreenEvent.Render.Post event) { - EmiDrawContext context = EmiDrawContext.wrap(event.getGuiGraphics()); + EmiDrawContext context = EmiDrawContext.wrap(event.getPoseStack()); Screen screen = event.getScreen(); if (!(screen instanceof HandledScreen)) { return; From 076bd3d7d6ac796ddc8e99ce53e6bb7ea03510e8 Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Sat, 10 Feb 2024 13:33:21 -0600 Subject: [PATCH 30/67] Fix 1.19.4 forge --- .../main/java/dev/emi/emi/platform/forge/EmiClientForge.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/forge/src/main/java/dev/emi/emi/platform/forge/EmiClientForge.java b/forge/src/main/java/dev/emi/emi/platform/forge/EmiClientForge.java index a3dc3250..fbfa5111 100644 --- a/forge/src/main/java/dev/emi/emi/platform/forge/EmiClientForge.java +++ b/forge/src/main/java/dev/emi/emi/platform/forge/EmiClientForge.java @@ -76,8 +76,7 @@ public static void renderScreenForeground(ContainerScreenEvent.Render.Foreground context.matrices().translate(-screen.getGuiLeft(), -screen.getGuiTop(), 0.0); EmiPort.setPositionTexShader(); EmiScreenManager.render(context, event.getMouseX(), event.getMouseY(), client.getTickDelta()); - viewStack.pop(); - RenderSystem.applyModelViewMatrix(); + context.pop(); } } From 5d1b1d6b90f61554c757747325bf7060b177f07c Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Fri, 22 Mar 2024 20:15:41 -0500 Subject: [PATCH 31/67] Revert "Fix JEMI recipe entry issue" This reverts commit db3c47f91bad7d2ba163f07c605450ad8b4483db. --- gradle.properties | 2 +- xplat/src/main/java/dev/emi/emi/jemi/JemiRecipeHandler.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gradle.properties b/gradle.properties index 83119af5..d9a74429 100644 --- a/gradle.properties +++ b/gradle.properties @@ -16,4 +16,4 @@ fabric_api_version=0.89.2+1.20.2 forge_version=1.20.2-48.1.0 -jei_version=jei-1.20.4-fabric:17.3.0.49 +jei_version=jei-1.20.2-fabric:16.0.0.28 diff --git a/xplat/src/main/java/dev/emi/emi/jemi/JemiRecipeHandler.java b/xplat/src/main/java/dev/emi/emi/jemi/JemiRecipeHandler.java index d2ee8773..ce7f74e4 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/JemiRecipeHandler.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/JemiRecipeHandler.java @@ -213,9 +213,9 @@ private R getRawRecipe(EmiRecipe recipe) { } } if (manager != null) { - Optional> opt = manager.get(recipe.getId()); + Optional> opt = manager.get(recipe.getId()).map(RecipeEntry::value); if (opt.isPresent()) { - RecipeEntry r = opt.get(); + Recipe r = opt.get(); if (type.getRecipeClass().isAssignableFrom(r.getClass())) { return type.getRecipeClass().cast(r); } @@ -223,7 +223,7 @@ private R getRawRecipe(EmiRecipe recipe) { } } if (manager != null) { - Optional> opt = manager.get(recipe.getId()); + Optional> opt = manager.get(recipe.getId()).map(RecipeEntry::value); if (opt.isPresent()) { return (R) opt.get(); } From bddd73038dec2c7860a288f677ff5d46649343da Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Tue, 30 Apr 2024 23:12:22 -0500 Subject: [PATCH 32/67] Revert "Port to 1.20.5 (#518)" This reverts commit aad1f66dda12c52ff3d1a623576471b9bb94a8db. --- .github/workflows/build.yml | 2 +- .github/workflows/release.yml | 2 +- build.gradle | 4 +- .../java/dev/emi/emi/api/FabricEmiStack.java | 4 +- ...lientConfigurationNetworkHandlerMixin.java | 16 ----- .../mixin/ClientPlayNetworkHandlerMixin.java | 2 +- .../SynchronizeRecipesS2CPacketMixin.java | 27 ++++++++ .../BrewingRecipeRegistryRecipeAccessor.java | 20 ++++++ .../emi/platform/fabric/EmiAgnosFabric.java | 56 +++++++-------- .../emi/platform/fabric/EmiClientFabric.java | 19 +++-- .../emi/platform/fabric/EmiMainFabric.java | 23 +++---- .../src/main/resources/emi-fabric.mixins.json | 5 +- gradle.properties | 10 +-- gradle/wrapper/gradle-wrapper.properties | 2 +- neoforge/build.gradle | 8 +-- neoforge/mappings/fix.tiny | 5 -- .../emi/api/neoforge/NeoForgeEmiStack.java | 2 +- .../platform/neoforge/EmiAgnosNeoForge.java | 54 +++++++-------- .../platform/neoforge/EmiClientNeoForge.java | 14 ++-- .../emi/platform/neoforge/EmiNeoForge.java | 2 +- .../platform/neoforge/EmiPacketHandler.java | 69 ++++++++++++------- .../{neoforge.mods.toml => mods.toml} | 0 xplat/src/main/java/dev/emi/emi/EmiPort.java | 25 +++---- .../main/java/dev/emi/emi/VanillaPlugin.java | 31 +++++---- .../dev/emi/emi/api/stack/Comparison.java | 6 +- .../emi/emi/api/stack/EmiRegistryAdapter.java | 10 +-- .../java/dev/emi/emi/api/stack/EmiStack.java | 41 ++++------- .../dev/emi/emi/api/stack/EmptyEmiStack.java | 6 +- .../dev/emi/emi/api/stack/FluidEmiStack.java | 25 +++---- .../dev/emi/emi/api/stack/ItemEmiStack.java | 42 +++++------ .../stack/serializer/EmiStackSerializer.java | 15 ++-- .../dev/emi/emi/api/widget/TankWidget.java | 2 +- .../java/dev/emi/emi/chess/ChessEmiStack.java | 6 +- .../main/java/dev/emi/emi/jemi/JemiStack.java | 12 ++-- .../main/java/dev/emi/emi/jemi/JemiUtil.java | 8 +-- .../emi/jemi/impl/JemiIngredientAcceptor.java | 8 +-- .../dev/emi/emi/mixin/HandledScreenMixin.java | 2 +- .../dev/emi/emi/mixin/ItemStackMixin.java | 6 +- .../java/dev/emi/emi/mixin/MouseMixin.java | 12 ++-- .../BrewingRecipeRegistryAccessor.java | 22 ------ .../dev/emi/emi/network/CommandS2CPacket.java | 5 +- .../emi/emi/network/CreateItemC2SPacket.java | 11 ++- .../dev/emi/emi/network/EmiChessPacket.java | 5 +- .../java/dev/emi/emi/network/EmiNetwork.java | 11 ++- .../java/dev/emi/emi/network/EmiPacket.java | 10 +-- .../emi/emi/network/FillRecipeC2SPacket.java | 16 ++--- .../dev/emi/emi/network/PingS2CPacket.java | 5 +- .../java/dev/emi/emi/platform/EmiAgnos.java | 14 ++-- .../recipe/special/EmiAnvilEnchantRecipe.java | 18 +++-- .../special/EmiAnvilRepairItemRecipe.java | 2 +- .../emi/recipe/special/EmiArmorDyeRecipe.java | 4 +- .../special/EmiBannerDuplicateRecipe.java | 9 +-- .../recipe/special/EmiBannerShieldRecipe.java | 14 ++-- .../recipe/special/EmiBookCloningRecipe.java | 11 ++- .../special/EmiFireworkRocketRecipe.java | 53 +++++++------- .../special/EmiFireworkStarFadeRecipe.java | 35 ++++------ .../recipe/special/EmiFireworkStarRecipe.java | 41 +++++++---- .../EmiGrindstoneDisenchantingBookRecipe.java | 22 ++++-- .../recipe/special/EmiRepairItemRecipe.java | 5 +- .../special/EmiSuspiciousStewRecipe.java | 4 +- .../dev/emi/emi/registry/EmiRecipeFiller.java | 6 +- .../dev/emi/emi/registry/EmiStackList.java | 6 +- .../emi/runtime/EmiScreenshotRecorder.java | 13 ++-- .../java/dev/emi/emi/screen/BoMScreen.java | 12 ++-- .../dev/emi/emi/screen/ConfigEnumScreen.java | 2 +- .../emi/emi/screen/ConfigPresetScreen.java | 2 +- .../java/dev/emi/emi/screen/ConfigScreen.java | 2 +- .../dev/emi/emi/screen/EmiScreenManager.java | 12 ++-- .../java/dev/emi/emi/screen/StackBatcher.java | 8 ++- .../emi/screen/widget/EmiSearchWidget.java | 9 ++- .../emi/screen/widget/config/ListWidget.java | 4 +- .../java/dev/emi/emi/search/EmiSearch.java | 7 +- .../serializer/FluidEmiStackSerializer.java | 7 +- .../serializer/ItemEmiStackSerializer.java | 6 +- xplat/src/main/resources/emi.accesswidener | 4 ++ xplat/src/main/resources/emi.mixins.json | 3 +- 76 files changed, 494 insertions(+), 529 deletions(-) delete mode 100644 fabric/src/main/java/dev/emi/emi/mixin/ClientConfigurationNetworkHandlerMixin.java create mode 100644 fabric/src/main/java/dev/emi/emi/mixin/SynchronizeRecipesS2CPacketMixin.java create mode 100644 fabric/src/main/java/dev/emi/emi/mixin/accessor/BrewingRecipeRegistryRecipeAccessor.java delete mode 100644 neoforge/mappings/fix.tiny rename neoforge/src/main/resources/META-INF/{neoforge.mods.toml => mods.toml} (100%) delete mode 100644 xplat/src/main/java/dev/emi/emi/mixin/accessor/BrewingRecipeRegistryAccessor.java diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9edcb4e1..c23031ee 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,7 +5,7 @@ jobs: build: strategy: matrix: - java: [ 21 ] + java: [ 17 ] runs-on: ubuntu-latest steps: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d91fb426..1b7ab436 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,7 +6,7 @@ jobs: build: strategy: matrix: - java: [ 21 ] + java: [ 17 ] runs-on: ubuntu-latest steps: diff --git a/build.gradle b/build.gradle index ae7f99a0..233b68a2 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ plugins { id "architectury-plugin" version "3.4-SNAPSHOT" - id "dev.architectury.loom" version "1.6-SNAPSHOT" apply false + id "dev.architectury.loom" version "1.4-SNAPSHOT" apply false } architectury { @@ -33,7 +33,7 @@ allprojects { tasks.withType(JavaCompile).configureEach({ options.encoding = "UTF-8" - options.release = 21 + options.release = 17 }) java { diff --git a/fabric/src/main/java/dev/emi/emi/api/FabricEmiStack.java b/fabric/src/main/java/dev/emi/emi/api/FabricEmiStack.java index 1e3e05db..39e7450f 100644 --- a/fabric/src/main/java/dev/emi/emi/api/FabricEmiStack.java +++ b/fabric/src/main/java/dev/emi/emi/api/FabricEmiStack.java @@ -15,10 +15,10 @@ public static EmiStack of(ItemVariant variant, long amount) { } public static EmiStack of(FluidVariant variant) { - return EmiStack.of(variant.getFluid(), variant.getComponents()); + return EmiStack.of(variant.getFluid(), variant.getNbt()); } public static EmiStack of(FluidVariant variant, long amount) { - return EmiStack.of(variant.getFluid(), variant.getComponents(), amount); + return EmiStack.of(variant.getFluid(), variant.getNbt(), amount); } } diff --git a/fabric/src/main/java/dev/emi/emi/mixin/ClientConfigurationNetworkHandlerMixin.java b/fabric/src/main/java/dev/emi/emi/mixin/ClientConfigurationNetworkHandlerMixin.java deleted file mode 100644 index 98beab73..00000000 --- a/fabric/src/main/java/dev/emi/emi/mixin/ClientConfigurationNetworkHandlerMixin.java +++ /dev/null @@ -1,16 +0,0 @@ -package dev.emi.emi.mixin; - -import dev.emi.emi.runtime.EmiReloadManager; -import net.minecraft.client.network.ClientConfigurationNetworkHandler; -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; - -@Mixin(ClientConfigurationNetworkHandler.class) -public class ClientConfigurationNetworkHandlerMixin { - @Inject(at = @At("RETURN"), method = "onSynchronizeTags") - private void refreshTagBasedData(CallbackInfo info) { - EmiReloadManager.reloadTags(); - } -} diff --git a/fabric/src/main/java/dev/emi/emi/mixin/ClientPlayNetworkHandlerMixin.java b/fabric/src/main/java/dev/emi/emi/mixin/ClientPlayNetworkHandlerMixin.java index 0ebd9a84..0b57dc57 100644 --- a/fabric/src/main/java/dev/emi/emi/mixin/ClientPlayNetworkHandlerMixin.java +++ b/fabric/src/main/java/dev/emi/emi/mixin/ClientPlayNetworkHandlerMixin.java @@ -29,7 +29,7 @@ private void onSynchronizeRecipes(SynchronizeRecipesS2CPacket packet, CallbackIn EmiReloadManager.reloadRecipes(); } - @Inject(at = @At("RETURN"), method = "onSynchronizeTags") + @Inject(at = @At("RETURN"), method = "refreshTagBasedData") private void refreshTagBasedData(CallbackInfo info) { EmiReloadManager.reloadTags(); } diff --git a/fabric/src/main/java/dev/emi/emi/mixin/SynchronizeRecipesS2CPacketMixin.java b/fabric/src/main/java/dev/emi/emi/mixin/SynchronizeRecipesS2CPacketMixin.java new file mode 100644 index 00000000..8c66f6f9 --- /dev/null +++ b/fabric/src/main/java/dev/emi/emi/mixin/SynchronizeRecipesS2CPacketMixin.java @@ -0,0 +1,27 @@ +package dev.emi.emi.mixin; + +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.CallbackInfoReturnable; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +import dev.emi.emi.runtime.EmiLog; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.network.packet.s2c.play.SynchronizeRecipesS2CPacket; +import net.minecraft.recipe.Recipe; +import net.minecraft.recipe.RecipeEntry; +import net.minecraft.util.Identifier; + +@Mixin(SynchronizeRecipesS2CPacket.class) +public class SynchronizeRecipesS2CPacketMixin { + + @Inject(at = @At("RETURN"), method = "readRecipe", locals = LocalCapture.CAPTURE_FAILHARD) + private static void readRecipe(PacketByteBuf buf, CallbackInfoReturnable>> info, Identifier serializer, Identifier id) { + RecipeEntry> recipe = info.getReturnValue(); + if (recipe == null) { + EmiLog.error("Recipe " + id + " was deserialized as null using recipe serializer " + serializer + + ", this is breaking vanilla recipe sync, and will prevent EMI from loading recipes"); + } + } +} diff --git a/fabric/src/main/java/dev/emi/emi/mixin/accessor/BrewingRecipeRegistryRecipeAccessor.java b/fabric/src/main/java/dev/emi/emi/mixin/accessor/BrewingRecipeRegistryRecipeAccessor.java new file mode 100644 index 00000000..e635392a --- /dev/null +++ b/fabric/src/main/java/dev/emi/emi/mixin/accessor/BrewingRecipeRegistryRecipeAccessor.java @@ -0,0 +1,20 @@ +package dev.emi.emi.mixin.accessor; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.recipe.BrewingRecipeRegistry; +import net.minecraft.recipe.Ingredient; + +@Mixin(BrewingRecipeRegistry.Recipe.class) +public interface BrewingRecipeRegistryRecipeAccessor { + + @Accessor("input") + Object getInput(); + + @Accessor("ingredient") + Ingredient getIngredient(); + + @Accessor("output") + Object getOutput(); +} diff --git a/fabric/src/main/java/dev/emi/emi/platform/fabric/EmiAgnosFabric.java b/fabric/src/main/java/dev/emi/emi/platform/fabric/EmiAgnosFabric.java index 75b18efb..c40b2856 100644 --- a/fabric/src/main/java/dev/emi/emi/platform/fabric/EmiAgnosFabric.java +++ b/fabric/src/main/java/dev/emi/emi/platform/fabric/EmiAgnosFabric.java @@ -15,7 +15,7 @@ import dev.emi.emi.api.stack.EmiStack; import dev.emi.emi.api.stack.FluidEmiStack; import dev.emi.emi.jemi.JemiUtil; -import dev.emi.emi.mixin.accessor.BrewingRecipeRegistryAccessor; +import dev.emi.emi.mixin.accessor.BrewingRecipeRegistryRecipeAccessor; import dev.emi.emi.platform.EmiAgnos; import dev.emi.emi.recipe.EmiBrewingRecipe; import dev.emi.emi.registry.EmiPluginContainer; @@ -29,18 +29,16 @@ import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariantAttributes; import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.ModContainer; -import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.tooltip.TooltipComponent; import net.minecraft.client.texture.Sprite; import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.component.ComponentChanges; -import net.minecraft.component.ComponentMap; import net.minecraft.fluid.Fluid; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.PotionItem; import net.minecraft.nbt.NbtCompound; import net.minecraft.potion.Potion; +import net.minecraft.potion.PotionUtil; import net.minecraft.potion.Potions; import net.minecraft.recipe.BrewingRecipeRegistry; import net.minecraft.recipe.Ingredient; @@ -110,22 +108,20 @@ protected List getPluginsAgnos() { @Override protected void addBrewingRecipesAgnos(EmiRegistry registry) { - BrewingRecipeRegistry brewingRegistry = MinecraftClient.getInstance().world != null ? MinecraftClient.getInstance().world.getBrewingRecipeRegistry() : BrewingRecipeRegistry.EMPTY; - BrewingRecipeRegistryAccessor brewingRegistryAccess = (BrewingRecipeRegistryAccessor)brewingRegistry; - for (Ingredient ingredient : brewingRegistryAccess.getPotionTypes()) { + for (Ingredient ingredient : BrewingRecipeRegistry.POTION_TYPES) { for (ItemStack stack : ingredient.getMatchingStacks()) { String pid = EmiUtil.subId(stack.getItem()); - for (BrewingRecipeRegistry.Recipe recipe : brewingRegistryAccess.getPotionRecipes()) { + for (BrewingRecipeRegistry.Recipe recipe : BrewingRecipeRegistry.POTION_RECIPES) { try { - Ingredient recipeIngredient = recipe.ingredient(); + Ingredient recipeIngredient = ((BrewingRecipeRegistryRecipeAccessor) recipe).getIngredient(); if (recipeIngredient.getMatchingStacks().length > 0) { Identifier id = new Identifier("emi", "/brewing/" + pid + "/" + EmiUtil.subId(recipeIngredient.getMatchingStacks()[0].getItem()) - + "/" + EmiUtil.subId(EmiPort.getPotionRegistry().getId(recipe.from().value())) - + "/" + EmiUtil.subId(EmiPort.getPotionRegistry().getId(recipe.to().value()))); + + "/" + EmiUtil.subId(EmiPort.getPotionRegistry().getId((Potion) ((BrewingRecipeRegistryRecipeAccessor) recipe).getInput())) + + "/" + EmiUtil.subId(EmiPort.getPotionRegistry().getId((Potion) ((BrewingRecipeRegistryRecipeAccessor) recipe).getOutput()))); registry.addRecipe(new EmiBrewingRecipe( - EmiStack.of(EmiPort.setPotion(stack.copy(), recipe.from().value())), EmiIngredient.of(recipeIngredient), - EmiStack.of(EmiPort.setPotion(stack.copy(), recipe.to().value())), id)); + EmiStack.of(EmiPort.setPotion(stack.copy(), (Potion) ((BrewingRecipeRegistryRecipeAccessor) recipe).getInput())), EmiIngredient.of(recipeIngredient), + EmiStack.of(EmiPort.setPotion(stack.copy(), (Potion) ((BrewingRecipeRegistryRecipeAccessor) recipe).getOutput())), id)); } } catch (Exception e) { e.printStackTrace(); @@ -134,26 +130,30 @@ protected void addBrewingRecipesAgnos(EmiRegistry registry) { } } - for (BrewingRecipeRegistry.Recipe recipe : brewingRegistryAccess.getItemRecipes()) { + for (BrewingRecipeRegistry.Recipe recipe : BrewingRecipeRegistry.ITEM_RECIPES) { try { - Ingredient recipeIngredient = recipe.ingredient(); + Ingredient recipeIngredient = ((BrewingRecipeRegistryRecipeAccessor) recipe).getIngredient(); if (recipeIngredient.getMatchingStacks().length > 0) { String gid = EmiUtil.subId(recipeIngredient.getMatchingStacks()[0].getItem()); - String iid = EmiUtil.subId(recipe.from().value()); - String oid = EmiUtil.subId(recipe.to().value()); + String iid = EmiUtil.subId((Item) ((BrewingRecipeRegistryRecipeAccessor) recipe).getInput()); + String oid = EmiUtil.subId((Item) ((BrewingRecipeRegistryRecipeAccessor) recipe).getOutput()); Consumer> potionRecipeGen = entry -> { - if (brewingRegistry.isBrewable(entry)) { + Potion potion = entry.value(); + if (potion == Potions.EMPTY) { + return; + } + if (BrewingRecipeRegistry.isBrewable(potion)) { Identifier id = new Identifier("emi", "brewing/item/" + EmiUtil.subId(entry.getKey().get().getValue()) + "/" + gid + "/" + iid + "/" + oid); registry.addRecipe(new EmiBrewingRecipe( - EmiStack.of(EmiPort.setPotion(new ItemStack(recipe.from().value()), entry.value())), EmiIngredient.of(recipeIngredient), - EmiStack.of(EmiPort.setPotion(new ItemStack(recipe.to().value()), entry.value())), id)); + EmiStack.of(EmiPort.setPotion(new ItemStack((Item) ((BrewingRecipeRegistryRecipeAccessor) recipe).getInput()), potion)), EmiIngredient.of(recipeIngredient), + EmiStack.of(EmiPort.setPotion(new ItemStack((Item) ((BrewingRecipeRegistryRecipeAccessor) recipe).getOutput()), potion)), id)); } }; - if (recipe.from().value() instanceof PotionItem) { + if ((((BrewingRecipeRegistryRecipeAccessor) recipe).getInput() instanceof PotionItem)) { EmiPort.getPotionRegistry().streamEntries().forEach(potionRecipeGen); } else { - potionRecipeGen.accept(Potions.AWKWARD); + potionRecipeGen.accept(EmiPort.getPotionRegistry().getEntry(Potions.AWKWARD)); } } } catch (Exception e) { @@ -168,24 +168,24 @@ protected List getItemTooltipAgnos(ItemStack stack) { } @Override - protected Text getFluidNameAgnos(Fluid fluid, ComponentChanges componentChanges) { - return FluidVariantAttributes.getName(FluidVariant.of(fluid, componentChanges)); + protected Text getFluidNameAgnos(Fluid fluid, NbtCompound nbt) { + return FluidVariantAttributes.getName(FluidVariant.of(fluid, nbt)); } @Override - protected List getFluidTooltipAgnos(Fluid fluid, ComponentChanges componentChanges) { - return FluidVariantRendering.getTooltip(FluidVariant.of(fluid, componentChanges)); + protected List getFluidTooltipAgnos(Fluid fluid, NbtCompound nbt) { + return FluidVariantRendering.getTooltip(FluidVariant.of(fluid, nbt)); } @Override protected boolean isFloatyFluidAgnos(FluidEmiStack stack) { - FluidVariant fluid = FluidVariant.of(stack.getKeyOfType(Fluid.class), stack.getComponentChanges()); + FluidVariant fluid = FluidVariant.of(stack.getKeyOfType(Fluid.class), stack.getNbt()); return FluidVariantAttributes.isLighterThanAir(fluid); } @Override protected void renderFluidAgnos(FluidEmiStack stack, MatrixStack matrices, int x, int y, float delta, int xOff, int yOff, int width, int height) { - FluidVariant fluid = FluidVariant.of(stack.getKeyOfType(Fluid.class), stack.getComponentChanges()); + FluidVariant fluid = FluidVariant.of(stack.getKeyOfType(Fluid.class), stack.getNbt()); Sprite[] sprites = FluidVariantRendering.getSprites(fluid); if (sprites == null || sprites.length < 1 || sprites[0] == null) { return; diff --git a/fabric/src/main/java/dev/emi/emi/platform/fabric/EmiClientFabric.java b/fabric/src/main/java/dev/emi/emi/platform/fabric/EmiClientFabric.java index 261cf799..6b340ff9 100644 --- a/fabric/src/main/java/dev/emi/emi/platform/fabric/EmiClientFabric.java +++ b/fabric/src/main/java/dev/emi/emi/platform/fabric/EmiClientFabric.java @@ -19,14 +19,9 @@ import net.fabricmc.api.ClientModInitializer; import net.fabricmc.fabric.api.client.model.loading.v1.PreparableModelLoadingPlugin; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; -import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry; import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener; import net.fabricmc.fabric.api.resource.ResourceManagerHelper; import net.minecraft.network.PacketByteBuf; -import net.minecraft.network.RegistryByteBuf; -import net.minecraft.network.codec.PacketCodec; -import net.minecraft.network.codec.PacketDecoder; -import net.minecraft.network.packet.CustomPayload; import net.minecraft.resource.ResourceManager; import net.minecraft.resource.ResourceType; import net.minecraft.util.Identifier; @@ -69,7 +64,9 @@ public Identifier getFabricId() { }); EmiNetwork.initClient(packet -> { - ClientPlayNetworking.send(packet); + PacketByteBuf buf = new PacketByteBuf(Unpooled.buffer()); + packet.write(buf); + ClientPlayNetworking.send(packet.getId(), buf); }); registerPacketReader(EmiNetwork.PING, PingS2CPacket::new); @@ -77,11 +74,11 @@ public Identifier getFabricId() { registerPacketReader(EmiNetwork.CHESS, EmiChessPacket.S2C::new); } - private void registerPacketReader(CustomPayload.Id id, PacketDecoder decode) { - PayloadTypeRegistry.playS2C().register(id, PacketCodec.ofStatic((buf, v) -> v.write(buf), decode)); - ClientPlayNetworking.registerGlobalReceiver(id, (payload, context) -> { - context.client().execute(() -> { - payload.apply(context.client().player); + private void registerPacketReader(Identifier id, Function create) { + ClientPlayNetworking.registerGlobalReceiver(id, (client, handler, buf, sender) -> { + EmiPacket packet = create.apply(buf); + client.execute(() -> { + packet.apply(client.player); }); }); } diff --git a/fabric/src/main/java/dev/emi/emi/platform/fabric/EmiMainFabric.java b/fabric/src/main/java/dev/emi/emi/platform/fabric/EmiMainFabric.java index 9e8cb89c..697da96f 100644 --- a/fabric/src/main/java/dev/emi/emi/platform/fabric/EmiMainFabric.java +++ b/fabric/src/main/java/dev/emi/emi/platform/fabric/EmiMainFabric.java @@ -1,6 +1,5 @@ package dev.emi.emi.platform.fabric; -import java.util.function.BiConsumer; import java.util.function.Function; import dev.emi.emi.network.CreateItemC2SPacket; @@ -14,15 +13,9 @@ import io.netty.buffer.Unpooled; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; -import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry; import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.minecraft.network.PacketByteBuf; -import net.minecraft.network.RegistryByteBuf; -import net.minecraft.network.codec.PacketCodec; -import net.minecraft.network.codec.PacketDecoder; -import net.minecraft.network.codec.PacketEncoder; -import net.minecraft.network.packet.CustomPayload; import net.minecraft.util.Identifier; public class EmiMainFabric implements ModInitializer { @@ -32,7 +25,11 @@ public void onInitialize() { EmiMain.init(); CommandRegistrationCallback.EVENT.register((dispatcher, registry, env) -> EmiCommands.registerCommands(dispatcher)); - EmiNetwork.initServer(ServerPlayNetworking::send); + EmiNetwork.initServer((player, packet) -> { + PacketByteBuf buf = new PacketByteBuf(Unpooled.buffer()); + packet.write(buf); + ServerPlayNetworking.send(player, packet.getId(), buf); + }); registerPacketReader(EmiNetwork.FILL_RECIPE, FillRecipeC2SPacket::new); registerPacketReader(EmiNetwork.CREATE_ITEM, CreateItemC2SPacket::new); @@ -43,11 +40,11 @@ public void onInitialize() { }); } - private void registerPacketReader(CustomPayload.Id id, PacketDecoder decode) { - PayloadTypeRegistry.playC2S().register(id, PacketCodec.ofStatic((buf, v) -> v.write(buf), decode)); - ServerPlayNetworking.registerGlobalReceiver(id, (payload, context) -> { - context.player().getServer().execute(() -> { - ((EmiPacket)payload).apply(context.player()); + private void registerPacketReader(Identifier id, Function create) { + ServerPlayNetworking.registerGlobalReceiver(id, (server, player, networkHandler, buf, sender) -> { + EmiPacket packet = create.apply(buf); + server.execute(() -> { + packet.apply(player); }); }); } diff --git a/fabric/src/main/resources/emi-fabric.mixins.json b/fabric/src/main/resources/emi-fabric.mixins.json index ee23af6e..0bad3d5a 100644 --- a/fabric/src/main/resources/emi-fabric.mixins.json +++ b/fabric/src/main/resources/emi-fabric.mixins.json @@ -6,11 +6,12 @@ "plugin": "dev.emi.emi.mixinsupport.EmiMixinPlugin", "mixins": [], "client": [ + "accessor.BrewingRecipeRegistryRecipeAccessor", "conversion.FluidMixin", "conversion.ItemConvertibleMixin", "conversion.ItemStackMixin", - "ClientConfigurationNetworkHandlerMixin", - "ClientPlayNetworkHandlerMixin" + "ClientPlayNetworkHandlerMixin", + "SynchronizeRecipesS2CPacketMixin" ], "server": [], "injectors": { diff --git a/gradle.properties b/gradle.properties index e0469457..4082b8f2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ org.gradle.jvmargs=-Xmx2048M -minecraft_version=1.20.6 +minecraft_version=1.20.4 enabled_platforms=fabric,neoforge archives_base_name=emi @@ -9,13 +9,13 @@ maven_group=dev.emi architectury_version=4.9.83 -yarn_mappings=1.20.6+build.1 +yarn_mappings=1.20.4+build.3 -fabric_loader_version=0.15.10 -fabric_api_version=0.97.8+1.20.6 +fabric_loader_version=0.15.2 +fabric_api_version=0.91.3+1.20.4 forge_version=1.20.4-49.0.9 -neoforge_version=20.6.2-beta +neoforge_version=20.4.190 jei_version=jei-1.20.4-fabric:17.3.0.49 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 17655d0e..a5952066 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/neoforge/build.gradle b/neoforge/build.gradle index f4bc92d3..e7b2c780 100644 --- a/neoforge/build.gradle +++ b/neoforge/build.gradle @@ -60,11 +60,7 @@ configurations { dependencies { minecraft "com.mojang:minecraft:${rootProject.minecraft_version}" - mappings loom.layered { - it.mappings("net.fabricmc:yarn:${project.yarn_mappings}:v2") - // Needed to fix "Unfixable conflicts" in 1.20.5 - it.mappings(project.projectDir.toPath().resolve("mappings/fix.tiny").toFile()) - } + mappings "net.fabricmc:yarn:${rootProject.yarn_mappings}:v2" neoForge "net.neoforged:neoforge:${rootProject.neoforge_version}" @@ -75,7 +71,7 @@ dependencies { processResources { inputs.property "version", project.version - filesMatching("META-INF/neoforge.mods.toml") { + filesMatching("META-INF/mods.toml") { expand "version": project.version } } diff --git a/neoforge/mappings/fix.tiny b/neoforge/mappings/fix.tiny deleted file mode 100644 index 620ab53f..00000000 --- a/neoforge/mappings/fix.tiny +++ /dev/null @@ -1,5 +0,0 @@ -tiny 2 0 intermediary named -c net/minecraft/class_1496 - m ()Lnet/minecraft/class_1263; method_56680 getInventoryVanilla -c net/minecraft/class_329 - m (Lnet/minecraft/class_332;F)V method_1759 renderHotbarVanilla diff --git a/neoforge/src/main/java/dev/emi/emi/api/neoforge/NeoForgeEmiStack.java b/neoforge/src/main/java/dev/emi/emi/api/neoforge/NeoForgeEmiStack.java index 0a06d098..7e5823c8 100644 --- a/neoforge/src/main/java/dev/emi/emi/api/neoforge/NeoForgeEmiStack.java +++ b/neoforge/src/main/java/dev/emi/emi/api/neoforge/NeoForgeEmiStack.java @@ -6,6 +6,6 @@ public final class NeoForgeEmiStack { public static EmiStack of(FluidStack stack) { - return EmiStack.of(stack.getFluid(), stack.getComponentsPatch(), stack.getAmount()); + return EmiStack.of(stack.getFluid(), stack.getTag(), stack.getAmount()); } } diff --git a/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiAgnosNeoForge.java b/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiAgnosNeoForge.java index 8fe51cda..e878c88e 100644 --- a/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiAgnosNeoForge.java +++ b/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiAgnosNeoForge.java @@ -7,8 +7,6 @@ import java.util.function.Consumer; import java.util.stream.Stream; -import dev.emi.emi.mixin.accessor.BrewingRecipeRegistryAccessor; -import net.minecraft.component.ComponentChanges; import net.minecraft.item.PotionItem; import net.minecraft.registry.entry.RegistryEntry; import net.neoforged.neoforge.client.ClientHooks; @@ -46,6 +44,7 @@ import net.minecraft.item.ItemStack; import net.minecraft.nbt.NbtCompound; import net.minecraft.potion.Potion; +import net.minecraft.potion.PotionUtil; import net.minecraft.potion.Potions; import net.minecraft.recipe.BrewingRecipeRegistry; import net.minecraft.recipe.Ingredient; @@ -138,21 +137,19 @@ protected List getPluginsAgnos() { @Override protected void addBrewingRecipesAgnos(EmiRegistry registry) { - BrewingRecipeRegistry brewingRegistry = MinecraftClient.getInstance().world != null ? MinecraftClient.getInstance().world.getBrewingRecipeRegistry() : BrewingRecipeRegistry.EMPTY; - BrewingRecipeRegistryAccessor brewingRegistryAccess = (BrewingRecipeRegistryAccessor)brewingRegistry; - for (Ingredient ingredient : brewingRegistryAccess.getPotionTypes()) { + for (Ingredient ingredient : BrewingRecipeRegistry.POTION_TYPES) { for (ItemStack stack : ingredient.getMatchingStacks()) { String pid = EmiUtil.subId(stack.getItem()); - for (BrewingRecipeRegistry.Recipe recipe : brewingRegistryAccess.getPotionRecipes()) { + for (BrewingRecipeRegistry.Recipe recipe : BrewingRecipeRegistry.POTION_RECIPES) { try { if (recipe.ingredient.getMatchingStacks().length > 0) { Identifier id = new Identifier("emi", "/brewing/" + pid + "/" + EmiUtil.subId(recipe.ingredient.getMatchingStacks()[0].getItem()) - + "/" + EmiUtil.subId(EmiPort.getPotionRegistry().getId(recipe.from().value())) - + "/" + EmiUtil.subId(EmiPort.getPotionRegistry().getId(recipe.to().value()))); + + "/" + EmiUtil.subId(EmiPort.getPotionRegistry().getId(recipe.input)) + + "/" + EmiUtil.subId(EmiPort.getPotionRegistry().getId(recipe.output))); registry.addRecipe(new EmiBrewingRecipe( - EmiStack.of(EmiPort.setPotion(stack.copy(), recipe.from().value())), EmiIngredient.of(recipe.ingredient), - EmiStack.of(EmiPort.setPotion(stack.copy(), recipe.to().value())), id)); + EmiStack.of(EmiPort.setPotion(stack.copy(), recipe.input)), EmiIngredient.of(recipe.ingredient), + EmiStack.of(EmiPort.setPotion(stack.copy(), recipe.output)), id)); } } catch (Exception e) { e.printStackTrace(); @@ -161,26 +158,29 @@ protected void addBrewingRecipesAgnos(EmiRegistry registry) { } } - for (BrewingRecipeRegistry.Recipe recipe : brewingRegistryAccess.getItemRecipes()) { + for (BrewingRecipeRegistry.Recipe recipe : BrewingRecipeRegistry.ITEM_RECIPES) { try { if (recipe.ingredient.getMatchingStacks().length > 0) { String gid = EmiUtil.subId(recipe.ingredient.getMatchingStacks()[0].getItem()); - String iid = EmiUtil.subId(recipe.from().value()); - String oid = EmiUtil.subId(recipe.to.value()); + String iid = EmiUtil.subId(recipe.input); + String oid = EmiUtil.subId(recipe.output); Consumer> potionRecipeGen = entry -> { Potion potion = entry.value(); - if (brewingRegistry.isBrewable(entry)) { + if (potion == Potions.EMPTY) { + return; + } + if (BrewingRecipeRegistry.isBrewable(potion)) { Identifier id = new Identifier("emi", "brewing/item/" + EmiUtil.subId(entry.getKey().get().getValue()) + "/" + gid + "/" + iid + "/" + oid); registry.addRecipe(new EmiBrewingRecipe( - EmiStack.of(EmiPort.setPotion(new ItemStack(recipe.from().value()), potion)), EmiIngredient.of(recipe.ingredient), - EmiStack.of(EmiPort.setPotion(new ItemStack(recipe.to().value()), potion)), id)); + EmiStack.of(EmiPort.setPotion(new ItemStack(recipe.input), potion)), EmiIngredient.of(recipe.ingredient), + EmiStack.of(EmiPort.setPotion(new ItemStack(recipe.output), potion)), id)); } }; - if ((recipe.from().value() instanceof PotionItem)) { + if ((recipe.input instanceof PotionItem)) { EmiPort.getPotionRegistry().streamEntries().forEach(potionRecipeGen); } else { - potionRecipeGen.accept(Potions.AWKWARD); + potionRecipeGen.accept(EmiPort.getPotionRegistry().getEntry(Potions.AWKWARD)); } } @@ -188,7 +188,7 @@ protected void addBrewingRecipesAgnos(EmiRegistry registry) { e.printStackTrace(); } } - for (IBrewingRecipe ibr : brewingRegistry.getRecipes()) { + for (IBrewingRecipe ibr : net.neoforged.neoforge.common.brewing.BrewingRecipeRegistry.getRecipes()) { try { if (ibr instanceof BrewingRecipe recipe) { for (ItemStack is : recipe.getInput().getMatchingStacks()) { @@ -235,24 +235,24 @@ protected List getItemTooltipAgnos(ItemStack stack) { } @Override - protected Text getFluidNameAgnos(Fluid fluid, ComponentChanges componentChanges) { - return new FluidStack(fluid.getRegistryEntry(), 1000, componentChanges).getHoverName(); + protected Text getFluidNameAgnos(Fluid fluid, NbtCompound nbt) { + return new FluidStack(fluid, 1000, nbt).getDisplayName(); } @Override - protected List getFluidTooltipAgnos(Fluid fluid, ComponentChanges componentChanges) { - return List.of(getFluidName(fluid, componentChanges)); + protected List getFluidTooltipAgnos(Fluid fluid, NbtCompound nbt) { + return List.of(getFluidName(fluid, nbt)); } @Override protected boolean isFloatyFluidAgnos(FluidEmiStack stack) { - FluidStack fs = new FluidStack(stack.getKeyOfType(Fluid.class).getRegistryEntry(), 1000, stack.getComponentChanges()); + FluidStack fs = new FluidStack(stack.getKeyOfType(Fluid.class), 1000, stack.getNbt()); return fs.getFluid().getFluidType().isLighterThanAir(); } @Override protected void renderFluidAgnos(FluidEmiStack stack, MatrixStack matrices, int x, int y, float delta, int xOff, int yOff, int width, int height) { - FluidStack fs = new FluidStack(stack.getKeyOfType(Fluid.class).getRegistryEntry(), 1000, stack.getComponentChanges()); + FluidStack fs = new FluidStack(stack.getKeyOfType(Fluid.class), 1000, stack.getNbt()); IClientFluidTypeExtensions ext = IClientFluidTypeExtensions.of(fs.getFluid()); Identifier texture = ext.getStillTexture(fs); int color = ext.getTintColor(fs); @@ -264,7 +264,7 @@ protected void renderFluidAgnos(FluidEmiStack stack, MatrixStack matrices, int x @Override protected EmiStack createFluidStackAgnos(Object object) { if (object instanceof FluidStack f) { - return EmiStack.of(f.getFluid(), f.getComponentsPatch(), f.getAmount()); + return EmiStack.of(f.getFluid(), f.getTag(), f.getAmount()); } return EmiStack.EMPTY; } @@ -281,7 +281,7 @@ protected boolean canBatchAgnos(ItemStack stack) { protected Map getFuelMapAgnos() { Object2IntMap fuelMap = new Object2IntOpenHashMap<>(); for (Item item : EmiPort.getItemRegistry()) { - int time = item.getDefaultStack().getBurnTime(null); + int time = CommonHooks.getBurnTime(item.getDefaultStack(), null); if (time > 0) { fuelMap.put(item, time); } diff --git a/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiClientNeoForge.java b/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiClientNeoForge.java index b9786196..3eca5c10 100644 --- a/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiClientNeoForge.java +++ b/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiClientNeoForge.java @@ -18,34 +18,34 @@ import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.neoforged.api.distmarker.Dist; import net.neoforged.bus.api.SubscribeEvent; -import net.neoforged.fml.ModList; -import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.fml.ModLoadingContext; +import net.neoforged.fml.common.Mod; import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent; +import net.neoforged.neoforge.client.ConfigScreenHandler; import net.neoforged.neoforge.client.NeoForgeRenderTypes; import net.neoforged.neoforge.client.event.ContainerScreenEvent; import net.neoforged.neoforge.client.event.ModelEvent; import net.neoforged.neoforge.client.event.RecipesUpdatedEvent; import net.neoforged.neoforge.client.event.RegisterClientReloadListenersEvent; import net.neoforged.neoforge.client.event.ScreenEvent; -import net.neoforged.neoforge.client.gui.IConfigScreenFactory; import net.neoforged.neoforge.common.NeoForge; import net.neoforged.neoforge.event.TagsUpdatedEvent; import net.neoforged.neoforge.network.PacketDistributor; -@EventBusSubscriber(modid = "emi", bus = EventBusSubscriber.Bus.MOD, value = Dist.CLIENT) +@Mod.EventBusSubscriber(modid = "emi", bus = Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT) public class EmiClientNeoForge { @SubscribeEvent public static void clientInit(FMLClientSetupEvent event) { StackBatcher.EXTRA_RENDER_LAYERS.addAll(Arrays.stream(NeoForgeRenderTypes.values()).map(f -> f.get()).toList()); EmiClient.init(); - EmiNetwork.initClient(packet -> PacketDistributor.sendToServer(EmiPacketHandler.wrap(packet))); + EmiNetwork.initClient(packet -> PacketDistributor.SERVER.noArg().send(EmiPacketHandler.wrap(packet))); NeoForge.EVENT_BUS.addListener(EmiClientNeoForge::recipesReloaded); NeoForge.EVENT_BUS.addListener(EmiClientNeoForge::tagsReloaded); NeoForge.EVENT_BUS.addListener(EmiClientNeoForge::renderScreenForeground); NeoForge.EVENT_BUS.addListener(EmiClientNeoForge::postRenderScreen); - ModList.get().getModContainerById("emi").orElseThrow().registerExtensionPoint(IConfigScreenFactory.class, - (client, last) -> new ConfigScreen(last)); + ModLoadingContext.get().registerExtensionPoint(ConfigScreenHandler.ConfigScreenFactory.class, + () -> new ConfigScreenHandler.ConfigScreenFactory((client, last) -> new ConfigScreen(last))); } @SubscribeEvent diff --git a/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiNeoForge.java b/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiNeoForge.java index 7fe21b65..d86cc326 100644 --- a/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiNeoForge.java +++ b/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiNeoForge.java @@ -19,7 +19,7 @@ public EmiNeoForge(IEventBus modEventBus) { EmiMain.init(); modEventBus.addListener(EmiPacketHandler::init); EmiNetwork.initServer((player, packet) -> { - PacketDistributor.sendToPlayer(player, EmiPacketHandler.wrap(packet)); + PacketDistributor.PLAYER.with(player).send(EmiPacketHandler.wrap(packet)); }); NeoForge.EVENT_BUS.addListener(this::registerCommands); NeoForge.EVENT_BUS.addListener(this::playerConnect); diff --git a/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiPacketHandler.java b/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiPacketHandler.java index a4608a82..0f08b7a2 100644 --- a/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiPacketHandler.java +++ b/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiPacketHandler.java @@ -7,49 +7,70 @@ import dev.emi.emi.network.EmiPacket; import dev.emi.emi.network.FillRecipeC2SPacket; import dev.emi.emi.network.PingS2CPacket; -import net.minecraft.network.RegistryByteBuf; -import net.minecraft.network.codec.PacketCodec; -import net.minecraft.network.codec.PacketDecoder; +import net.minecraft.network.PacketByteBuf; import net.minecraft.network.packet.CustomPayload; -import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent; -import net.neoforged.neoforge.network.handling.IPayloadContext; +import net.minecraft.util.Identifier; +import net.neoforged.neoforge.network.event.RegisterPayloadHandlerEvent; +import net.neoforged.neoforge.network.handling.PlayPayloadContext; + +import java.util.function.Function; public class EmiPacketHandler { - private static final CustomPayload.Id ID_CHESS_CLIENTBOUND = CustomPayload.id("emi:chess_s2c"); - private static final CustomPayload.Id ID_CHESS_SERVERBOUND = CustomPayload.id("emi:chess_c2s"); + private static final Identifier ID_CHESS_CLIENTBOUND = new Identifier("emi", "chess_s2c"); + private static final Identifier ID_CHESS_SERVERBOUND = new Identifier("emi", "chess_c2s"); - public static void init(RegisterPayloadHandlersEvent event) { + public static void init(RegisterPayloadHandlerEvent event) { var registrar = event.registrar("emi").optional(); - registrar.playToServer(EmiNetwork.FILL_RECIPE, makeReader(EmiNetwork.FILL_RECIPE, FillRecipeC2SPacket::new), EmiPacketHandler::handleServerbound); - registrar.playToServer(EmiNetwork.CREATE_ITEM, makeReader(EmiNetwork.CREATE_ITEM, CreateItemC2SPacket::new), EmiPacketHandler::handleServerbound); - registrar.playToClient(EmiNetwork.PING, makeReader(EmiNetwork.PING, PingS2CPacket::new), EmiPacketHandler::handleClientbound); - registrar.playToClient(EmiNetwork.COMMAND, makeReader(EmiNetwork.COMMAND, CommandS2CPacket::new), EmiPacketHandler::handleClientbound); - registrar.playToServer(ID_CHESS_SERVERBOUND, makeReader(ID_CHESS_SERVERBOUND, EmiChessPacket.C2S::new), EmiPacketHandler::handleServerbound); - registrar.playToClient(ID_CHESS_CLIENTBOUND, makeReader(ID_CHESS_CLIENTBOUND, EmiChessPacket.S2C::new), EmiPacketHandler::handleClientbound); + registrar.play(EmiNetwork.FILL_RECIPE, makeReader(EmiNetwork.FILL_RECIPE, FillRecipeC2SPacket::new), EmiPacketHandler::handleServerbound); + registrar.play(EmiNetwork.CREATE_ITEM, makeReader(EmiNetwork.CREATE_ITEM, CreateItemC2SPacket::new), EmiPacketHandler::handleServerbound); + registrar.play(EmiNetwork.PING, makeReader(EmiNetwork.PING, PingS2CPacket::new), EmiPacketHandler::handleClientbound); + registrar.play(EmiNetwork.COMMAND, makeReader(EmiNetwork.COMMAND, CommandS2CPacket::new), EmiPacketHandler::handleClientbound); + registrar.play(ID_CHESS_SERVERBOUND, makeReader(ID_CHESS_SERVERBOUND, EmiChessPacket.C2S::new), EmiPacketHandler::handleServerbound); + registrar.play(ID_CHESS_CLIENTBOUND, makeReader(ID_CHESS_CLIENTBOUND, EmiChessPacket.S2C::new), EmiPacketHandler::handleClientbound); } - public static EmiPacket wrap(EmiPacket packet) { - return packet; + public static CustomPayload wrap(EmiPacket packet) { + // Special casing for chess since it's reusing the same ID in EMI for both + if (packet instanceof EmiChessPacket.S2C) { + return new PayloadWrapper<>(ID_CHESS_CLIENTBOUND, packet); + } else if (packet instanceof EmiChessPacket.C2S) { + return new PayloadWrapper<>(ID_CHESS_SERVERBOUND, packet); + } else { + return new PayloadWrapper<>(packet.getId(), packet); + } + } + + // Neoforge requires us to implement this interface, we use a wrapper-record to do this on top of EmiPacket + private record PayloadWrapper(Identifier id, T packet) implements CustomPayload { + @Override + public void write(PacketByteBuf buf) { + packet.write(buf); + } } - private static PacketCodec makeReader(CustomPayload.Id id, PacketDecoder reader) { - return PacketCodec.of(EmiPacket::write, reader); + private static PacketByteBuf.PacketReader> makeReader(Identifier id, Function reader) { + return buffer -> { + // Read EMI packet and wrap + return new PayloadWrapper<>(id, reader.apply(buffer)); + }; } - private static void handleServerbound(EmiPacket packet, IPayloadContext context) { + private static void handleServerbound(PayloadWrapper wrapper, PlayPayloadContext context) { + var packet = wrapper.packet(); if (!context.flow().isServerbound()) { throw new IllegalArgumentException("Trying to handle serverbound packet on client: " + packet); } - var player = context.player(); - context.enqueueWork(() -> packet.apply(player)); + var player = context.player().orElse(null); + context.workHandler().execute(() -> packet.apply(player)); } - private static void handleClientbound(EmiPacket packet, IPayloadContext context) { + private static void handleClientbound(PayloadWrapper wrapper, PlayPayloadContext context) { + var packet = wrapper.packet(); if (!context.flow().isClientbound()) { throw new IllegalArgumentException("Trying to handle clientbound packet on server: " + packet); } - var player = context.player(); - context.enqueueWork(() -> packet.apply(player)); + var player = context.player().orElse(null); + context.workHandler().execute(() -> packet.apply(player)); } } diff --git a/neoforge/src/main/resources/META-INF/neoforge.mods.toml b/neoforge/src/main/resources/META-INF/mods.toml similarity index 100% rename from neoforge/src/main/resources/META-INF/neoforge.mods.toml rename to neoforge/src/main/resources/META-INF/mods.toml diff --git a/xplat/src/main/java/dev/emi/emi/EmiPort.java b/xplat/src/main/java/dev/emi/emi/EmiPort.java index 4f5d2fce..adefa46d 100644 --- a/xplat/src/main/java/dev/emi/emi/EmiPort.java +++ b/xplat/src/main/java/dev/emi/emi/EmiPort.java @@ -7,11 +7,6 @@ import java.util.function.Predicate; import java.util.stream.Stream; -import net.minecraft.component.ComponentChanges; -import net.minecraft.component.DataComponentTypes; -import net.minecraft.component.type.BannerPatternsComponent; -import net.minecraft.component.type.PotionContentsComponent; -import net.minecraft.registry.RegistryKeys; import org.jetbrains.annotations.Nullable; import org.joml.Matrix4f; @@ -36,7 +31,9 @@ import net.minecraft.fluid.Fluid; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NbtCompound; import net.minecraft.potion.Potion; +import net.minecraft.potion.PotionUtil; import net.minecraft.recipe.Recipe; import net.minecraft.recipe.RecipeEntry; import net.minecraft.recipe.RecipeManager; @@ -107,10 +104,9 @@ public static InputStream getInputStream(Resource resource) { } } - public static BannerPatternsComponent addRandomBanner(BannerPatternsComponent patterns, Random random) { - var bannerRegistry = MinecraftClient.getInstance().world.getRegistryManager().get(RegistryKeys.BANNER_PATTERN); - return new BannerPatternsComponent.Builder().addAll(patterns).add(bannerRegistry.getEntry(random.nextInt(bannerRegistry.size())).get(), - DyeColor.values()[random.nextInt(DyeColor.values().length)]).build(); + public static BannerPattern.Patterns addRandomBanner(BannerPattern.Patterns patterns, Random random) { + return patterns.add(Registries.BANNER_PATTERN.getEntry(random.nextInt(Registries.BANNER_PATTERN.size())).get(), + DyeColor.values()[random.nextInt(DyeColor.values().length)]); } public static boolean canTallFlowerDuplicate(TallFlowerBlock tallFlowerBlock) { @@ -186,7 +182,7 @@ public static void focus(TextFieldWidget widget, boolean focused) { if (client != null && client.currentScreen != null) { var currentFocus = client.currentScreen.getFocused(); if (!focused && currentFocus == widget || focused && currentFocus != widget) { - client.currentScreen.setFocused(null); + client.currentScreen.focusOn(null); } } widget.setFocused(focused); @@ -214,15 +210,14 @@ public static Identifier getId(Recipe recipe) { } public static Comparison compareStrict() { - return Comparison.compareComponents(); + return Comparison.compareNbt(); } public static ItemStack setPotion(ItemStack stack, Potion potion) { - stack.apply(DataComponentTypes.POTION_CONTENTS, PotionContentsComponent.DEFAULT, getPotionRegistry().getEntry(potion), PotionContentsComponent::with); - return stack; + return PotionUtil.setPotion(stack, potion); } - public static ComponentChanges emptyExtraData() { - return ComponentChanges.EMPTY; + public static NbtCompound emptyExtraData() { + return null; } } diff --git a/xplat/src/main/java/dev/emi/emi/VanillaPlugin.java b/xplat/src/main/java/dev/emi/emi/VanillaPlugin.java index 923ab00c..02eff9ad 100644 --- a/xplat/src/main/java/dev/emi/emi/VanillaPlugin.java +++ b/xplat/src/main/java/dev/emi/emi/VanillaPlugin.java @@ -107,9 +107,6 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.ingame.AbstractInventoryScreen; import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen; -import net.minecraft.component.DataComponentTypes; -import net.minecraft.component.type.DyedColorComponent; -import net.minecraft.component.type.PotionContentsComponent; import net.minecraft.enchantment.Enchantment; import net.minecraft.entity.effect.StatusEffectInstance; import net.minecraft.fluid.FlowableFluid; @@ -119,6 +116,7 @@ import net.minecraft.item.ArmorItem; import net.minecraft.item.BlockItem; import net.minecraft.item.DyeItem; +import net.minecraft.item.DyeableItem; import net.minecraft.item.HoneycombItem; import net.minecraft.item.Item; import net.minecraft.item.ItemConvertible; @@ -126,6 +124,7 @@ import net.minecraft.item.ItemUsageContext; import net.minecraft.item.Items; import net.minecraft.item.ToolItem; +import net.minecraft.potion.PotionUtil; import net.minecraft.potion.Potions; import net.minecraft.recipe.ArmorDyeRecipe; import net.minecraft.recipe.BannerDuplicateRecipe; @@ -319,7 +318,7 @@ public void register(EmiRegistry registry) { } }); - Comparison potionComparison = Comparison.compareData(stack -> stack.get(DataComponentTypes.POTION_CONTENTS)); + Comparison potionComparison = Comparison.compareData(stack -> PotionUtil.getPotion(stack.getNbt())); registry.setDefaultComparison(Items.POTION, potionComparison); registry.setDefaultComparison(Items.SPLASH_POTION, potionComparison); @@ -332,7 +331,7 @@ public void register(EmiRegistry registry) { EmiPort.getDisabledItems() ).collect(Collectors.toSet()); - List dyeableItems = EmiUtil.values(ItemTags.DYEABLE).map(RegistryEntry::value).collect(Collectors.toList()); + List dyeableItems = EmiPort.getItemRegistry().stream().filter(i -> i instanceof DyeableItem).collect(Collectors.toList()); for (CraftingRecipe recipe : getRecipes(registry, RecipeType.CRAFTING)) { Identifier id = EmiPort.getId(recipe); @@ -371,6 +370,9 @@ public void register(EmiRegistry registry) { addRecipeSafe(registry, () -> new EmiBookCloningRecipe(id), recipe); } else if (recipe instanceof TippedArrowRecipe tipped) { EmiPort.getPotionRegistry().streamEntries().forEach(entry -> { + if (entry.value() == Potions.EMPTY) { + return; + } EmiStack arrow = EmiStack.of(Items.ARROW); addRecipeSafe(registry, () -> new EmiCraftingRecipe(List.of( arrow, arrow, arrow, arrow, @@ -488,19 +490,18 @@ private static void addRepair(EmiRegistry registry, Set hiddenItems) { continue; } try { - if (i.getComponents().getOrDefault(DataComponentTypes.MAX_DAMAGE, 0) > 0) { - if (i instanceof ArmorItem ai && ai.getMaterial() != null && ai.getMaterial().value().repairIngredient().get() != null - && !ai.getMaterial().value().repairIngredient().get().isEmpty()) { - Identifier id = synthetic("anvil/repairing/material", EmiUtil.subId(i) + "/" + EmiUtil.subId(ai.getMaterial().value().repairIngredient().get().getMatchingStacks()[0].getItem())); - addRecipeSafe(registry, () -> new EmiAnvilRecipe(EmiStack.of(i), EmiIngredient.of(ai.getMaterial().value().repairIngredient().get()), id)); + if (i.getMaxDamage() > 0) { + if (i instanceof ArmorItem ai && ai.getMaterial() != null && ai.getMaterial().getRepairIngredient() != null + && !ai.getMaterial().getRepairIngredient().isEmpty()) { + Identifier id = synthetic("anvil/repairing/material", EmiUtil.subId(i) + "/" + EmiUtil.subId(ai.getMaterial().getRepairIngredient().getMatchingStacks()[0].getItem())); + addRecipeSafe(registry, () -> new EmiAnvilRecipe(EmiStack.of(i), EmiIngredient.of(ai.getMaterial().getRepairIngredient()), id)); } else if (i instanceof ToolItem ti && ti.getMaterial().getRepairIngredient() != null && !ti.getMaterial().getRepairIngredient().isEmpty()) { Identifier id = synthetic("anvil/repairing/material", EmiUtil.subId(i) + "/" + EmiUtil.subId(ti.getMaterial().getRepairIngredient().getMatchingStacks()[0].getItem())); addRecipeSafe(registry, () -> new EmiAnvilRecipe(EmiStack.of(i), EmiIngredient.of(ti.getMaterial().getRepairIngredient()), id)); } } - // TODO used to be isDamageable, the 20.1 impl of that method appears to just be maxDamage > 0 though - if (i.getComponents().getOrDefault(DataComponentTypes.MAX_DAMAGE, 0) > 0) { + if (i.isDamageable()) { addRecipeSafe(registry, () -> new EmiAnvilRepairItemRecipe(i, synthetic("anvil/repairing/tool", EmiUtil.subId(i)))); addRecipeSafe(registry, () -> new EmiGrindstoneRecipe(i, synthetic("grindstone/repairing", EmiUtil.subId(i)))); } @@ -655,7 +656,7 @@ private static void addWorldInteraction(EmiRegistry registry, Set hiddenIt .id(synthetic("world/cauldron_washing", EmiUtil.subId(i))) .leftInput(EmiStack.EMPTY, s -> new GeneratedSlotWidget(r -> { ItemStack stack = i.getDefaultStack(); - stack.set(DataComponentTypes.DYED_COLOR, new DyedColorComponent(r.nextInt(0xFFFFFF + 1), true)); + ((DyeableItem) i).setColor(stack, r.nextInt(0xFFFFFF + 1)); return EmiStack.of(stack); }, uniq, s.getBounds().x(), s.getBounds().y())) .rightInput(cauldron, true) @@ -720,10 +721,10 @@ private static void addWorldInteraction(EmiRegistry registry, Set hiddenIt }); addRecipeSafe(registry, () -> basicWorld(EmiStack.of(Items.GLASS_BOTTLE), water, - EmiStack.of(EmiPort.setPotion(new ItemStack(Items.POTION), Potions.WATER.value())), + EmiStack.of(EmiPort.setPotion(new ItemStack(Items.POTION), Potions.WATER)), synthetic("world/unique", "minecraft/water_bottle"))); - EmiStack waterBottle = EmiStack.of(EmiPort.setPotion(new ItemStack(Items.POTION), Potions.WATER.value())) + EmiStack waterBottle = EmiStack.of(EmiPort.setPotion(new ItemStack(Items.POTION), Potions.WATER)) .setRemainder(EmiStack.of(Items.GLASS_BOTTLE)); EmiStack mud = EmiStack.of(Items.MUD); addRecipeSafe(registry, () -> basicWorld(EmiStack.of(Items.DIRT), waterBottle, mud, synthetic("world/unique", "minecraft/mud"), false)); diff --git a/xplat/src/main/java/dev/emi/emi/api/stack/Comparison.java b/xplat/src/main/java/dev/emi/emi/api/stack/Comparison.java index 7f668b74..5ea125cc 100644 --- a/xplat/src/main/java/dev/emi/emi/api/stack/Comparison.java +++ b/xplat/src/main/java/dev/emi/emi/api/stack/Comparison.java @@ -8,7 +8,7 @@ import dev.emi.emi.runtime.EmiLog; public class Comparison { - private static final Comparison COMPARE_COMPONENTS = Comparison.compareData(stack -> stack.getComponentChanges()); + private static final Comparison COMPARE_NBT = Comparison.compareData(stack -> stack.getNbt()); public static final Comparison DEFAULT_COMPARISON = Comparison.of((a, b) -> true); private Predicate predicate; private HashFunction hash; @@ -38,8 +38,8 @@ public static Comparison compareData(Function function) { /** * Creates a comparison method where stacks are distinct based on NBT */ - public static Comparison compareComponents() { - return COMPARE_COMPONENTS; + public static Comparison compareNbt() { + return COMPARE_NBT; } public boolean compare(EmiStack a, EmiStack b) { diff --git a/xplat/src/main/java/dev/emi/emi/api/stack/EmiRegistryAdapter.java b/xplat/src/main/java/dev/emi/emi/api/stack/EmiRegistryAdapter.java index 310a43ed..1a1d976f 100644 --- a/xplat/src/main/java/dev/emi/emi/api/stack/EmiRegistryAdapter.java +++ b/xplat/src/main/java/dev/emi/emi/api/stack/EmiRegistryAdapter.java @@ -1,8 +1,8 @@ package dev.emi.emi.api.stack; -import net.minecraft.component.ComponentChanges; import org.jetbrains.annotations.ApiStatus; +import net.minecraft.nbt.NbtCompound; import net.minecraft.registry.Registry; /** @@ -25,7 +25,7 @@ public interface EmiRegistryAdapter { /** * Constructs an {@link EmiStack} from a given object from the registry, or {@link EmiStack#EMPTY} if somehow invalid. */ - EmiStack of(T t, ComponentChanges componentChanges, long amount); + EmiStack of(T t, NbtCompound nbt, long amount); /** * Convenience method for creating an {@link EmiRegistryAdapter}. @@ -44,13 +44,13 @@ public Registry getRegistry() { } @Override - public EmiStack of(T t, ComponentChanges componentChanges, long amount) { - return constructor.of(t, componentChanges, amount); + public EmiStack of(T t, NbtCompound nbt, long amount) { + return constructor.of(t, nbt, amount); } }; } public static interface StackConstructor { - EmiStack of(T t, ComponentChanges componentChanges, long amount); + EmiStack of(T t, NbtCompound nbt, long amount); } } diff --git a/xplat/src/main/java/dev/emi/emi/api/stack/EmiStack.java b/xplat/src/main/java/dev/emi/emi/api/stack/EmiStack.java index 0827b49c..f2d8fdd0 100644 --- a/xplat/src/main/java/dev/emi/emi/api/stack/EmiStack.java +++ b/xplat/src/main/java/dev/emi/emi/api/stack/EmiStack.java @@ -1,14 +1,8 @@ package dev.emi.emi.api.stack; import java.util.List; -import java.util.Optional; import java.util.function.Function; -import net.minecraft.component.ComponentChanges; -import net.minecraft.component.ComponentHolder; -import net.minecraft.component.ComponentMap; -import net.minecraft.component.ComponentMapImpl; -import net.minecraft.component.DataComponentType; import org.jetbrains.annotations.Nullable; import com.google.common.collect.Lists; @@ -86,17 +80,10 @@ public EmiStack setChance(float chance) { return this; } - public abstract ComponentChanges getComponentChanges(); + public abstract NbtCompound getNbt(); - public @Nullable T get(DataComponentType type) { - var opt = getComponentChanges().get(type); - //noinspection OptionalAssignedToNull - return opt != null ? opt.orElse(null) : null; - } - - public T getOrDefault(DataComponentType type, T fallback) { - var componentValue = this.get(type); - return componentValue != null ? componentValue : fallback; + public boolean hasNbt() { + return getNbt() != null; } public abstract Object getKey(); @@ -163,9 +150,9 @@ public int hashCode() { @Override public String toString() { String s = "" + getKey(); - ComponentChanges changes = getComponentChanges(); - if (changes != ComponentChanges.EMPTY) { - s += changes; + NbtCompound nbt = getNbt(); + if (nbt != null) { + s += nbt; } return s + " x" + getAmount(); } @@ -192,12 +179,12 @@ public static EmiStack of(ItemConvertible item, long amount) { return of(item.asItem().getDefaultStack(), amount); } - public static EmiStack of(ItemConvertible item, ComponentChanges componentChanges) { - return of(item, componentChanges, 1); + public static EmiStack of(ItemConvertible item, NbtCompound nbt) { + return of(item, nbt, 1); } - public static EmiStack of(ItemConvertible item, ComponentChanges componentChanges, long amount) { - return new ItemEmiStack(item.asItem(), componentChanges, amount); + public static EmiStack of(ItemConvertible item, NbtCompound nbt, long amount) { + return new ItemEmiStack(item.asItem(), nbt, amount); } public static EmiStack of(Fluid fluid) { @@ -208,18 +195,18 @@ public static EmiStack of(Fluid fluid, long amount) { return of(fluid, EmiPort.emptyExtraData(), amount); } - public static EmiStack of(Fluid fluid, ComponentChanges componentChanges) { - return of(fluid, componentChanges, 0); + public static EmiStack of(Fluid fluid, NbtCompound nbt) { + return of(fluid, nbt, 0); } - public static EmiStack of(Fluid fluid, ComponentChanges componentChanges, long amount) { + public static EmiStack of(Fluid fluid, NbtCompound nbt, long amount) { if (fluid instanceof FlowableFluid ff && ff.getStill() != Fluids.EMPTY) { fluid = ff.getStill(); } if (fluid == Fluids.EMPTY) { return EmiStack.EMPTY; } - return new FluidEmiStack(fluid, componentChanges, amount); + return new FluidEmiStack(fluid, nbt, amount); } static abstract class Entry { diff --git a/xplat/src/main/java/dev/emi/emi/api/stack/EmptyEmiStack.java b/xplat/src/main/java/dev/emi/emi/api/stack/EmptyEmiStack.java index cd5a0947..57ea9921 100644 --- a/xplat/src/main/java/dev/emi/emi/api/stack/EmptyEmiStack.java +++ b/xplat/src/main/java/dev/emi/emi/api/stack/EmptyEmiStack.java @@ -2,8 +2,6 @@ import java.util.List; -import net.minecraft.component.ComponentChanges; -import net.minecraft.component.ComponentMap; import org.jetbrains.annotations.ApiStatus; import dev.emi.emi.EmiPort; @@ -53,8 +51,8 @@ public boolean isEmpty() { } @Override - public ComponentChanges getComponentChanges() { - return ComponentChanges.EMPTY; + public NbtCompound getNbt() { + return null; } @Override diff --git a/xplat/src/main/java/dev/emi/emi/api/stack/FluidEmiStack.java b/xplat/src/main/java/dev/emi/emi/api/stack/FluidEmiStack.java index 2ce44b73..1f606959 100644 --- a/xplat/src/main/java/dev/emi/emi/api/stack/FluidEmiStack.java +++ b/xplat/src/main/java/dev/emi/emi/api/stack/FluidEmiStack.java @@ -3,9 +3,6 @@ import java.util.List; import java.util.stream.Collectors; -import net.minecraft.component.ComponentChanges; -import net.minecraft.component.ComponentMap; -import net.minecraft.component.ComponentMapImpl; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; @@ -24,25 +21,25 @@ @ApiStatus.Internal public class FluidEmiStack extends EmiStack { private final Fluid fluid; - private final ComponentChanges componentChanges; + private final NbtCompound nbt; public FluidEmiStack(Fluid fluid) { - this(fluid, ComponentChanges.EMPTY); + this(fluid, null); } - public FluidEmiStack(Fluid fluid, ComponentChanges componentChanges) { - this(fluid, componentChanges, 0); + public FluidEmiStack(Fluid fluid, @Nullable NbtCompound nbt) { + this(fluid, nbt, 0); } - public FluidEmiStack(Fluid fluid, ComponentChanges componentChanges, long amount) { + public FluidEmiStack(Fluid fluid, @Nullable NbtCompound nbt, long amount) { this.fluid = fluid; - this.componentChanges = componentChanges; + this.nbt = nbt; this.amount = amount; } @Override public EmiStack copy() { - EmiStack e = new FluidEmiStack(fluid, componentChanges, amount); + EmiStack e = new FluidEmiStack(fluid, nbt, amount); e.setChance(chance); e.setRemainder(getRemainder().copy()); e.comparison = comparison; @@ -55,8 +52,8 @@ public boolean isEmpty() { } @Override - public ComponentChanges getComponentChanges() { - return ComponentChanges.EMPTY; + public NbtCompound getNbt() { + return nbt; } @Override @@ -85,7 +82,7 @@ public void render(DrawContext raw, int x, int y, float delta, int flags) { @Override public List getTooltipText() { - return EmiAgnos.getFluidTooltip(fluid, componentChanges); + return EmiAgnos.getFluidTooltip(fluid, nbt); } @Override @@ -102,7 +99,7 @@ public List getTooltip() { @Override public Text getName() { - return EmiAgnos.getFluidName(fluid, componentChanges); + return EmiAgnos.getFluidName(fluid, nbt); } static class FluidEntry { diff --git a/xplat/src/main/java/dev/emi/emi/api/stack/ItemEmiStack.java b/xplat/src/main/java/dev/emi/emi/api/stack/ItemEmiStack.java index 4acbb1e2..784c3bc7 100644 --- a/xplat/src/main/java/dev/emi/emi/api/stack/ItemEmiStack.java +++ b/xplat/src/main/java/dev/emi/emi/api/stack/ItemEmiStack.java @@ -2,9 +2,6 @@ import java.util.List; -import net.minecraft.client.item.TooltipType; -import net.minecraft.component.ComponentChanges; -import net.minecraft.component.DataComponentType; import net.minecraft.item.Item; import net.minecraft.item.Items; import org.jetbrains.annotations.ApiStatus; @@ -20,6 +17,7 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.tooltip.TooltipComponent; +import net.minecraft.client.item.TooltipContext; import net.minecraft.client.render.DiffuseLighting; import net.minecraft.client.render.LightmapTextureManager; import net.minecraft.client.render.OverlayTexture; @@ -28,16 +26,16 @@ import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.render.model.json.ModelTransformationMode; import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NbtCompound; import net.minecraft.text.Text; import net.minecraft.util.Identifier; -import org.jetbrains.annotations.Nullable; @ApiStatus.Internal public class ItemEmiStack extends EmiStack implements Batchable { private static final MinecraftClient client = MinecraftClient.getInstance(); private final Item item; - private final ComponentChanges componentChanges; + private final NbtCompound nbt; private boolean unbatchable; @@ -46,23 +44,27 @@ public ItemEmiStack(ItemStack stack) { } public ItemEmiStack(ItemStack stack, long amount) { - this(stack.getItem(), stack.getComponentChanges(), amount); + this(stack.getItem(), stack.getNbt(), amount); } - public ItemEmiStack(Item item, ComponentChanges components, long amount) { + public ItemEmiStack(Item item, NbtCompound nbt, long amount) { this.item = item; - this.componentChanges = components; + this.nbt = nbt != null ? nbt.copy() : null; this.amount = amount; } @Override public ItemStack getItemStack() { - return new ItemStack(EmiPort.getItemRegistry().getEntry(this.item), (int) this.amount, componentChanges); + ItemStack stack = new ItemStack(this.item, (int) this.amount); + if (this.nbt != null) { + stack.setNbt(this.nbt); + } + return stack; } @Override public EmiStack copy() { - EmiStack e = new ItemEmiStack(item, componentChanges, amount); + EmiStack e = new ItemEmiStack(item, nbt, amount); e.setChance(chance); e.setRemainder(getRemainder().copy()); e.comparison = comparison; @@ -75,20 +77,8 @@ public boolean isEmpty() { } @Override - public ComponentChanges getComponentChanges() { - return this.componentChanges; - } - - @Override - public @Nullable T get(DataComponentType type) { - // Check the changes first - var changedOpt = this.componentChanges.get(type); - //noinspection OptionalAssignedToNull - if(changedOpt != null) { - return changedOpt.orElse(null); - } - // Check the item's default components - return this.item.getComponents().get(type); + public NbtCompound getNbt() { + return nbt; } @Override @@ -149,7 +139,7 @@ public void renderForBatch(VertexConsumerProvider vcp, DrawContext draw, int x, try { context.matrices().translate(x, y, 100.0f + z + (model.hasDepth() ? 50 : 0)); context.matrices().translate(8.0, 8.0, 0.0); - context.matrices().scale(16.0f, -16.0f, 16.0f); + context.matrices().scale(16.0f, 16.0f, 16.0f); ir.renderItem(stack, ModelTransformationMode.GUI, false, context.matrices(), vcp, LightmapTextureManager.MAX_LIGHT_COORDINATE, OverlayTexture.DEFAULT_UV, model); } finally { context.pop(); @@ -158,7 +148,7 @@ public void renderForBatch(VertexConsumerProvider vcp, DrawContext draw, int x, @Override public List getTooltipText() { - return getItemStack().getTooltip(Item.TooltipContext.DEFAULT, client.player, TooltipType.BASIC); + return getItemStack().getTooltip(client.player, TooltipContext.BASIC); } @Override diff --git a/xplat/src/main/java/dev/emi/emi/api/stack/serializer/EmiStackSerializer.java b/xplat/src/main/java/dev/emi/emi/api/stack/serializer/EmiStackSerializer.java index e584fe28..d722003f 100644 --- a/xplat/src/main/java/dev/emi/emi/api/stack/serializer/EmiStackSerializer.java +++ b/xplat/src/main/java/dev/emi/emi/api/stack/serializer/EmiStackSerializer.java @@ -10,9 +10,7 @@ import dev.emi.emi.api.stack.EmiIngredient; import dev.emi.emi.api.stack.EmiStack; import dev.emi.emi.runtime.EmiLog; -import net.minecraft.component.ComponentChanges; import net.minecraft.nbt.NbtCompound; -import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.StringNbtReader; import net.minecraft.util.Identifier; import net.minecraft.util.JsonHelper; @@ -20,7 +18,7 @@ public interface EmiStackSerializer extends EmiIngredientSerializer { static final Pattern STACK_REGEX = Pattern.compile("^([\\w_\\-./]+):([\\w_\\-.]+):([\\w_\\-./]+)(\\{.*\\})?$"); - EmiStack create(Identifier id, ComponentChanges componentChanges, long amount); + EmiStack create(Identifier id, NbtCompound nbt, long amount); @Override default EmiIngredient deserialize(JsonElement element) { @@ -51,11 +49,11 @@ default EmiIngredient deserialize(JsonElement element) { } if (id != null) { try { - ComponentChanges changes = ComponentChanges.EMPTY; + NbtCompound nbtComp = null; if (nbt != null) { - changes = ComponentChanges.CODEC.decode(NbtOps.INSTANCE, StringNbtReader.parse(nbt)).getOrThrow().getFirst(); + nbtComp = StringNbtReader.parse(nbt); } - EmiStack stack = create(id, changes, amount); + EmiStack stack = create(id, nbtComp, amount); if (chance != 1) { stack.setChance(chance); } @@ -76,9 +74,8 @@ default EmiIngredient deserialize(JsonElement element) { default JsonElement serialize(T stack) { if (stack.getAmount() == 1 && stack.getChance() == 1 && stack.getRemainder().isEmpty()) { String s = getType() + ":" + stack.getId(); - var componentChanges = stack.getComponentChanges(); - if (componentChanges != ComponentChanges.EMPTY) { - s += ComponentChanges.CODEC.encodeStart(NbtOps.INSTANCE, componentChanges).getOrThrow().asString(); + if (stack.hasNbt()) { + s += stack.getNbt().asString(); } return new JsonPrimitive(s); } else { diff --git a/xplat/src/main/java/dev/emi/emi/api/widget/TankWidget.java b/xplat/src/main/java/dev/emi/emi/api/widget/TankWidget.java index ffc82f78..6689b8b0 100644 --- a/xplat/src/main/java/dev/emi/emi/api/widget/TankWidget.java +++ b/xplat/src/main/java/dev/emi/emi/api/widget/TankWidget.java @@ -35,7 +35,7 @@ public void drawStack(DrawContext draw, int mouseX, int mouseY, float delta) { EmiIngredient ingredient = getStack(); for (EmiStack stack : ingredient.getEmiStacks()) { if (stack.getKey() instanceof Fluid fluid) { - FluidEmiStack fes = new FluidEmiStack(fluid, stack.getComponentChanges(), ingredient.getAmount()); + FluidEmiStack fes = new FluidEmiStack(fluid, stack.getNbt(), ingredient.getAmount()); boolean floaty = EmiAgnos.isFloatyFluid(fes); Bounds bounds = getBounds(); int x = bounds.x() + 1; diff --git a/xplat/src/main/java/dev/emi/emi/chess/ChessEmiStack.java b/xplat/src/main/java/dev/emi/emi/chess/ChessEmiStack.java index 1c219ef1..28a33ef9 100644 --- a/xplat/src/main/java/dev/emi/emi/chess/ChessEmiStack.java +++ b/xplat/src/main/java/dev/emi/emi/chess/ChessEmiStack.java @@ -13,8 +13,6 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.tooltip.TooltipComponent; -import net.minecraft.component.ComponentChanges; -import net.minecraft.component.ComponentMap; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.nbt.NbtCompound; import net.minecraft.text.Text; @@ -88,8 +86,8 @@ public boolean isEmpty() { } @Override - public ComponentChanges getComponentChanges() { - return ComponentChanges.EMPTY; + public NbtCompound getNbt() { + return null; } @Override diff --git a/xplat/src/main/java/dev/emi/emi/jemi/JemiStack.java b/xplat/src/main/java/dev/emi/emi/jemi/JemiStack.java index ef0b9e44..93f77e60 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/JemiStack.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/JemiStack.java @@ -17,9 +17,7 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.tooltip.TooltipComponent; -import net.minecraft.client.item.TooltipType; -import net.minecraft.component.ComponentChanges; -import net.minecraft.component.ComponentMap; +import net.minecraft.client.item.TooltipContext; import net.minecraft.nbt.NbtCompound; import net.minecraft.text.Text; import net.minecraft.util.Formatting; @@ -70,8 +68,8 @@ public boolean isEmpty() { } @Override - public ComponentChanges getComponentChanges() { - return ComponentChanges.EMPTY; + public NbtCompound getNbt() { + return null; } @Override @@ -86,14 +84,14 @@ public Identifier getId() { @Override public List getTooltipText() { - return renderer.getTooltip(ingredient, TooltipType.BASIC); + return renderer.getTooltip(ingredient, TooltipContext.BASIC); } @Override public List getTooltip() { List list = Lists.newArrayList(); MinecraftClient client = MinecraftClient.getInstance(); - list.addAll(renderer.getTooltip(ingredient, client.options.advancedItemTooltips ? TooltipType.ADVANCED : TooltipType.BASIC) + list.addAll(renderer.getTooltip(ingredient, client.options.advancedItemTooltips ? TooltipContext.Default.ADVANCED : TooltipContext.Default.BASIC) .stream().map(EmiPort::ordered).map(TooltipComponent::of).toList()); Identifier id = getId(); diff --git a/xplat/src/main/java/dev/emi/emi/jemi/JemiUtil.java b/xplat/src/main/java/dev/emi/emi/jemi/JemiUtil.java index c69a7403..02574738 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/JemiUtil.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/JemiUtil.java @@ -6,7 +6,6 @@ import dev.emi.emi.api.stack.EmiIngredient; import dev.emi.emi.api.stack.EmiStack; import dev.emi.emi.platform.EmiAgnos; -import dev.emi.emi.runtime.EmiLog; import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.fabric.ingredients.fluids.IJeiFluidIngredient; import mezz.jei.api.helpers.IPlatformFluidHelper; @@ -59,9 +58,7 @@ public static Optional> getTyped(EmiStack stack) { if (stack.isEmpty()) { return Optional.empty(); } else if (stack.getKey() instanceof Fluid f) { - EmiLog.error("TODO implement JEMI support for fluids again"); - return Optional.empty(); - //return JemiPlugin.runtime.getIngredientManager().createTypedIngredient(getFluidType(), getFluidHelper().create(f, stack.getAmount() == 0 ? 1000 : stack.getAmount(), stack.getComponents())); + return JemiPlugin.runtime.getIngredientManager().createTypedIngredient(getFluidType(), getFluidHelper().create(f, stack.getAmount() == 0 ? 1000 : stack.getAmount(), stack.getNbt())); } else if (stack instanceof JemiStack js) { return JemiPlugin.runtime.getIngredientManager().getIngredientTypeChecked(js.ingredient) .map(t -> (Optional) JemiPlugin.runtime.getIngredientManager().createTypedIngredient(t, js.ingredient)) @@ -72,8 +69,7 @@ public static Optional> getTyped(EmiStack stack) { public static EmiStack getFluidFromJei(Object object) { if (object instanceof IJeiFluidIngredient fluid) { - EmiLog.error("TODO implement JEMI support for fluids again"); - //return EmiStack.of(fluid.getFluid(), fluid.getTag().orElseGet(() -> null), fluid.getAmount()); + return EmiStack.of(fluid.getFluid(), fluid.getTag().orElseGet(() -> null), fluid.getAmount()); } return EmiStack.EMPTY; } diff --git a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiIngredientAcceptor.java b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiIngredientAcceptor.java index 47805589..6a35c27b 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiIngredientAcceptor.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiIngredientAcceptor.java @@ -5,8 +5,6 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import dev.emi.emi.runtime.EmiLog; -import net.minecraft.client.item.TooltipType; import org.jetbrains.annotations.Nullable; import com.google.common.collect.Lists; @@ -22,6 +20,7 @@ import mezz.jei.api.ingredients.IIngredientType; import mezz.jei.api.ingredients.ITypedIngredient; import mezz.jei.api.recipe.RecipeIngredientRole; +import net.minecraft.client.item.TooltipContext; import net.minecraft.fluid.Fluid; import net.minecraft.nbt.NbtCompound; import net.minecraft.text.Text; @@ -45,7 +44,7 @@ public void coerceStacks(IRecipeSlotTooltipCallback tooltipCallback, Map base = Lists.newArrayList(); if (renderers != null && renderers.containsKey(typed.getType())) { - base.addAll(((IngredientRenderer) renderers.get(typed.getType())).renderer().getTooltip(typed.getIngredient(), TooltipType.BASIC)); + base.addAll(((IngredientRenderer) renderers.get(typed.getType())).renderer().getTooltip(typed.getIngredient(), TooltipContext.Default.BASIC)); } if (base == null || base.isEmpty()) { if (tooltipCallback == null) { @@ -114,8 +113,7 @@ public JemiIngredientAcceptor addFluidStack(Fluid fluid, long amount) { @Override public JemiIngredientAcceptor addFluidStack(Fluid fluid, long amount, NbtCompound tag) { - EmiLog.error("TODO update JEMI ingredient acceptor to use components"); - //addStack(EmiStack.of(fluid, tag, amount)); + addStack(EmiStack.of(fluid, tag, amount)); return this; } } diff --git a/xplat/src/main/java/dev/emi/emi/mixin/HandledScreenMixin.java b/xplat/src/main/java/dev/emi/emi/mixin/HandledScreenMixin.java index f26a3395..c0ce2775 100644 --- a/xplat/src/main/java/dev/emi/emi/mixin/HandledScreenMixin.java +++ b/xplat/src/main/java/dev/emi/emi/mixin/HandledScreenMixin.java @@ -25,7 +25,7 @@ public abstract class HandledScreenMixin extends Screen { @Dynamic @Inject(at = @At(value = "INVOKE", - target = "net/minecraft/client/gui/screen/ingame/HandledScreen.drawBackground(Lnet/minecraft/client/gui/DrawContext;FII)V", + target = "net/minecraft/client/gui/screen/Screen.renderBackground(Lnet/minecraft/client/gui/DrawContext;IIF)V", shift = Shift.AFTER), method = "renderBackground(Lnet/minecraft/client/gui/DrawContext;IIF)V") private void renderBackground(DrawContext raw, int mouseX, int mouseY, float delta, CallbackInfo info) { diff --git a/xplat/src/main/java/dev/emi/emi/mixin/ItemStackMixin.java b/xplat/src/main/java/dev/emi/emi/mixin/ItemStackMixin.java index afe1efab..79c3a229 100644 --- a/xplat/src/main/java/dev/emi/emi/mixin/ItemStackMixin.java +++ b/xplat/src/main/java/dev/emi/emi/mixin/ItemStackMixin.java @@ -2,9 +2,6 @@ import java.util.List; -import net.minecraft.client.item.TooltipType; -import net.minecraft.item.Item; -import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -14,6 +11,7 @@ import dev.emi.emi.EmiUtil; import dev.emi.emi.config.EmiConfig; import dev.emi.emi.search.EmiSearch; +import net.minecraft.client.item.TooltipContext; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.text.Text; @@ -23,7 +21,7 @@ public class ItemStackMixin { @Inject(at = @At("RETURN"), method = "getTooltip") - private void getTooltip(Item.TooltipContext context, @Nullable PlayerEntity player, TooltipType type, CallbackInfoReturnable> info) { + private void getTooltip(PlayerEntity player, TooltipContext context, CallbackInfoReturnable> info) { if (EmiConfig.appendItemModId && EmiConfig.appendModId && Thread.currentThread() != EmiSearch.searchThread) { List text = info.getReturnValue(); String namespace = EmiPort.getItemRegistry().getId(((ItemStack) (Object) this).getItem()).getNamespace(); diff --git a/xplat/src/main/java/dev/emi/emi/mixin/MouseMixin.java b/xplat/src/main/java/dev/emi/emi/mixin/MouseMixin.java index c550a2a7..9f135e59 100644 --- a/xplat/src/main/java/dev/emi/emi/mixin/MouseMixin.java +++ b/xplat/src/main/java/dev/emi/emi/mixin/MouseMixin.java @@ -23,10 +23,6 @@ public class MouseMixin { @Shadow private int activeButton = -1; - @Shadow private double cursorDeltaX; - - @Shadow private double cursorDeltaY; - @Inject(at = @At(value = "INVOKE", ordinal = 0, target = "net/minecraft/client/gui/screen/Screen.wrapScreenError(Ljava/lang/Runnable;Ljava/lang/String;Ljava/lang/String;)V"), method = "onMouseButton(JIII)V", cancellable = true) @@ -67,15 +63,15 @@ private void onMouseUp(long window, int button, int action, int mods, CallbackIn @Inject(at = @At(value = "INVOKE", ordinal = 1, target = "net/minecraft/client/gui/screen/Screen.wrapScreenError(Ljava/lang/Runnable;Ljava/lang/String;Ljava/lang/String;)V"), - method = "tick", cancellable = true) - private void onMouseDragged(CallbackInfo info) { + method = "onCursorPos(JDD)V", cancellable = true) + private void onMouseDragged(long window, double x, double y, CallbackInfo info) { try { Screen screen = client.currentScreen; if (screen instanceof HandledScreen hs) { double mx = this.x * client.getWindow().getScaledWidth() / client.getWindow().getWidth(); double my = this.y * client.getWindow().getScaledHeight() / client.getWindow().getHeight(); - double dx = this.cursorDeltaX * client.getWindow().getScaledWidth() / client.getWindow().getWidth(); - double dy = this.cursorDeltaY * client.getWindow().getScaledHeight() / client.getWindow().getHeight(); + double dx = (x - this.x) * client.getWindow().getScaledWidth() / client.getWindow().getWidth(); + double dy = (y - this.y) * client.getWindow().getScaledHeight() / client.getWindow().getHeight(); EmiScreenManager.mouseDragged(mx, my, activeButton, dx, dy); } } catch (Exception e) { diff --git a/xplat/src/main/java/dev/emi/emi/mixin/accessor/BrewingRecipeRegistryAccessor.java b/xplat/src/main/java/dev/emi/emi/mixin/accessor/BrewingRecipeRegistryAccessor.java deleted file mode 100644 index 013d584b..00000000 --- a/xplat/src/main/java/dev/emi/emi/mixin/accessor/BrewingRecipeRegistryAccessor.java +++ /dev/null @@ -1,22 +0,0 @@ -package dev.emi.emi.mixin.accessor; - -import net.minecraft.item.Item; -import net.minecraft.potion.Potion; -import net.minecraft.recipe.BrewingRecipeRegistry; -import net.minecraft.recipe.Ingredient; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -import java.util.List; - -@Mixin(BrewingRecipeRegistry.class) -public interface BrewingRecipeRegistryAccessor { - @Accessor("potionTypes") - List getPotionTypes(); - - @Accessor("potionRecipes") - List> getPotionRecipes(); - - @Accessor("itemRecipes") - List> getItemRecipes(); -} diff --git a/xplat/src/main/java/dev/emi/emi/network/CommandS2CPacket.java b/xplat/src/main/java/dev/emi/emi/network/CommandS2CPacket.java index f27253f7..4c5a89ba 100644 --- a/xplat/src/main/java/dev/emi/emi/network/CommandS2CPacket.java +++ b/xplat/src/main/java/dev/emi/emi/network/CommandS2CPacket.java @@ -7,7 +7,6 @@ import dev.emi.emi.registry.EmiCommands; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.network.PacketByteBuf; -import net.minecraft.network.RegistryByteBuf; import net.minecraft.util.Identifier; public class CommandS2CPacket implements EmiPacket { @@ -29,7 +28,7 @@ public CommandS2CPacket(PacketByteBuf buf) { } @Override - public void write(RegistryByteBuf buf) { + public void write(PacketByteBuf buf) { buf.writeByte(type); if (type == EmiCommands.VIEW_RECIPE || type == EmiCommands.TREE_GOAL || type == EmiCommands.TREE_RESOLUTION) { buf.writeIdentifier(id); @@ -61,7 +60,7 @@ public void apply(PlayerEntity player) { } @Override - public Id getId() { + public Identifier getId() { return EmiNetwork.COMMAND; } } diff --git a/xplat/src/main/java/dev/emi/emi/network/CreateItemC2SPacket.java b/xplat/src/main/java/dev/emi/emi/network/CreateItemC2SPacket.java index 0e6ac777..1f644313 100644 --- a/xplat/src/main/java/dev/emi/emi/network/CreateItemC2SPacket.java +++ b/xplat/src/main/java/dev/emi/emi/network/CreateItemC2SPacket.java @@ -4,7 +4,6 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.network.PacketByteBuf; -import net.minecraft.network.RegistryByteBuf; import net.minecraft.util.Identifier; public class CreateItemC2SPacket implements EmiPacket { @@ -16,14 +15,14 @@ public CreateItemC2SPacket(int mode, ItemStack stack) { this.stack = stack; } - public CreateItemC2SPacket(RegistryByteBuf buf) { - this(buf.readByte(), ItemStack.PACKET_CODEC.decode(buf)); + public CreateItemC2SPacket(PacketByteBuf buf) { + this(buf.readByte(), buf.readItemStack()); } @Override - public void write(RegistryByteBuf buf) { + public void write(PacketByteBuf buf) { buf.writeByte(mode); - ItemStack.PACKET_CODEC.encode(buf, stack); + buf.writeItemStack(stack); } @Override @@ -46,7 +45,7 @@ public void apply(PlayerEntity player) { } @Override - public Id getId() { + public Identifier getId() { return EmiNetwork.CREATE_ITEM; } } diff --git a/xplat/src/main/java/dev/emi/emi/network/EmiChessPacket.java b/xplat/src/main/java/dev/emi/emi/network/EmiChessPacket.java index 12d7bda8..8b269a85 100644 --- a/xplat/src/main/java/dev/emi/emi/network/EmiChessPacket.java +++ b/xplat/src/main/java/dev/emi/emi/network/EmiChessPacket.java @@ -5,7 +5,6 @@ import dev.emi.emi.chess.EmiChess; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.network.PacketByteBuf; -import net.minecraft.network.RegistryByteBuf; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.Identifier; @@ -25,7 +24,7 @@ public EmiChessPacket(PacketByteBuf buf) { } @Override - public void write(RegistryByteBuf buf) { + public void write(PacketByteBuf buf) { buf.writeUuid(uuid); buf.writeByte(type); buf.writeByte(start); @@ -33,7 +32,7 @@ public void write(RegistryByteBuf buf) { } @Override - public Id getId() { + public Identifier getId() { return EmiNetwork.CHESS; } diff --git a/xplat/src/main/java/dev/emi/emi/network/EmiNetwork.java b/xplat/src/main/java/dev/emi/emi/network/EmiNetwork.java index 354f7f16..66ff3166 100644 --- a/xplat/src/main/java/dev/emi/emi/network/EmiNetwork.java +++ b/xplat/src/main/java/dev/emi/emi/network/EmiNetwork.java @@ -3,16 +3,15 @@ import java.util.function.BiConsumer; import java.util.function.Consumer; -import net.minecraft.network.packet.CustomPayload; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.Identifier; public class EmiNetwork { - public static final CustomPayload.Id FILL_RECIPE = CustomPayload.id("emi:fill_recipe"); - public static final CustomPayload.Id CREATE_ITEM = CustomPayload.id("emi:create_item"); - public static final CustomPayload.Id COMMAND = CustomPayload.id("emi:command"); - public static final CustomPayload.Id CHESS = CustomPayload.id("emi:chess"); - public static final CustomPayload.Id PING = CustomPayload.id("emi:ping"); + public static final Identifier FILL_RECIPE = new Identifier("emi:fill_recipe"); + public static final Identifier CREATE_ITEM = new Identifier("emi:create_item"); + public static final Identifier COMMAND = new Identifier("emi:command"); + public static final Identifier CHESS = new Identifier("emi:chess"); + public static final Identifier PING = new Identifier("emi:ping"); private static BiConsumer clientSender; private static Consumer serverSender; diff --git a/xplat/src/main/java/dev/emi/emi/network/EmiPacket.java b/xplat/src/main/java/dev/emi/emi/network/EmiPacket.java index 2f5b17a1..8d57fd1c 100644 --- a/xplat/src/main/java/dev/emi/emi/network/EmiPacket.java +++ b/xplat/src/main/java/dev/emi/emi/network/EmiPacket.java @@ -1,12 +1,14 @@ package dev.emi.emi.network; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.network.RegistryByteBuf; -import net.minecraft.network.packet.CustomPayload; +import net.minecraft.network.PacketByteBuf; import net.minecraft.util.Identifier; -public interface EmiPacket extends CustomPayload { - void write(RegistryByteBuf buf); +public interface EmiPacket { + + void write(PacketByteBuf buf); void apply(PlayerEntity player); + + Identifier getId(); } diff --git a/xplat/src/main/java/dev/emi/emi/network/FillRecipeC2SPacket.java b/xplat/src/main/java/dev/emi/emi/network/FillRecipeC2SPacket.java index 1bbca981..cc9bf8e8 100644 --- a/xplat/src/main/java/dev/emi/emi/network/FillRecipeC2SPacket.java +++ b/xplat/src/main/java/dev/emi/emi/network/FillRecipeC2SPacket.java @@ -3,8 +3,6 @@ import java.util.List; import java.util.function.Consumer; -import net.minecraft.network.RegistryByteBuf; -import net.minecraft.registry.entry.RegistryEntry; import org.jetbrains.annotations.Nullable; import com.google.common.collect.Lists; @@ -34,7 +32,7 @@ public FillRecipeC2SPacket(ScreenHandler handler, int action, List slots, this.stacks = stacks; } - public FillRecipeC2SPacket(RegistryByteBuf buf) { + public FillRecipeC2SPacket(PacketByteBuf buf) { syncId = buf.readInt(); action = buf.readByte(); slots = parseCompressedSlots(buf); @@ -52,12 +50,12 @@ public FillRecipeC2SPacket(RegistryByteBuf buf) { int size = buf.readVarInt(); stacks = Lists.newArrayList(); for (int i = 0; i < size; i++) { - stacks.add(ItemStack.PACKET_CODEC.decode(buf)); + stacks.add(buf.readItemStack()); } } @Override - public void write(RegistryByteBuf buf) { + public void write(PacketByteBuf buf) { buf.writeInt(syncId); buf.writeByte(action); writeCompressedSlots(slots, buf); @@ -73,7 +71,7 @@ public void write(RegistryByteBuf buf) { } buf.writeVarInt(stacks.size()); for (ItemStack stack : stacks) { - ItemStack.PACKET_CODEC.encode(buf, stack); + buf.writeItemStack(stack); } } @@ -203,7 +201,7 @@ private static int grabMatching(PlayerEntity player, List slots, List slots, List slots, List getId() { + public Identifier getId() { return EmiNetwork.FILL_RECIPE; } } diff --git a/xplat/src/main/java/dev/emi/emi/network/PingS2CPacket.java b/xplat/src/main/java/dev/emi/emi/network/PingS2CPacket.java index b8e50e11..d56e2fd2 100644 --- a/xplat/src/main/java/dev/emi/emi/network/PingS2CPacket.java +++ b/xplat/src/main/java/dev/emi/emi/network/PingS2CPacket.java @@ -3,7 +3,6 @@ import dev.emi.emi.platform.EmiClient; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.network.PacketByteBuf; -import net.minecraft.network.RegistryByteBuf; import net.minecraft.util.Identifier; public class PingS2CPacket implements EmiPacket { @@ -15,7 +14,7 @@ public PingS2CPacket(PacketByteBuf buf) { } @Override - public void write(RegistryByteBuf buf) { + public void write(PacketByteBuf buf) { } @Override @@ -24,7 +23,7 @@ public void apply(PlayerEntity player) { } @Override - public Id getId() { + public Identifier getId() { return EmiNetwork.PING; } } diff --git a/xplat/src/main/java/dev/emi/emi/platform/EmiAgnos.java b/xplat/src/main/java/dev/emi/emi/platform/EmiAgnos.java index c40ac119..b9532c8f 100644 --- a/xplat/src/main/java/dev/emi/emi/platform/EmiAgnos.java +++ b/xplat/src/main/java/dev/emi/emi/platform/EmiAgnos.java @@ -10,8 +10,6 @@ import dev.emi.emi.registry.EmiPluginContainer; import net.minecraft.client.gui.tooltip.TooltipComponent; import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.component.ComponentChanges; -import net.minecraft.component.ComponentMap; import net.minecraft.fluid.Fluid; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; @@ -96,17 +94,17 @@ public static List getItemTooltip(ItemStack stack) { protected abstract List getItemTooltipAgnos(ItemStack stack); - public static Text getFluidName(Fluid fluid, ComponentChanges componentChanges) { - return delegate.getFluidNameAgnos(fluid, componentChanges); + public static Text getFluidName(Fluid fluid, NbtCompound nbt) { + return delegate.getFluidNameAgnos(fluid, nbt); } - protected abstract Text getFluidNameAgnos(Fluid fluid, ComponentChanges componentChanges); + protected abstract Text getFluidNameAgnos(Fluid fluid, NbtCompound nbt); - public static List getFluidTooltip(Fluid fluid, ComponentChanges componentChanges) { - return delegate.getFluidTooltipAgnos(fluid, componentChanges); + public static List getFluidTooltip(Fluid fluid, NbtCompound nbt) { + return delegate.getFluidTooltipAgnos(fluid, nbt); } - protected abstract List getFluidTooltipAgnos(Fluid fluid, ComponentChanges componentChanges); + protected abstract List getFluidTooltipAgnos(Fluid fluid, NbtCompound nbt); public static boolean isFloatyFluid(FluidEmiStack stack) { return delegate.isFloatyFluidAgnos(stack); diff --git a/xplat/src/main/java/dev/emi/emi/recipe/special/EmiAnvilEnchantRecipe.java b/xplat/src/main/java/dev/emi/emi/recipe/special/EmiAnvilEnchantRecipe.java index 5309f78d..ad92047e 100644 --- a/xplat/src/main/java/dev/emi/emi/recipe/special/EmiAnvilEnchantRecipe.java +++ b/xplat/src/main/java/dev/emi/emi/recipe/special/EmiAnvilEnchantRecipe.java @@ -10,12 +10,13 @@ import dev.emi.emi.api.stack.EmiIngredient; import dev.emi.emi.api.stack.EmiStack; import dev.emi.emi.api.widget.WidgetHolder; -import net.minecraft.component.DataComponentTypes; -import net.minecraft.component.type.ItemEnchantmentsComponent; import net.minecraft.enchantment.Enchantment; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtElement; +import net.minecraft.nbt.NbtList; import net.minecraft.util.Identifier; public class EmiAnvilEnchantRecipe implements EmiRecipe { @@ -84,9 +85,16 @@ private ItemStack getTool() { private EmiStack getBook() { ItemStack item = new ItemStack(Items.ENCHANTED_BOOK); - var enchBuilder = new ItemEnchantmentsComponent.Builder(ItemEnchantmentsComponent.DEFAULT); - enchBuilder.add(enchantment, level); - item.set(DataComponentTypes.STORED_ENCHANTMENTS, enchBuilder.build()); + NbtCompound tag = new NbtCompound(); + NbtList StoredEnchantments = new NbtList(); + NbtCompound enchant = new NbtCompound(); + String id = getTool().getNbt().getList("Enchantments", NbtElement.COMPOUND_TYPE).getCompound(0).getString("id"); + + enchant.putString("id", id); + enchant.putShort("lvl", (short) level); + StoredEnchantments.add(enchant); + tag.put("StoredEnchantments", StoredEnchantments); + item.setNbt(tag); return EmiStack.of(item); } } diff --git a/xplat/src/main/java/dev/emi/emi/recipe/special/EmiAnvilRepairItemRecipe.java b/xplat/src/main/java/dev/emi/emi/recipe/special/EmiAnvilRepairItemRecipe.java index 299ad2bf..27216f20 100644 --- a/xplat/src/main/java/dev/emi/emi/recipe/special/EmiAnvilRepairItemRecipe.java +++ b/xplat/src/main/java/dev/emi/emi/recipe/special/EmiAnvilRepairItemRecipe.java @@ -83,7 +83,7 @@ protected EmiStack getItem(Random random, int item) { private ItemStack getMergeItems(List items) { ItemStack item = tool.getDefaultStack(); - int maxDamage = item.getMaxDamage(); + int maxDamage = tool.getMaxDamage(); int damage = items.get(0).getDamage() - (21 * maxDamage)/20 + items.get(1).getDamage(); if (damage > 0) { item.setDamage(damage); diff --git a/xplat/src/main/java/dev/emi/emi/recipe/special/EmiArmorDyeRecipe.java b/xplat/src/main/java/dev/emi/emi/recipe/special/EmiArmorDyeRecipe.java index 43cd9a58..5bb3a1da 100644 --- a/xplat/src/main/java/dev/emi/emi/recipe/special/EmiArmorDyeRecipe.java +++ b/xplat/src/main/java/dev/emi/emi/recipe/special/EmiArmorDyeRecipe.java @@ -12,8 +12,8 @@ import dev.emi.emi.api.stack.EmiStack; import dev.emi.emi.api.widget.GeneratedSlotWidget; import dev.emi.emi.api.widget.SlotWidget; -import net.minecraft.component.type.DyedColorComponent; import net.minecraft.item.DyeItem; +import net.minecraft.item.DyeableItem; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.DyeColor; @@ -49,7 +49,7 @@ public SlotWidget getInputWidget(int slot, int x, int y) { @Override public SlotWidget getOutputWidget(int x, int y) { return new GeneratedSlotWidget(r -> { - return EmiStack.of(DyedColorComponent.setColor(new ItemStack(armor), getDyes(r))); + return EmiStack.of(DyeableItem.blendAndSetColor(new ItemStack(armor), getDyes(r))); }, unique, x, y); } diff --git a/xplat/src/main/java/dev/emi/emi/recipe/special/EmiBannerDuplicateRecipe.java b/xplat/src/main/java/dev/emi/emi/recipe/special/EmiBannerDuplicateRecipe.java index 234ed614..bd5d67a1 100644 --- a/xplat/src/main/java/dev/emi/emi/recipe/special/EmiBannerDuplicateRecipe.java +++ b/xplat/src/main/java/dev/emi/emi/recipe/special/EmiBannerDuplicateRecipe.java @@ -11,8 +11,6 @@ import net.minecraft.block.entity.BannerPattern; import net.minecraft.block.entity.BlockEntityType; -import net.minecraft.component.DataComponentTypes; -import net.minecraft.component.type.BannerPatternsComponent; import net.minecraft.item.BlockItem; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; @@ -57,13 +55,16 @@ public SlotWidget getOutputWidget(int x, int y) { public EmiStack getPattern(Random random, boolean reminder) { ItemStack stack = new ItemStack(banner); int patterns = 1 + Math.max(random.nextInt(5), random.nextInt(3)); - BannerPatternsComponent pattern = BannerPatternsComponent.DEFAULT; + BannerPattern.Patterns pattern = new BannerPattern.Patterns(); for (int i = 0; i < patterns; i++) { pattern = EmiPort.addRandomBanner(pattern, random); } - stack.set(DataComponentTypes.BANNER_PATTERNS, pattern); + NbtCompound tag = new NbtCompound(); + tag.put("Patterns", pattern.toNbt()); + BlockItem.setBlockEntityNbt(stack, BlockEntityType.BANNER, tag); + //stack.setNbt(tag); EmiStack emiStack = EmiStack.of(stack); if (reminder) { emiStack.setRemainder(EmiStack.of(stack)); diff --git a/xplat/src/main/java/dev/emi/emi/recipe/special/EmiBannerShieldRecipe.java b/xplat/src/main/java/dev/emi/emi/recipe/special/EmiBannerShieldRecipe.java index 228d8c0d..2115eb3f 100644 --- a/xplat/src/main/java/dev/emi/emi/recipe/special/EmiBannerShieldRecipe.java +++ b/xplat/src/main/java/dev/emi/emi/recipe/special/EmiBannerShieldRecipe.java @@ -13,8 +13,6 @@ import dev.emi.emi.api.widget.SlotWidget; import net.minecraft.block.entity.BannerPattern; import net.minecraft.block.entity.BlockEntityType; -import net.minecraft.component.DataComponentTypes; -import net.minecraft.component.type.BannerPatternsComponent; import net.minecraft.item.BannerItem; import net.minecraft.item.BlockItem; import net.minecraft.item.Item; @@ -60,13 +58,17 @@ public EmiStack getPattern(Random random, Item item) { } ItemStack stack = new ItemStack(item); int patterns = 1 + Math.max(random.nextInt(5), random.nextInt(3)); - BannerPatternsComponent pattern = BannerPatternsComponent.DEFAULT; + BannerPattern.Patterns pattern = new BannerPattern.Patterns(); for (int i = 0; i < patterns; i++) { pattern = EmiPort.addRandomBanner(pattern, random); } - - stack.set(DataComponentTypes.BANNER_PATTERNS, pattern); - + NbtCompound tag = new NbtCompound(); + tag.put("Patterns", pattern.toNbt()); + if (item == Items.SHIELD) { + tag.putInt("Base", ((BannerItem) BANNERS.get(base)).getColor().getId()); + } + BlockItem.setBlockEntityNbt(stack, BlockEntityType.BANNER, tag); + //stack.setNbt(tag); return EmiStack.of(stack); } } diff --git a/xplat/src/main/java/dev/emi/emi/recipe/special/EmiBookCloningRecipe.java b/xplat/src/main/java/dev/emi/emi/recipe/special/EmiBookCloningRecipe.java index d5606b84..a7d89fc7 100644 --- a/xplat/src/main/java/dev/emi/emi/recipe/special/EmiBookCloningRecipe.java +++ b/xplat/src/main/java/dev/emi/emi/recipe/special/EmiBookCloningRecipe.java @@ -10,14 +10,11 @@ import dev.emi.emi.api.widget.GeneratedSlotWidget; import dev.emi.emi.api.widget.SlotWidget; import dev.emi.emi.platform.EmiAgnos; -import net.minecraft.component.DataComponentTypes; -import net.minecraft.component.type.WrittenBookContentComponent; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.item.WrittenBookItem; import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtList; -import net.minecraft.text.RawFilteredPair; import net.minecraft.util.Identifier; public class EmiBookCloningRecipe extends EmiPatternCraftingRecipe { @@ -81,15 +78,17 @@ private EmiStack getWrittenBook(Random random, boolean copy) { if (title.length() > 0) { title = Character.toUpperCase(title.charAt(0)) + title.substring(1, title.length()); } + tag.putString(WrittenBookItem.TITLE_KEY, title); String author; if (random.nextInt(20) < 5) { author = MOD_AUTHORS.get(random.nextInt(MOD_AUTHORS.size())); } else { author = AUTHORS.get(random.nextInt(AUTHORS.size())); } - int generationKey = (copy ? 1 : 0) + random.nextInt(2); - stack.set(DataComponentTypes.WRITTEN_BOOK_CONTENT, new WrittenBookContentComponent(RawFilteredPair.of(title), author, generationKey, List.of(), false)); - + tag.putString(WrittenBookItem.AUTHOR_KEY, author); + tag.putInt(WrittenBookItem.GENERATION_KEY, (copy ? 1 : 0) + random.nextInt(2)); + tag.put("pages", new NbtList()); + stack.setNbt(tag); return EmiStack.of(stack); } diff --git a/xplat/src/main/java/dev/emi/emi/recipe/special/EmiFireworkRocketRecipe.java b/xplat/src/main/java/dev/emi/emi/recipe/special/EmiFireworkRocketRecipe.java index 448e9b96..aa6112fa 100644 --- a/xplat/src/main/java/dev/emi/emi/recipe/special/EmiFireworkRocketRecipe.java +++ b/xplat/src/main/java/dev/emi/emi/recipe/special/EmiFireworkRocketRecipe.java @@ -1,6 +1,5 @@ package dev.emi.emi.recipe.special; -import java.util.ArrayList; import java.util.List; import java.util.Random; import java.util.stream.Stream; @@ -11,12 +10,6 @@ import dev.emi.emi.api.stack.EmiStack; import dev.emi.emi.api.widget.GeneratedSlotWidget; import dev.emi.emi.api.widget.SlotWidget; -import it.unimi.dsi.fastutil.ints.IntArrayList; -import it.unimi.dsi.fastutil.ints.IntList; -import it.unimi.dsi.fastutil.ints.IntLists; -import net.minecraft.component.DataComponentTypes; -import net.minecraft.component.type.FireworkExplosionComponent; -import net.minecraft.component.type.FireworksComponent; import net.minecraft.item.DyeItem; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; @@ -60,19 +53,27 @@ public SlotWidget getOutputWidget(int x, int y) { private EmiStack getFireworkRocket(Random random) { ItemStack stack = new ItemStack(Items.FIREWORK_ROCKET); - List explosions = new ArrayList<>(); + NbtCompound tag = new NbtCompound(); + NbtCompound fireworks = new NbtCompound(); + NbtList explosions = new NbtList(); List items = getItems(random); int gunpowder = 0; for (EmiStack item : items) { if (item.getId() == EmiStack.of(Items.FIREWORK_STAR).getId()){ - explosions.add(item.getOrDefault(DataComponentTypes.FIREWORK_EXPLOSION, FireworkExplosionComponent.DEFAULT)); + explosions.add(item.getNbt().get("Explosion")); } else if (item.isEqual(EmiStack.of(Items.GUNPOWDER))) { gunpowder++; } } - - stack.set(DataComponentTypes.FIREWORKS, new FireworksComponent(gunpowder, explosions)); + if (gunpowder > 1) { + fireworks.putByte("Flight", (byte) gunpowder); + } + if (!(items.isEmpty())) { + fireworks.put("Explosions", explosions); + } + tag.put("Fireworks", fireworks); + stack.setNbt(tag); return EmiStack.of(stack, 3); } @@ -101,11 +102,12 @@ private List getDyes(Random random, int max) { private EmiStack getFireworkStar(Random random) { ItemStack stack = new ItemStack(Items.FIREWORK_STAR); + NbtCompound tag = new NbtCompound(); + NbtCompound explosion = new NbtCompound(); int items = 0; int amount = random.nextInt(5); - - FireworkExplosionComponent.Type type = FireworkExplosionComponent.Type.values()[random.nextInt(FireworkExplosionComponent.Type.values().length)]; + explosion.putByte("Type", (byte) amount); if (!(amount == 0)) { items++; @@ -113,43 +115,38 @@ private EmiStack getFireworkStar(Random random) { amount = random.nextInt(4); - boolean flicker = false, trail = false; - if (amount == 0) { - flicker = true; + explosion.putByte("Flicker", (byte) 1); items++; } else if (amount == 1) { - trail = true; + explosion.putByte("Trail", (byte) 1); items++; } else if (amount == 2){ - flicker = true; - trail = true; + explosion.putByte("Trail", (byte) 1); + explosion.putByte("Flicker", (byte) 1); items = items + 2; } List dyeItems = getDyes(random, 8 - items); - IntList colors = new IntArrayList(); + List colors = Lists.newArrayList(); for (DyeItem dyeItem : dyeItems) { colors.add(dyeItem.getColor().getFireworkColor()); } + explosion.putIntArray("Colors", colors); amount = random.nextInt(2); - IntList fadedColors; - if (amount == 1) { List dyeItemsFaded = getDyes(random, 8); - fadedColors = new IntArrayList(); + List fadedColors = Lists.newArrayList(); for (DyeItem dyeItem : dyeItemsFaded) { fadedColors.add(dyeItem.getColor().getFireworkColor()); } - } else { - fadedColors = IntLists.emptyList(); + explosion.putIntArray("FadeColors", fadedColors); } - FireworkExplosionComponent component = new FireworkExplosionComponent(type, colors, fadedColors, trail, flicker); - - stack.set(DataComponentTypes.FIREWORK_EXPLOSION, component); + tag.put("Explosion", explosion); + stack.setNbt(tag); return EmiStack.of(stack); } } diff --git a/xplat/src/main/java/dev/emi/emi/recipe/special/EmiFireworkStarFadeRecipe.java b/xplat/src/main/java/dev/emi/emi/recipe/special/EmiFireworkStarFadeRecipe.java index b2ed7b62..0d6be9b7 100644 --- a/xplat/src/main/java/dev/emi/emi/recipe/special/EmiFireworkStarFadeRecipe.java +++ b/xplat/src/main/java/dev/emi/emi/recipe/special/EmiFireworkStarFadeRecipe.java @@ -12,11 +12,6 @@ import dev.emi.emi.api.stack.EmiStack; import dev.emi.emi.api.widget.GeneratedSlotWidget; import dev.emi.emi.api.widget.SlotWidget; -import it.unimi.dsi.fastutil.ints.IntArrayList; -import it.unimi.dsi.fastutil.ints.IntList; -import it.unimi.dsi.fastutil.ints.IntLists; -import net.minecraft.component.DataComponentTypes; -import net.minecraft.component.type.FireworkExplosionComponent; import net.minecraft.item.DyeItem; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; @@ -65,11 +60,12 @@ private List getDyes(Random random, int max) { private EmiStack getFireworkStar(Random random, Boolean faded) { ItemStack stack = new ItemStack(Items.FIREWORK_STAR); + NbtCompound tag = new NbtCompound(); + NbtCompound explosion = new NbtCompound(); int items = 0; int amount = random.nextInt(5); - - FireworkExplosionComponent.Type type = FireworkExplosionComponent.Type.values()[random.nextInt(FireworkExplosionComponent.Type.values().length)]; + explosion.putByte("Type", (byte) amount); if (!(amount == 0)) { items++; @@ -77,41 +73,36 @@ private EmiStack getFireworkStar(Random random, Boolean faded) { amount = random.nextInt(4); - boolean flicker = false, trail = false; - if (amount == 0) { - flicker = true; + explosion.putByte("Flicker", (byte) 1); items++; } else if (amount == 1) { - trail = true; + explosion.putByte("Trail", (byte) 1); items++; } else if (amount == 2){ - flicker = true; - trail = true; + explosion.putByte("Trail", (byte) 1); + explosion.putByte("Flicker", (byte) 1); items = items + 2; } List dyeItems = getDyes(random, 8 - items); - IntList colors = new IntArrayList(); + List colors = Lists.newArrayList(); for (DyeItem dyeItem : dyeItems) { colors.add(dyeItem.getColor().getFireworkColor()); } - - IntList fadedColors; + explosion.putIntArray("Colors", colors); if (faded) { List dyeItemsFaded = getDyes(random, 8); - fadedColors = new IntArrayList(); + List fadedColors = Lists.newArrayList(); for (DyeItem dyeItem : dyeItemsFaded) { fadedColors.add(dyeItem.getColor().getFireworkColor()); } - } else { - fadedColors = IntLists.emptyList(); + explosion.putIntArray("FadeColors", fadedColors); } - FireworkExplosionComponent component = new FireworkExplosionComponent(type, colors, fadedColors, trail, flicker); - - stack.set(DataComponentTypes.FIREWORK_EXPLOSION, component); + tag.put("Explosion", explosion); + stack.setNbt(tag); return EmiStack.of(stack); } } diff --git a/xplat/src/main/java/dev/emi/emi/recipe/special/EmiFireworkStarRecipe.java b/xplat/src/main/java/dev/emi/emi/recipe/special/EmiFireworkStarRecipe.java index 3063962e..c43135ae 100644 --- a/xplat/src/main/java/dev/emi/emi/recipe/special/EmiFireworkStarRecipe.java +++ b/xplat/src/main/java/dev/emi/emi/recipe/special/EmiFireworkStarRecipe.java @@ -12,10 +12,6 @@ import dev.emi.emi.api.stack.EmiStack; import dev.emi.emi.api.widget.GeneratedSlotWidget; import dev.emi.emi.api.widget.SlotWidget; -import it.unimi.dsi.fastutil.ints.IntArrayList; -import it.unimi.dsi.fastutil.ints.IntList; -import net.minecraft.component.DataComponentTypes; -import net.minecraft.component.type.FireworkExplosionComponent; import net.minecraft.item.DyeItem; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; @@ -91,32 +87,47 @@ private List getItems(Random random) { private EmiStack getFireworkStar(Random random) { ItemStack stack = new ItemStack(Items.FIREWORK_STAR); - List items = getItems(random); - FireworkExplosionComponent.Type type = FireworkExplosionComponent.Type.SMALL_BALL; - IntList colors = new IntArrayList(); + NbtCompound tag = new NbtCompound(); + NbtCompound explosion = new NbtCompound(); + boolean hasShape = false; - boolean flicker = false, trail = false; + List items = getItems(random); + byte smallBall = 0; + byte largeBall = 1; + byte star = 2; + byte creeper = 3; + byte burst = 4; + List colors = Lists.newArrayList(); for (Item item : items) { if (Items.GLOWSTONE_DUST.equals(item)) { - flicker = true; + explosion.putByte("Flicker", largeBall); } else if (Items.DIAMOND.equals(item)) { - trail = true; + explosion.putByte("Trail", largeBall); } else if (Items.FIRE_CHARGE.equals(item)) { - type = FireworkExplosionComponent.Type.LARGE_BALL; + explosion.putByte("Type", largeBall); + hasShape = true; } else if (Items.GOLD_NUGGET.equals(item)) { - type = FireworkExplosionComponent.Type.STAR; + explosion.putByte("Type", star); + hasShape = true; } else if (Items.FEATHER.equals(item)) { - type = FireworkExplosionComponent.Type.BURST; + explosion.putByte("Type", burst); + hasShape = true; } else if (SHAPES.contains(item)) { - type = FireworkExplosionComponent.Type.CREEPER; + explosion.putByte("Type", creeper); + hasShape = true; } else { DyeItem dyeItem = (DyeItem) item; colors.add(dyeItem.getColor().getFireworkColor()); } } + if (!hasShape) { + explosion.putByte("Type", smallBall); + } - stack.set(DataComponentTypes.FIREWORK_EXPLOSION, new FireworkExplosionComponent(type, colors, IntList.of(), trail, flicker)); + explosion.putIntArray("Colors", colors); + tag.put("Explosion", explosion); + stack.setNbt(tag); return EmiStack.of(stack); } } diff --git a/xplat/src/main/java/dev/emi/emi/recipe/special/EmiGrindstoneDisenchantingBookRecipe.java b/xplat/src/main/java/dev/emi/emi/recipe/special/EmiGrindstoneDisenchantingBookRecipe.java index a9244be4..4c2c8a8a 100644 --- a/xplat/src/main/java/dev/emi/emi/recipe/special/EmiGrindstoneDisenchantingBookRecipe.java +++ b/xplat/src/main/java/dev/emi/emi/recipe/special/EmiGrindstoneDisenchantingBookRecipe.java @@ -8,11 +8,12 @@ import dev.emi.emi.api.stack.EmiStack; import dev.emi.emi.api.widget.WidgetHolder; import dev.emi.emi.api.widget.TextWidget.Alignment; -import net.minecraft.component.DataComponentTypes; -import net.minecraft.component.type.ItemEnchantmentsComponent; import net.minecraft.enchantment.Enchantment; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtElement; +import net.minecraft.nbt.NbtList; import net.minecraft.text.OrderedText; import net.minecraft.util.Identifier; @@ -75,11 +76,20 @@ public void addWidgets(WidgetHolder widgets) { } private EmiStack getBook() { - ItemStack book = new ItemStack(Items.ENCHANTED_BOOK); + ItemStack enchantedTool = new ItemStack(Items.ENCHANTED_BOOK);; + enchantedTool.addEnchantment(enchantment, level); - var enchBuilder = new ItemEnchantmentsComponent.Builder(ItemEnchantmentsComponent.DEFAULT); - enchBuilder.add(enchantment, level); - book.set(DataComponentTypes.STORED_ENCHANTMENTS, enchBuilder.build()); + ItemStack book = new ItemStack(Items.ENCHANTED_BOOK); + NbtCompound tag = new NbtCompound(); + NbtList StoredEnchantments = new NbtList(); + NbtCompound enchant = new NbtCompound(); + String id = enchantedTool.getNbt().getList("Enchantments", NbtElement.COMPOUND_TYPE).getCompound(0).getString("id"); + + enchant.putString("id", id); + enchant.putShort("lvl", (short) level); + StoredEnchantments.add(enchant); + tag.put("StoredEnchantments", StoredEnchantments); + book.setNbt(tag); return EmiStack.of(book); } diff --git a/xplat/src/main/java/dev/emi/emi/recipe/special/EmiRepairItemRecipe.java b/xplat/src/main/java/dev/emi/emi/recipe/special/EmiRepairItemRecipe.java index 9f6c7829..dade083a 100644 --- a/xplat/src/main/java/dev/emi/emi/recipe/special/EmiRepairItemRecipe.java +++ b/xplat/src/main/java/dev/emi/emi/recipe/special/EmiRepairItemRecipe.java @@ -11,14 +11,13 @@ import dev.emi.emi.api.stack.EmiStack; import dev.emi.emi.api.widget.GeneratedSlotWidget; import dev.emi.emi.api.widget.SlotWidget; -import net.minecraft.component.DataComponentTypes; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.Identifier; public class EmiRepairItemRecipe extends EmiPatternCraftingRecipe { public static final List TOOLS = EmiPort.getItemRegistry().stream() - .filter(i -> i.getComponents().getOrDefault(DataComponentTypes.MAX_DAMAGE, 0) > 0).collect(Collectors.toList()); + .filter(Item::isDamageable).collect(Collectors.toList()); private final Item tool; public EmiRepairItemRecipe(Item tool, Identifier id) { @@ -55,7 +54,7 @@ private List getItems(Random random) { private ItemStack getMergeItems(Random random) { List items = getItems(random); ItemStack item = tool.getDefaultStack(); - int maxDamage = item.getMaxDamage(); + int maxDamage = tool.getMaxDamage(); int damage = items.get(0).getDamage() - (21 * maxDamage)/20 + items.get(1).getDamage(); if (damage > 0) { item.setDamage(damage); diff --git a/xplat/src/main/java/dev/emi/emi/recipe/special/EmiSuspiciousStewRecipe.java b/xplat/src/main/java/dev/emi/emi/recipe/special/EmiSuspiciousStewRecipe.java index 40bf65a0..351b2b21 100644 --- a/xplat/src/main/java/dev/emi/emi/recipe/special/EmiSuspiciousStewRecipe.java +++ b/xplat/src/main/java/dev/emi/emi/recipe/special/EmiSuspiciousStewRecipe.java @@ -11,8 +11,6 @@ import dev.emi.emi.api.widget.GeneratedSlotWidget; import dev.emi.emi.api.widget.SlotWidget; import net.minecraft.block.FlowerBlock; -import net.minecraft.component.DataComponentTypes; -import net.minecraft.component.type.SuspiciousStewEffectsComponent; import net.minecraft.item.BlockItem; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; @@ -52,7 +50,7 @@ public SlotWidget getOutputWidget(int x, int y) { return new GeneratedSlotWidget(r -> { FlowerBlock block = (FlowerBlock) ((BlockItem) getFlower(r)).getBlock(); ItemStack stack = new ItemStack(Items.SUSPICIOUS_STEW); - stack.set(DataComponentTypes.SUSPICIOUS_STEW_EFFECTS, block.getStewEffects()); + SuspiciousStewItem.addEffectsToStew(stack, block.getStewEffects()); return EmiStack.of(stack); }, unique, x, y); } diff --git a/xplat/src/main/java/dev/emi/emi/registry/EmiRecipeFiller.java b/xplat/src/main/java/dev/emi/emi/registry/EmiRecipeFiller.java index 340430e6..8bdb32dc 100644 --- a/xplat/src/main/java/dev/emi/emi/registry/EmiRecipeFiller.java +++ b/xplat/src/main/java/dev/emi/emi/registry/EmiRecipeFiller.java @@ -150,7 +150,7 @@ public static boolean performFill(EmiRecipe recipe, Ha ItemStack ss = s.getStack(); if (EmiStack.of(s.getStack()).isEqual(stack)) { for (DiscoveredItem di : d) { - if (ItemStack.areItemsAndComponentsEqual(ss, di.stack)) { + if (ItemStack.canCombine(ss, di.stack)) { di.amount += ss.getCount(); continue slotLoop; } @@ -193,7 +193,7 @@ public static boolean performFill(EmiRecipe recipe, Ha continue; } for (DiscoveredItem ui : unique) { - if (ItemStack.areItemsAndComponentsEqual(di.stack, ui.stack)) { + if (ItemStack.canCombine(di.stack, ui.stack)) { ui.consumed += di.consumed; continue outer; } @@ -313,7 +313,7 @@ public static boolean clientFill(StandardRecipeHandler continue; } ItemStack is = input.getStack().copy(); - if (ItemStack.areItemsAndComponentsEqual(is, stack)) { + if (ItemStack.canCombine(is, stack)) { manager.clickSlot(screenHandler.syncId, input.id, 0, SlotActionType.PICKUP, player); if (is.getCount() <= needed) { needed -= is.getCount(); diff --git a/xplat/src/main/java/dev/emi/emi/registry/EmiStackList.java b/xplat/src/main/java/dev/emi/emi/registry/EmiStackList.java index d192c2f7..d1df87fe 100644 --- a/xplat/src/main/java/dev/emi/emi/registry/EmiStackList.java +++ b/xplat/src/main/java/dev/emi/emi/registry/EmiStackList.java @@ -28,8 +28,6 @@ import it.unimi.dsi.fastutil.objects.ObjectOpenCustomHashSet; import net.minecraft.block.Block; import net.minecraft.client.MinecraftClient; -import net.minecraft.component.ComponentChanges; -import net.minecraft.component.ComponentMap; import net.minecraft.fluid.FlowableFluid; import net.minecraft.fluid.Fluid; import net.minecraft.fluid.Fluids; @@ -281,9 +279,9 @@ public boolean equals(EmiStack a, EmiStack b) { @Override public int hashCode(EmiStack stack) { if (stack != null) { - ComponentChanges changes = stack.getComponentChanges(); + NbtCompound nbtCompound = stack.getNbt(); int i = 31 + stack.getKey().hashCode(); - return 31 * i + changes.hashCode(); + return 31 * i + (nbtCompound == null ? 0 : nbtCompound.hashCode()); } return 0; } diff --git a/xplat/src/main/java/dev/emi/emi/runtime/EmiScreenshotRecorder.java b/xplat/src/main/java/dev/emi/emi/runtime/EmiScreenshotRecorder.java index 5e06a7fd..189e640b 100644 --- a/xplat/src/main/java/dev/emi/emi/runtime/EmiScreenshotRecorder.java +++ b/xplat/src/main/java/dev/emi/emi/runtime/EmiScreenshotRecorder.java @@ -19,7 +19,6 @@ import net.minecraft.text.Style; import net.minecraft.text.Text; import net.minecraft.util.Util; -import org.joml.Matrix4fStack; public class EmiScreenshotRecorder { private static final String SCREENSHOTS_DIRNAME = "screenshots"; @@ -65,12 +64,12 @@ private static void saveScreenshotInner(String path, int width, int height, Runn framebuffer.beginWrite(true); - Matrix4fStack view = RenderSystem.getModelViewStack(); - view.pushMatrix(); - view.identity(); - view.translate(-1.0f, 1.0f, 0.0f); + MatrixStack view = RenderSystem.getModelViewStack(); + view.push(); + view.loadIdentity(); + view.translate(-1.0, 1.0, 0.0); view.scale(2f / width, -2f / height, -1f / 1000f); - view.translate(0.0f, 0.0f, 10.0f); + view.translate(0.0, 0.0, 10.0); RenderSystem.applyModelViewMatrix(); Matrix4f backupProj = RenderSystem.getProjectionMatrix(); @@ -79,7 +78,7 @@ private static void saveScreenshotInner(String path, int width, int height, Runn renderer.run(); RenderSystem.setProjectionMatrix(backupProj, VertexSorter.BY_Z); - view.popMatrix(); + view.pop(); RenderSystem.applyModelViewMatrix(); framebuffer.endWrite(); diff --git a/xplat/src/main/java/dev/emi/emi/screen/BoMScreen.java b/xplat/src/main/java/dev/emi/emi/screen/BoMScreen.java index 9a759874..f9a2bd32 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/BoMScreen.java +++ b/xplat/src/main/java/dev/emi/emi/screen/BoMScreen.java @@ -7,8 +7,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import org.joml.Matrix4f; -import org.joml.Matrix4fStack; import org.lwjgl.glfw.GLFW; import com.google.common.collect.Lists; @@ -195,7 +193,7 @@ public void recalculateTree() { @Override public void render(DrawContext raw, int mouseX, int mouseY, float delta) { EmiDrawContext context = EmiDrawContext.wrap(raw); - this.renderDarkening(context.raw()); + this.renderBackgroundTexture(context.raw()); lastMouseX = mouseX; lastMouseY = mouseY; float scale = getScale(); @@ -213,11 +211,11 @@ public void render(DrawContext raw, int mouseX, int mouseY, float delta) { int mx = (int) ((mouseX - width / 2) / scale - offX); int my = (int) ((mouseY - height / 2) / scale - offY); - Matrix4fStack view = RenderSystem.getModelViewStack(); - view.pushMatrix(); + MatrixStack view = RenderSystem.getModelViewStack(); + view.push(); view.translate(width / 2, height / 2, 0); view.scale(scale, scale, 1); - view.translate((float)offX, (float)offY, 0); + view.translate(offX, offY, 0); RenderSystem.applyModelViewMatrix(); if (BoM.tree != null) { batcher.begin(0, 0, 0); @@ -252,7 +250,7 @@ public void render(DrawContext raw, int mouseX, int mouseY, float delta) { context.drawCenteredText(EmiPort.translatable("emi.random_tree_input"), 0, 0); } - view.popMatrix(); + view.pop(); RenderSystem.applyModelViewMatrix(); if (help.contains(mouseX, mouseY)) { diff --git a/xplat/src/main/java/dev/emi/emi/screen/ConfigEnumScreen.java b/xplat/src/main/java/dev/emi/emi/screen/ConfigEnumScreen.java index 43f312bd..c894bf99 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/ConfigEnumScreen.java +++ b/xplat/src/main/java/dev/emi/emi/screen/ConfigEnumScreen.java @@ -51,7 +51,7 @@ public void init() { public void render(DrawContext raw, int mouseX, int mouseY, float delta) { EmiDrawContext context = EmiDrawContext.wrap(raw); list.setScrollAmount(list.getScrollAmount()); - this.renderDarkening(context.raw()); + this.renderBackgroundTexture(context.raw()); list.render(context.raw(), mouseX, mouseY, delta); super.render(context.raw(), mouseX, mouseY, delta); ListWidget.Entry entry = list.getHoveredEntry(); diff --git a/xplat/src/main/java/dev/emi/emi/screen/ConfigPresetScreen.java b/xplat/src/main/java/dev/emi/emi/screen/ConfigPresetScreen.java index ad95b055..985cec15 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/ConfigPresetScreen.java +++ b/xplat/src/main/java/dev/emi/emi/screen/ConfigPresetScreen.java @@ -74,7 +74,7 @@ public void init() { public void render(DrawContext raw, int mouseX, int mouseY, float delta) { EmiDrawContext context = EmiDrawContext.wrap(raw); list.setScrollAmount(list.getScrollAmount()); - this.renderDarkening(context.raw()); + this.renderBackgroundTexture(context.raw()); list.render(context.raw(), mouseX, mouseY, delta); super.render(context.raw(), mouseX, mouseY, delta); if (list.getHoveredEntry() instanceof PresetWidget widget) { diff --git a/xplat/src/main/java/dev/emi/emi/screen/ConfigScreen.java b/xplat/src/main/java/dev/emi/emi/screen/ConfigScreen.java index c9783454..de776c98 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/ConfigScreen.java +++ b/xplat/src/main/java/dev/emi/emi/screen/ConfigScreen.java @@ -366,7 +366,7 @@ public void updateChanges() { public void render(DrawContext raw, int mouseX, int mouseY, float delta) { EmiDrawContext context = EmiDrawContext.wrap(raw); list.setScrollAmount(list.getScrollAmount()); - this.renderDarkening(context.raw()); + this.renderBackgroundTexture(context.raw()); list.render(context.raw(), mouseX, mouseY, delta); super.render(context.raw(), mouseX, mouseY, delta); if (list.getHoveredEntry() != null) { diff --git a/xplat/src/main/java/dev/emi/emi/screen/EmiScreenManager.java b/xplat/src/main/java/dev/emi/emi/screen/EmiScreenManager.java index 6cc6814a..06fbbe34 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/EmiScreenManager.java +++ b/xplat/src/main/java/dev/emi/emi/screen/EmiScreenManager.java @@ -7,9 +7,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import net.minecraft.component.ComponentChanges; import org.jetbrains.annotations.Nullable; -import org.joml.Matrix4fStack; import org.lwjgl.glfw.GLFW; import com.google.common.collect.Lists; @@ -662,8 +660,8 @@ private static void renderLastHoveredCraftable(EmiDrawContext context, int mouse if (cur.getRecipeContext() != lastHoveredCraftable.getRecipeContext()) { ScreenSpace space = getHoveredSpace(mouseX, mouseY); if (space != null && (space.getType() == SidebarType.CRAFTABLES || space.getType() == SidebarType.CRAFT_HISTORY)) { - Matrix4fStack view = RenderSystem.getModelViewStack(); - view.pushMatrix(); + MatrixStack view = RenderSystem.getModelViewStack(); + view.push(); view.translate(0, 0, 200); RenderSystem.applyModelViewMatrix(); int lhx = space.getRawX(lastHoveredCraftableOffset); @@ -671,7 +669,7 @@ private static void renderLastHoveredCraftable(EmiDrawContext context, int mouse context.fill(lhx, lhy, 18, 18, 0x44AA00FF); lastHoveredCraftable.getStack().render(context.raw(), lhx + 1, lhy + 1, delta, EmiIngredient.RENDER_ICON); - view.popMatrix(); + view.pop(); RenderSystem.applyModelViewMatrix(); } } @@ -1284,8 +1282,8 @@ private static boolean give(EmiStack stack, int amount, int mode) { if (!is.isEmpty()) { Identifier id = EmiPort.getItemRegistry().getId(is.getItem()); String command = "give @s " + id; - if (is.getComponentChanges() != ComponentChanges.EMPTY) { - command += is.getComponentChanges().toString(); + if (is.hasNbt()) { + command += is.getNbt().toString(); } command += " " + amount; if (command.length() < 256) { diff --git a/xplat/src/main/java/dev/emi/emi/screen/StackBatcher.java b/xplat/src/main/java/dev/emi/emi/screen/StackBatcher.java index 114b8c03..56e07749 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/StackBatcher.java +++ b/xplat/src/main/java/dev/emi/emi/screen/StackBatcher.java @@ -171,7 +171,7 @@ public void render(EmiIngredient stack, DrawContext draw, int x, int y, float de if (stack instanceof Batchable b && !b.isUnbatchable() && isEnabled() && (flags & EmiIngredient.RENDER_ICON) != 0) { if (!populated) { try { - b.renderForBatch(b.isSideLit() ? imm : unlitFacade, draw, x-this.x, y + this.y, z, delta); + b.renderForBatch(b.isSideLit() ? imm : unlitFacade, draw, x-this.x, -y-this.y, z, delta); if (sodiumSpriteHandle != null && !stack.isEmpty()) { ItemStack is = stack.getEmiStacks().get(0).getItemStack(); MinecraftClient client = MinecraftClient.getInstance(); @@ -218,7 +218,9 @@ public void draw() { RenderSystem.enableDepthTest(); DiffuseLighting.enableGuiDepthLighting(); Matrix4f mat = new Matrix4f(RenderSystem.getModelViewMatrix()); - mat.mul(new Matrix4f().translation(x, y, 0)); + mat.mul(new Matrix4f().scale(1, -1, 1)); + // Flipped Y creates an offset + mat.mul(new Matrix4f().translation(x, -y - 16, 0)); for (Map.Entry en : buffers.entrySet()) { en.getKey().startDrawing(); EmiPort.setShader(en.getValue(), mat); @@ -366,7 +368,7 @@ private Consumer(VertexConsumer delegate) { @Override public VertexConsumer normal(float x, float y, float z) { - delegate.normal(0, -1, 0); // this is the change + delegate.normal(0, 1, 0); // this is the change return this; } diff --git a/xplat/src/main/java/dev/emi/emi/screen/widget/EmiSearchWidget.java b/xplat/src/main/java/dev/emi/emi/screen/widget/EmiSearchWidget.java index c325d15b..2e06a29c 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/widget/EmiSearchWidget.java +++ b/xplat/src/main/java/dev/emi/emi/screen/widget/EmiSearchWidget.java @@ -4,7 +4,6 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.joml.Matrix4fStack; import org.lwjgl.glfw.GLFW; import com.google.common.collect.Lists; @@ -237,11 +236,11 @@ public void renderWidget(DrawContext raw, int mouseX, int mouseY, float delta) { } lastRender = System.currentTimeMillis(); long deg = accumulatedSpin * -180 / 500; - Matrix4fStack view = RenderSystem.getModelViewStack(); - view.pushMatrix(); + MatrixStack view = RenderSystem.getModelViewStack(); + view.push(); if (deg != 0) { view.translate(this.x + this.width / 2, this.y + this.height / 2, 0); - view.rotate(RotationAxis.NEGATIVE_Z.rotationDegrees(deg)); + view.multiply(RotationAxis.NEGATIVE_Z.rotationDegrees(deg)); view.translate(-(this.x + this.width / 2), -(this.y + this.height / 2), 0); RenderSystem.applyModelViewMatrix(); } @@ -264,7 +263,7 @@ public void renderWidget(DrawContext raw, int mouseX, int mouseY, float delta) { } } context.resetColor(); - view.popMatrix(); + view.pop(); RenderSystem.applyModelViewMatrix(); } } diff --git a/xplat/src/main/java/dev/emi/emi/screen/widget/config/ListWidget.java b/xplat/src/main/java/dev/emi/emi/screen/widget/config/ListWidget.java index 0ad84d05..e922ff4b 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/widget/config/ListWidget.java +++ b/xplat/src/main/java/dev/emi/emi/screen/widget/config/ListWidget.java @@ -164,7 +164,7 @@ public void render(DrawContext draw, int mouseX, int mouseY, float delta) { this.hoveredEntry = this.isMouseOver(mouseX, mouseY) ? this.getEntryAtPosition(mouseX, mouseY) : null; { // Render background - RenderSystem.setShaderTexture(0, Screen.MENU_BACKGROUND_TEXTURE); + RenderSystem.setShaderTexture(0, Screen.OPTIONS_BACKGROUND_TEXTURE); RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); bufferBuilder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR); bufferBuilder.vertex((double)this.left, (double)this.bottom, 0.0) @@ -193,7 +193,7 @@ public void render(DrawContext draw, int mouseX, int mouseY, float delta) { { // Render horizontal shadows RenderSystem.setShader(GameRenderer::getPositionTexColorProgram); - RenderSystem.setShaderTexture(0, Screen.MENU_BACKGROUND_TEXTURE); + RenderSystem.setShaderTexture(0, Screen.OPTIONS_BACKGROUND_TEXTURE); RenderSystem.enableDepthTest(); RenderSystem.depthFunc(519); bufferBuilder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR); diff --git a/xplat/src/main/java/dev/emi/emi/search/EmiSearch.java b/xplat/src/main/java/dev/emi/emi/search/EmiSearch.java index da7947d7..d720adcf 100644 --- a/xplat/src/main/java/dev/emi/emi/search/EmiSearch.java +++ b/xplat/src/main/java/dev/emi/emi/search/EmiSearch.java @@ -24,12 +24,9 @@ import dev.emi.emi.screen.EmiScreenManager; import net.minecraft.client.resource.language.I18n; import net.minecraft.client.search.SuffixArray; -import net.minecraft.component.DataComponentTypes; -import net.minecraft.component.type.ItemEnchantmentsComponent; import net.minecraft.enchantment.Enchantment; import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.item.Items; -import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.text.Text; import net.minecraft.util.Identifier; @@ -75,8 +72,8 @@ public static void bake() { names.add(searchStack, id.getPath().toLowerCase()); } if (stack.getItemStack().getItem() == Items.ENCHANTED_BOOK) { - for (RegistryEntry e : stack.getOrDefault(DataComponentTypes.ENCHANTMENTS, ItemEnchantmentsComponent.DEFAULT).getEnchantments()) { - Identifier eid = EmiPort.getEnchantmentRegistry().getId(e.value()); + for (Enchantment e : EnchantmentHelper.get(stack.getItemStack()).keySet()) { + Identifier eid = EmiPort.getEnchantmentRegistry().getId(e); if (eid != null && !eid.getNamespace().equals("minecraft")) { mods.add(searchStack, EmiUtil.getModName(eid.getNamespace()).toLowerCase()); } diff --git a/xplat/src/main/java/dev/emi/emi/stack/serializer/FluidEmiStackSerializer.java b/xplat/src/main/java/dev/emi/emi/stack/serializer/FluidEmiStackSerializer.java index 460b9593..30c241e8 100644 --- a/xplat/src/main/java/dev/emi/emi/stack/serializer/FluidEmiStackSerializer.java +++ b/xplat/src/main/java/dev/emi/emi/stack/serializer/FluidEmiStackSerializer.java @@ -4,9 +4,6 @@ import dev.emi.emi.api.stack.EmiStack; import dev.emi.emi.api.stack.FluidEmiStack; import dev.emi.emi.api.stack.serializer.EmiStackSerializer; -import net.minecraft.component.ComponentChanges; -import net.minecraft.component.ComponentMap; -import net.minecraft.component.ComponentMapImpl; import net.minecraft.nbt.NbtCompound; import net.minecraft.util.Identifier; @@ -18,7 +15,7 @@ public String getType() { } @Override - public EmiStack create(Identifier id, ComponentChanges componentChanges, long amount) { - return EmiStack.of(EmiPort.getFluidRegistry().get(id), componentChanges, amount); + public EmiStack create(Identifier id, NbtCompound nbt, long amount) { + return EmiStack.of(EmiPort.getFluidRegistry().get(id), nbt, amount); } } diff --git a/xplat/src/main/java/dev/emi/emi/stack/serializer/ItemEmiStackSerializer.java b/xplat/src/main/java/dev/emi/emi/stack/serializer/ItemEmiStackSerializer.java index 9d249011..83acea03 100644 --- a/xplat/src/main/java/dev/emi/emi/stack/serializer/ItemEmiStackSerializer.java +++ b/xplat/src/main/java/dev/emi/emi/stack/serializer/ItemEmiStackSerializer.java @@ -4,7 +4,6 @@ import dev.emi.emi.api.stack.EmiStack; import dev.emi.emi.api.stack.ItemEmiStack; import dev.emi.emi.api.stack.serializer.EmiStackSerializer; -import net.minecraft.component.ComponentChanges; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NbtCompound; import net.minecraft.util.Identifier; @@ -17,8 +16,9 @@ public String getType() { } @Override - public EmiStack create(Identifier id, ComponentChanges componentChanges, long amount) { - ItemStack stack = new ItemStack(EmiPort.getItemRegistry().getEntry(id).orElseThrow(), 1, componentChanges); + public EmiStack create(Identifier id, NbtCompound nbt, long amount) { + ItemStack stack = new ItemStack(EmiPort.getItemRegistry().get(id)); + stack.setNbt(nbt); return EmiStack.of(stack, amount); } } diff --git a/xplat/src/main/resources/emi.accesswidener b/xplat/src/main/resources/emi.accesswidener index 5e89f68e..e3eb7d0b 100644 --- a/xplat/src/main/resources/emi.accesswidener +++ b/xplat/src/main/resources/emi.accesswidener @@ -2,6 +2,10 @@ accessWidener v1 named accessible class net/minecraft/recipe/BrewingRecipeRegistry$Recipe +accessible field net/minecraft/recipe/BrewingRecipeRegistry POTION_RECIPES Ljava/util/List; +accessible field net/minecraft/recipe/BrewingRecipeRegistry ITEM_RECIPES Ljava/util/List; +accessible field net/minecraft/recipe/BrewingRecipeRegistry POTION_TYPES Ljava/util/List; + accessible method net/minecraft/client/gui/screen/Screen addSelectableChild (Lnet/minecraft/client/gui/Element;)Lnet/minecraft/client/gui/Element; accessible field net/minecraft/client/gui/widget/ClickableWidget x I diff --git a/xplat/src/main/resources/emi.mixins.json b/xplat/src/main/resources/emi.mixins.json index 804234c0..49a1733d 100644 --- a/xplat/src/main/resources/emi.mixins.json +++ b/xplat/src/main/resources/emi.mixins.json @@ -7,7 +7,6 @@ "client": [ "accessor.AxeItemAccessor", "accessor.BakedModelManagerAccessor", - "accessor.BrewingRecipeRegistryAccessor", "accessor.CraftingResultSlotAccessor", "accessor.DrawContextAccessor", "accessor.HandledScreenAccessor", @@ -36,4 +35,4 @@ "injectors": { "defaultRequire": 1 } -} +} \ No newline at end of file From d721aedcd5b800e96cda74f10622d73cc853205c Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Thu, 2 May 2024 05:48:15 -0500 Subject: [PATCH 33/67] Revert "Clip vanity's vestigial wings" This reverts commit 56950bae6e5460479519e2b74008d5483f0efbb9. --- .../emi/mixin/api/ComparisonBuilderMixin.java | 67 +++++++++ .../emi/emi/mixin/api/ComparisonMixin.java | 51 +++++++ .../dev/emi/emi/mixin/api/EmiApiMixin.java | 17 +++ .../emi/emi/mixin/api/EmiIngredientMixin.java | 45 ++++++ .../emi/emi/mixin/api/EmiRegistryMixin.java | 20 +++ .../emi/emi/mixin/api/EmiStackEntryMixin.java | 31 ++++ .../dev/emi/emi/mixin/api/EmiStackMixin.java | 55 +++++++ .../mixin/api/EmptyEmiStackEntryMixin.java | 28 ++++ .../emi/emi/mixin/api/EmptyEmiStackMixin.java | 23 +++ .../mixin/api/FluidEmiStackEntryMixin.java | 35 +++++ .../emi/emi/mixin/api/FluidEmiStackMixin.java | 48 +++++++ .../emi/mixin/api/ItemEmiStackEntryMixin.java | 34 +++++ .../emi/emi/mixin/api/ItemEmiStackMixin.java | 43 ++++++ .../emi/emi/mixin/api/SlotWidgetMixin.java | 23 +++ .../src/main/resources/emi-fabric.mixins.json | 14 ++ .../dev/emi/emi/api/EmiRecipeHandler.java | 136 ++++++++++++++++++ 16 files changed, 670 insertions(+) create mode 100644 fabric/src/main/java/dev/emi/emi/mixin/api/ComparisonBuilderMixin.java create mode 100644 fabric/src/main/java/dev/emi/emi/mixin/api/ComparisonMixin.java create mode 100644 fabric/src/main/java/dev/emi/emi/mixin/api/EmiApiMixin.java create mode 100644 fabric/src/main/java/dev/emi/emi/mixin/api/EmiIngredientMixin.java create mode 100644 fabric/src/main/java/dev/emi/emi/mixin/api/EmiRegistryMixin.java create mode 100644 fabric/src/main/java/dev/emi/emi/mixin/api/EmiStackEntryMixin.java create mode 100644 fabric/src/main/java/dev/emi/emi/mixin/api/EmiStackMixin.java create mode 100644 fabric/src/main/java/dev/emi/emi/mixin/api/EmptyEmiStackEntryMixin.java create mode 100644 fabric/src/main/java/dev/emi/emi/mixin/api/EmptyEmiStackMixin.java create mode 100644 fabric/src/main/java/dev/emi/emi/mixin/api/FluidEmiStackEntryMixin.java create mode 100644 fabric/src/main/java/dev/emi/emi/mixin/api/FluidEmiStackMixin.java create mode 100644 fabric/src/main/java/dev/emi/emi/mixin/api/ItemEmiStackEntryMixin.java create mode 100644 fabric/src/main/java/dev/emi/emi/mixin/api/ItemEmiStackMixin.java create mode 100644 fabric/src/main/java/dev/emi/emi/mixin/api/SlotWidgetMixin.java create mode 100644 xplat/src/main/java/dev/emi/emi/api/EmiRecipeHandler.java diff --git a/fabric/src/main/java/dev/emi/emi/mixin/api/ComparisonBuilderMixin.java b/fabric/src/main/java/dev/emi/emi/mixin/api/ComparisonBuilderMixin.java new file mode 100644 index 00000000..017a7c1a --- /dev/null +++ b/fabric/src/main/java/dev/emi/emi/mixin/api/ComparisonBuilderMixin.java @@ -0,0 +1,67 @@ +package dev.emi.emi.mixin.api; + +import org.spongepowered.asm.mixin.Mixin; + +import dev.emi.emi.api.stack.Comparison; +import dev.emi.emi.mixinsupport.MixinPlaceholder; +import dev.emi.emi.mixinsupport.annotation.InvokeTarget; +import dev.emi.emi.mixinsupport.annotation.StripConstructors; +import dev.emi.emi.mixinsupport.annotation.Transform; +import net.fabricmc.fabric.api.util.TriState; + +@StripConstructors +@Transform(visibility = "PUBLIC") +@Mixin(targets = "dev/emi/emi/api/stack/Comparison$Builder") +public abstract class ComparisonBuilderMixin { + private TriState amount = TriState.DEFAULT; + private TriState nbt = TriState.DEFAULT; + + @InvokeTarget(owner = "java/lang/Object", name = "") + abstract void superConstructor(); + + @Transform(name = "") + private void constructor() { + superConstructor(); + } + + @Transform(desc = "(Z)Ldev/emi/emi/api/stack/Comparison$Builder;") + public ComparisonBuilderMixin amount(boolean amount) { + this.amount = TriState.of(amount); + return this; + } + + @Transform(desc = "(Lnet/fabricmc/fabric/api/util/TriState;)Ldev/emi/emi/api/stack/Comparison$Builder;") + public ComparisonBuilderMixin amount(TriState amount) { + this.amount = amount; + return this; + } + + @Transform(desc = "(Z)Ldev/emi/emi/api/stack/Comparison$Builder;") + public ComparisonBuilderMixin nbt(boolean nbt) { + this.nbt = TriState.of(nbt); + return this; + } + + @Transform(desc = "(Lnet/fabricmc/fabric/api/util/TriState;)Ldev/emi/emi/api/stack/Comparison$Builder;") + public ComparisonBuilderMixin nbt(TriState nbt) { + this.nbt = nbt; + return this; + } + + @InvokeTarget(owner = "dev/emi/emi/api/stack/Comparison", name = "", + desc = "(Ldev/emi/emi/api/stack/Comparison$Predicate;)V", type = "NEW") + private static Comparison newComparison(Object newDup, Comparison.Predicate predicate) { throw new AbstractMethodError(); } + + public Comparison build() { + Comparison base; + if (nbt == TriState.TRUE) { + base = Comparison.compareNbt(); + } else { + base = Comparison.DEFAULT_COMPARISON; + } + if (amount != TriState.TRUE) { + return base; + } + return newComparison(MixinPlaceholder.NEW_DUP, (a, b) -> a.getAmount() == b.getAmount() && base.compare(a, b)); + } +} diff --git a/fabric/src/main/java/dev/emi/emi/mixin/api/ComparisonMixin.java b/fabric/src/main/java/dev/emi/emi/mixin/api/ComparisonMixin.java new file mode 100644 index 00000000..82a2d604 --- /dev/null +++ b/fabric/src/main/java/dev/emi/emi/mixin/api/ComparisonMixin.java @@ -0,0 +1,51 @@ +package dev.emi.emi.mixin.api; + +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 dev.emi.emi.api.stack.Comparison; +import dev.emi.emi.mixinsupport.MixinPlaceholder; +import dev.emi.emi.mixinsupport.annotation.InvokeTarget; +import dev.emi.emi.mixinsupport.annotation.Transform; +import net.fabricmc.fabric.api.util.TriState; + +@Mixin(Comparison.class) +public class ComparisonMixin { + public TriState amount; + public TriState nbt; + + @Inject(at = @At("RETURN"), method = "") + private void constructor(CallbackInfo info) { + amount = TriState.FALSE; + nbt = TriState.FALSE; + newBuilder(MixinPlaceholder.NEW_DUP); + } + + public TriState resolveAmount(Comparison other) { + return resolvePair(amount, ((ComparisonMixin) (Object) other).amount); + } + + public TriState resolveNbt(Comparison other) { + return resolvePair(nbt, ((ComparisonMixin) (Object) other).nbt); + } + + private TriState resolvePair(TriState a, TriState b) { + if (a == TriState.TRUE || b == TriState.TRUE) { + return TriState.TRUE; + } else if (a == TriState.FALSE || b == TriState.FALSE) { + return TriState.FALSE; + } + return TriState.DEFAULT; + } + + @InvokeTarget(owner = "dev/emi/emi/api/stack/Comparison$Builder", name = "", + desc = "()V", type = "NEW") + private static Object newBuilder(Object newDup) { throw new AbstractMethodError(); } + + @Transform(desc = "()Ldev/emi/emi/api/stack/Comparison$Builder;") + public Object copy() { + return newBuilder(MixinPlaceholder.NEW_DUP); + } +} diff --git a/fabric/src/main/java/dev/emi/emi/mixin/api/EmiApiMixin.java b/fabric/src/main/java/dev/emi/emi/mixin/api/EmiApiMixin.java new file mode 100644 index 00000000..0d22cb9d --- /dev/null +++ b/fabric/src/main/java/dev/emi/emi/mixin/api/EmiApiMixin.java @@ -0,0 +1,17 @@ +package dev.emi.emi.mixin.api; + +import org.spongepowered.asm.mixin.Mixin; + +import dev.emi.emi.api.EmiApi; +import dev.emi.emi.api.EmiFillAction; +import dev.emi.emi.api.recipe.EmiRecipe; +import dev.emi.emi.mixinsupport.annotation.Transform; + +@Mixin(EmiApi.class) +public class EmiApiMixin { + + @Transform(visibility = "PUBLIC") + private static boolean performFill(EmiRecipe recipe, EmiFillAction action, int amount) { + return false; + } +} diff --git a/fabric/src/main/java/dev/emi/emi/mixin/api/EmiIngredientMixin.java b/fabric/src/main/java/dev/emi/emi/mixin/api/EmiIngredientMixin.java new file mode 100644 index 00000000..7c60edca --- /dev/null +++ b/fabric/src/main/java/dev/emi/emi/mixin/api/EmiIngredientMixin.java @@ -0,0 +1,45 @@ +package dev.emi.emi.mixin.api; + +import java.text.DecimalFormat; + +import org.spongepowered.asm.mixin.Mixin; + +import dev.emi.emi.EmiRenderHelper; +import dev.emi.emi.api.stack.EmiIngredient; +import dev.emi.emi.mixinsupport.annotation.AdditionalField; +import net.minecraft.text.Text; + +/** + * Making EmiIngredients mutable introduced several necessary methods for mutation + * Chance was also added + * Can be removed in 1.20 + */ +@Mixin(EmiIngredient.class) +public interface EmiIngredientMixin { + + @AdditionalField(value = "TEXT_FORMAT", owner = "dev/emi/emi/EmiRenderHelper", name = "TEXT_FORMAT") + default DecimalFormat copyTextFormat() { throw new AbstractMethodError(); } + + @AdditionalField(value = "EMPTY_TEXT", owner = "dev/emi/emi/EmiRenderHelper", name = "EMPTY_TEXT") + default Text copyEmptyText() { throw new AbstractMethodError(); } + + default Text getAmountText(double amount) { + return EmiRenderHelper.getAmountText((EmiIngredient) (Object) this, amount); + } + + default EmiIngredient copy() { + return (EmiIngredient) this; + } + + default EmiIngredient setAmount(long amount) { + return (EmiIngredient) this; + } + + default float getChance() { + return 1f; + } + + default EmiIngredient setChance(float chance) { + return (EmiIngredient) this; + } +} diff --git a/fabric/src/main/java/dev/emi/emi/mixin/api/EmiRegistryMixin.java b/fabric/src/main/java/dev/emi/emi/mixin/api/EmiRegistryMixin.java new file mode 100644 index 00000000..fd5b8f11 --- /dev/null +++ b/fabric/src/main/java/dev/emi/emi/mixin/api/EmiRegistryMixin.java @@ -0,0 +1,20 @@ +package dev.emi.emi.mixin.api; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import dev.emi.emi.api.EmiRegistry; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.screen.ScreenHandlerType; + +@Mixin(EmiRegistry.class) +public interface EmiRegistryMixin { + + @Shadow + void addRecipeHandler(ScreenHandlerType type, dev.emi.emi.api.recipe.handler.EmiRecipeHandler handler); + + @SuppressWarnings("deprecation") + default void addRecipeHandler(ScreenHandlerType type, dev.emi.emi.api.EmiRecipeHandler handler) { + addRecipeHandler(type, (dev.emi.emi.api.recipe.handler.EmiRecipeHandler) handler); + } +} diff --git a/fabric/src/main/java/dev/emi/emi/mixin/api/EmiStackEntryMixin.java b/fabric/src/main/java/dev/emi/emi/mixin/api/EmiStackEntryMixin.java new file mode 100644 index 00000000..c73f01c1 --- /dev/null +++ b/fabric/src/main/java/dev/emi/emi/mixin/api/EmiStackEntryMixin.java @@ -0,0 +1,31 @@ +package dev.emi.emi.mixin.api; + +import org.objectweb.asm.Opcodes; +import org.spongepowered.asm.mixin.Mixin; + +import dev.emi.emi.mixinsupport.annotation.InvokeTarget; +import dev.emi.emi.mixinsupport.annotation.StripConstructors; +import dev.emi.emi.mixinsupport.annotation.Transform; + +@StripConstructors +@Transform(visibility = "PUBLIC", flags = Opcodes.ACC_ABSTRACT) +@Mixin(targets = "dev/emi/emi/api/stack/EmiStack$Entry") +public abstract class EmiStackEntryMixin { + @Transform(flags = Opcodes.ACC_FINAL) + private T value; + + @InvokeTarget(owner = "java/lang/Object", name = "") + public abstract void superConstructor(); + + @Transform(name = "") + public void constructor(T value) { + superConstructor(); + this.value = value; + } + + public T getValue() { + return value; + } + + public abstract Class getType(); +} diff --git a/fabric/src/main/java/dev/emi/emi/mixin/api/EmiStackMixin.java b/fabric/src/main/java/dev/emi/emi/mixin/api/EmiStackMixin.java new file mode 100644 index 00000000..ae840b23 --- /dev/null +++ b/fabric/src/main/java/dev/emi/emi/mixin/api/EmiStackMixin.java @@ -0,0 +1,55 @@ +package dev.emi.emi.mixin.api; + +import org.spongepowered.asm.mixin.Mixin; + +import dev.emi.emi.api.stack.EmiStack; +import dev.emi.emi.api.stack.FluidEmiStack; +import dev.emi.emi.mixinsupport.annotation.InvokeTarget; +import dev.emi.emi.mixinsupport.annotation.Transform; +import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant; +import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant; + +@Mixin(EmiStack.class) +public class EmiStackMixin { + + @Transform(visibility = "PUBLIC") + private static EmiStack of(ItemVariant item) { + return EmiStack.of(item.toStack(), 1); + } + + @Transform(visibility = "PUBLIC") + private static EmiStack of(ItemVariant item, long amount) { + return EmiStack.of(item.toStack(), amount); + } + + @Transform(visibility = "PUBLIC") + private static EmiStack of(FluidVariant fluid) { + return new FluidEmiStack(fluid.getFluid(), fluid.getNbt()); + } + + @Transform(visibility = "PUBLIC") + private static EmiStack of(FluidVariant fluid, long amount) { + return new FluidEmiStack(fluid.getFluid(), fluid.getNbt(), amount); + } + + @InvokeTarget(owner = "dev/emi/emi/api/stack/EmiStack", name = "getEntry", + desc = "()Ldev/emi/emi/api/stack/EmiStack$Entry;", type = "VIRTUAL") + private static Object getEmptyEntry(EmiStack stack) { throw new AbstractMethodError(); } + + @Transform(desc = "()Ldev/emi/emi/api/stack/EmiStack$Entry;") + public Object getEntry() { + return getEmptyEntry(EmiStack.EMPTY); + } + + @InvokeTarget(owner = "dev/emi/emi/api/stack/EmiStack$Entry", name = "getType", + desc = "()Ljava/lang/Class;", type = "VIRTUAL") + private static Class getType(Object object) { throw new AbstractMethodError(); } + + @Transform(desc = "(Ljava/lang/Class;)Ldev/emi/emi/api/stack/EmiStack$Entry;") + public Object getEntryOfType(Class clazz) { + if (getType(getEntry()) == clazz) { + return getEntry(); + } + return null; + } +} diff --git a/fabric/src/main/java/dev/emi/emi/mixin/api/EmptyEmiStackEntryMixin.java b/fabric/src/main/java/dev/emi/emi/mixin/api/EmptyEmiStackEntryMixin.java new file mode 100644 index 00000000..828571f0 --- /dev/null +++ b/fabric/src/main/java/dev/emi/emi/mixin/api/EmptyEmiStackEntryMixin.java @@ -0,0 +1,28 @@ +package dev.emi.emi.mixin.api; + +import org.spongepowered.asm.mixin.Mixin; + +import dev.emi.emi.mixinsupport.annotation.Extends; +import dev.emi.emi.mixinsupport.annotation.InvokeTarget; +import dev.emi.emi.mixinsupport.annotation.StripConstructors; +import dev.emi.emi.mixinsupport.annotation.Transform; +import net.minecraft.item.ItemStack; + +@StripConstructors +@Transform(visibility = "PUBLIC") +@Extends("dev/emi/emi/api/stack/EmiStack$Entry") +@Mixin(targets = "dev/emi/emi/api/stack/EmptyEmiStack$EmptyEntry") +public abstract class EmptyEmiStackEntryMixin { + + @InvokeTarget(name = "", owner = "super") + abstract void constructor(Object object); + + @Transform(name = "") + public void constructor() { + constructor(ItemStack.EMPTY); + } + + public Class getType() { + return ItemStack.class; + } +} diff --git a/fabric/src/main/java/dev/emi/emi/mixin/api/EmptyEmiStackMixin.java b/fabric/src/main/java/dev/emi/emi/mixin/api/EmptyEmiStackMixin.java new file mode 100644 index 00000000..6a48a23c --- /dev/null +++ b/fabric/src/main/java/dev/emi/emi/mixin/api/EmptyEmiStackMixin.java @@ -0,0 +1,23 @@ +package dev.emi.emi.mixin.api; + +import org.spongepowered.asm.mixin.Mixin; + +import dev.emi.emi.api.stack.EmptyEmiStack; +import dev.emi.emi.mixinsupport.MixinPlaceholder; +import dev.emi.emi.mixinsupport.annotation.InvokeTarget; +import dev.emi.emi.mixinsupport.annotation.Transform; + +@Mixin(EmptyEmiStack.class) +public class EmptyEmiStackMixin { + @Transform(visibility = "PUBLIC", desc = "Ldev/emi/emi/api/stack/EmptyEmiStack$EmptyEntry;") + private static final Object ENTRY = newEntry(MixinPlaceholder.NEW_DUP); + + @InvokeTarget(owner = "dev/emi/emi/api/stack/EmptyEmiStack$EmptyEntry", name = "", + desc = "()V", type = "NEW") + private static Object newEntry(Object newDup) { throw new AbstractMethodError(); } + + @Transform(desc = "()Ldev/emi/emi/api/stack/EmiStack$Entry;") + public Object getEntry() { + return ENTRY; + } +} diff --git a/fabric/src/main/java/dev/emi/emi/mixin/api/FluidEmiStackEntryMixin.java b/fabric/src/main/java/dev/emi/emi/mixin/api/FluidEmiStackEntryMixin.java new file mode 100644 index 00000000..48243323 --- /dev/null +++ b/fabric/src/main/java/dev/emi/emi/mixin/api/FluidEmiStackEntryMixin.java @@ -0,0 +1,35 @@ +package dev.emi.emi.mixin.api; + +import org.spongepowered.asm.mixin.Mixin; + +import dev.emi.emi.mixinsupport.annotation.Extends; +import dev.emi.emi.mixinsupport.annotation.InvokeTarget; +import dev.emi.emi.mixinsupport.annotation.StripConstructors; +import dev.emi.emi.mixinsupport.annotation.Transform; +import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant; +import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant; + +@StripConstructors +@Transform(visibility = "PUBLIC") +@Extends("dev/emi/emi/api/stack/EmiStack$Entry") +@Mixin(targets = "dev/emi/emi/api/stack/FluidEmiStack$FluidEntry") +public abstract class FluidEmiStackEntryMixin { + private FluidVariant variant; + + @InvokeTarget(name = "", owner = "super") + abstract void constructor(Object object); + + @Transform(name = "") + public void constructor(FluidVariant variant) { + constructor((Object) variant); + this.variant = variant; + } + + public Class getType() { + return ItemVariant.class; + } + + public boolean equals(Object obj) { + return obj instanceof FluidEmiStackEntryMixin e && variant.getFluid().equals(e.variant.getFluid()); + } +} diff --git a/fabric/src/main/java/dev/emi/emi/mixin/api/FluidEmiStackMixin.java b/fabric/src/main/java/dev/emi/emi/mixin/api/FluidEmiStackMixin.java new file mode 100644 index 00000000..30377725 --- /dev/null +++ b/fabric/src/main/java/dev/emi/emi/mixin/api/FluidEmiStackMixin.java @@ -0,0 +1,48 @@ +package dev.emi.emi.mixin.api; + +import org.jetbrains.annotations.Nullable; +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 dev.emi.emi.api.stack.FluidEmiStack; +import dev.emi.emi.mixinsupport.MixinPlaceholder; +import dev.emi.emi.mixinsupport.annotation.InvokeTarget; +import dev.emi.emi.mixinsupport.annotation.Transform; +import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant; +import net.minecraft.fluid.Fluid; +import net.minecraft.nbt.NbtCompound; + +@Mixin(FluidEmiStack.class) +public abstract class FluidEmiStackMixin { + @Transform(desc = "Ldev/emi/emi/api/stack/EmiStack$Entry;") + private Object entry; + + @InvokeTarget(owner = "dev/emi/emi/api/stack/FluidEmiStack$FluidEntry", name = "", + desc = "(Lnet/fabricmc/fabric/api/transfer/v1/fluid/FluidVariant;)V", type = "NEW") + private static Object newEntry(Object newDup, FluidVariant variant) { throw new AbstractMethodError(); } + + @Inject(at = @At("RETURN"), method = "(Lnet/minecraft/fluid/Fluid;Lnet/minecraft/nbt/NbtCompound;J)V") + private void init(Fluid fluid, @Nullable NbtCompound nbt, long amount, CallbackInfo info) { + entry = newEntry(MixinPlaceholder.NEW_DUP, FluidVariant.of(fluid, nbt)); + } + + @InvokeTarget(name = "", owner = "this") + abstract void constructor(Fluid fluid, NbtCompound nbt, long amount); + + @Transform(name = "") + public void constructor(FluidVariant fluid) { + constructor(fluid.getFluid(), fluid.getNbt(), 0); + } + + @Transform(name = "") + public void constructor(FluidVariant fluid, long amount) { + constructor(fluid.getFluid(), fluid.getNbt(), amount); + } + + @Transform(desc = "()Ldev/emi/emi/api/stack/EmiStack$Entry;") + public Object getEntry() { + return entry; + } +} diff --git a/fabric/src/main/java/dev/emi/emi/mixin/api/ItemEmiStackEntryMixin.java b/fabric/src/main/java/dev/emi/emi/mixin/api/ItemEmiStackEntryMixin.java new file mode 100644 index 00000000..c3a92e86 --- /dev/null +++ b/fabric/src/main/java/dev/emi/emi/mixin/api/ItemEmiStackEntryMixin.java @@ -0,0 +1,34 @@ +package dev.emi.emi.mixin.api; + +import org.spongepowered.asm.mixin.Mixin; + +import dev.emi.emi.mixinsupport.annotation.Extends; +import dev.emi.emi.mixinsupport.annotation.InvokeTarget; +import dev.emi.emi.mixinsupport.annotation.StripConstructors; +import dev.emi.emi.mixinsupport.annotation.Transform; +import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant; + +@StripConstructors +@Transform(visibility = "PUBLIC") +@Extends("dev/emi/emi/api/stack/EmiStack$Entry") +@Mixin(targets = "dev/emi/emi/api/stack/ItemEmiStack$ItemEntry") +public abstract class ItemEmiStackEntryMixin { + private ItemVariant variant; + + @InvokeTarget(name = "", owner = "super") + abstract void constructor(Object object); + + @Transform(name = "") + public void constructor(ItemVariant variant) { + constructor((Object) variant); + this.variant = variant; + } + + public Class getType() { + return ItemVariant.class; + } + + public boolean equals(Object obj) { + return obj instanceof ItemEmiStackEntryMixin e && variant.getItem().equals(e.variant.getItem()); + } +} diff --git a/fabric/src/main/java/dev/emi/emi/mixin/api/ItemEmiStackMixin.java b/fabric/src/main/java/dev/emi/emi/mixin/api/ItemEmiStackMixin.java new file mode 100644 index 00000000..33eb2ae0 --- /dev/null +++ b/fabric/src/main/java/dev/emi/emi/mixin/api/ItemEmiStackMixin.java @@ -0,0 +1,43 @@ +package dev.emi.emi.mixin.api; + +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 dev.emi.emi.api.stack.ItemEmiStack; +import dev.emi.emi.mixinsupport.MixinPlaceholder; +import dev.emi.emi.mixinsupport.annotation.InvokeTarget; +import dev.emi.emi.mixinsupport.annotation.Transform; +import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant; +import net.minecraft.item.ItemStack; + +@Mixin(ItemEmiStack.class) +public abstract class ItemEmiStackMixin { + @Transform(desc = "Ldev/emi/emi/api/stack/EmiStack$Entry;") + private Object entry; + public ItemVariant item; + + @InvokeTarget(owner = "dev/emi/emi/api/stack/ItemEmiStack$ItemEntry", name = "", + desc = "(Lnet/fabricmc/fabric/api/transfer/v1/item/ItemVariant;)V", type = "NEW") + private static Object newEntry(Object newDup, ItemVariant variant) { throw new AbstractMethodError(); } + + @Inject(at = @At("RETURN"), method = "(Lnet/minecraft/item/ItemStack;J)V") + public void constructor(ItemStack stack, long amount, CallbackInfo info) { + this.item = ItemVariant.of(stack); + this.entry = newEntry(MixinPlaceholder.NEW_DUP, item); + } + + @InvokeTarget(name = "", owner = "this") + abstract void constructor(ItemStack stack, long amount); + + @Transform(name = "") + public void constructor(ItemVariant item, long amount) { + constructor(item.toStack(), amount); + } + + @Transform(desc = "()Ldev/emi/emi/api/stack/EmiStack$Entry;") + public Object getEntry() { + return entry; + } +} diff --git a/fabric/src/main/java/dev/emi/emi/mixin/api/SlotWidgetMixin.java b/fabric/src/main/java/dev/emi/emi/mixin/api/SlotWidgetMixin.java new file mode 100644 index 00000000..c2e4a286 --- /dev/null +++ b/fabric/src/main/java/dev/emi/emi/mixin/api/SlotWidgetMixin.java @@ -0,0 +1,23 @@ +package dev.emi.emi.mixin.api; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import dev.emi.emi.api.widget.SlotWidget; +import net.minecraft.util.Identifier; + +@Mixin(SlotWidget.class) +public abstract class SlotWidgetMixin { + @Shadow(remap = false) + public abstract SlotWidget large(boolean large); + @Shadow + public abstract SlotWidget customBackground(Identifier id, int u, int v, int width, int height); + + public SlotWidget output(boolean output) { + return large(output); + } + + public void custom(Identifier id, int u, int v, int width, int height) { + customBackground(id, u, v, width, height); + } +} diff --git a/fabric/src/main/resources/emi-fabric.mixins.json b/fabric/src/main/resources/emi-fabric.mixins.json index 0bad3d5a..a1b13ec8 100644 --- a/fabric/src/main/resources/emi-fabric.mixins.json +++ b/fabric/src/main/resources/emi-fabric.mixins.json @@ -7,6 +7,20 @@ "mixins": [], "client": [ "accessor.BrewingRecipeRegistryRecipeAccessor", + "api.ComparisonBuilderMixin", + "api.ComparisonMixin", + "api.EmiApiMixin", + "api.EmiIngredientMixin", + "api.EmiRegistryMixin", + "api.EmiStackEntryMixin", + "api.EmiStackMixin", + "api.EmptyEmiStackEntryMixin", + "api.EmptyEmiStackMixin", + "api.FluidEmiStackEntryMixin", + "api.FluidEmiStackMixin", + "api.ItemEmiStackEntryMixin", + "api.ItemEmiStackMixin", + "api.SlotWidgetMixin", "conversion.FluidMixin", "conversion.ItemConvertibleMixin", "conversion.ItemStackMixin", diff --git a/xplat/src/main/java/dev/emi/emi/api/EmiRecipeHandler.java b/xplat/src/main/java/dev/emi/emi/api/EmiRecipeHandler.java new file mode 100644 index 00000000..2dfc9e00 --- /dev/null +++ b/xplat/src/main/java/dev/emi/emi/api/EmiRecipeHandler.java @@ -0,0 +1,136 @@ +package dev.emi.emi.api; + +import java.util.List; + +import org.jetbrains.annotations.Nullable; + +import dev.emi.emi.EmiPort; +import dev.emi.emi.api.recipe.EmiPlayerInventory; +import dev.emi.emi.api.recipe.EmiRecipe; +import dev.emi.emi.api.recipe.handler.EmiCraftContext; +import dev.emi.emi.api.recipe.handler.StandardRecipeHandler; +import dev.emi.emi.platform.EmiClient; +import dev.emi.emi.registry.EmiRecipeFiller; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.ingame.HandledScreen; +import net.minecraft.item.ItemStack; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.screen.slot.Slot; +import net.minecraft.text.Text; + +/** + * @deprecated Migrate to {@link StandardRecipeHandler} + */ +@Deprecated +public interface EmiRecipeHandler extends StandardRecipeHandler { + public static final Text NOT_ENOUGH_INGREDIENTS = EmiPort.translatable("emi.not_enough_ingredients"); + + /** + * @return The slots for the recipe handler to source ingredients from. + * Typically this should include the player's inventory, and crafting slots. + */ + List getInputSources(T handler); + + default List getInputSources(HandledScreen screen) { + return getInputSources(screen.getScreenHandler()); + } + + /** + * @return The slots where inputs should be placed to perform crafting. + */ + List getCraftingSlots(T handler); + + default List getCraftingSlots(HandledScreen screen) { + return getCraftingSlots(screen.getScreenHandler()); + } + + /** + * @return The slots where inputs should be placed to perform crafting for a particular context. + */ + default List getCraftingSlots(EmiRecipe recipe, HandledScreen screen) { + return getCraftingSlots(screen.getScreenHandler()); + } + + @SuppressWarnings("unchecked") + default List getCraftingSlots(EmiRecipe recipe, T handler) { + HandledScreen hs = EmiApi.getHandledScreen(); + if (hs != null && hs.getScreenHandler() == handler) { + return getCraftingSlots(recipe, (HandledScreen) hs); + } + return List.of(); + } + + /** + * @return The output slot for recipe handlers that support instant interaction, like crafting tables. + * For handlers that have processing time, or where this concept is otherwise inapplicable, null. + */ + default @Nullable Slot getOutputSlot(T handler) { + return null; + } + + /** + * @return Whether this handler is applicable for the provided recipe. + */ + boolean supportsRecipe(EmiRecipe recipe); + + /** + * @return Whether the provided recipe is only conscious of the handler when the handler is applicable. + * Effectively, whether to not display the plus fill button outside of applicable screens. + */ + default boolean onlyDisplayWhenApplicable(EmiRecipe recipe) { + return false; + } + + @Override + default boolean alwaysDisplaySupport(EmiRecipe recipe) { + return !onlyDisplayWhenApplicable(recipe); + } + + @Override + default boolean canCraft(EmiRecipe recipe, EmiCraftContext context) { + return canCraft(recipe, context.getInventory(), context.getScreen()); + } + + default boolean canCraft(EmiRecipe recipe, EmiPlayerInventory inventory, HandledScreen screen) { + return inventory.canCraft(recipe); + } + + default Text getInvalidReason(EmiRecipe recipe, EmiPlayerInventory inventory, HandledScreen screen) { + return NOT_ENOUGH_INGREDIENTS; + } + + default boolean performFill(EmiRecipe recipe, HandledScreen screen, EmiFillAction action, int amount) { + List stacks = EmiRecipeFiller.getStacks(this, recipe, screen, amount); + if (stacks != null) { + stacks = mutateFill(recipe, screen, stacks); + if (stacks != null) { + MinecraftClient.getInstance().setScreen(screen); + if (!EmiClient.onServer) { + return EmiRecipeFiller.clientFill(this, recipe, screen, stacks, switch (action) { + case FILL -> EmiCraftContext.Destination.NONE; + case QUICK_MOVE -> EmiCraftContext.Destination.INVENTORY; + case CURSOR -> EmiCraftContext.Destination.CURSOR; + }); + } else { + EmiClient.sendFillRecipe(this, screen, screen.getScreenHandler().syncId, action.id, stacks, recipe); + } + return true; + } + } + return false; + } + + @Override + default boolean craft(EmiRecipe recipe, EmiCraftContext context) { + return performFill(recipe, context.getScreen(), switch (context.getDestination()) { + case NONE -> EmiFillAction.FILL; + case INVENTORY -> EmiFillAction.QUICK_MOVE; + case CURSOR -> EmiFillAction.CURSOR; + }, context.getAmount()); + } + + @Deprecated + default List mutateFill(EmiRecipe recipe, HandledScreen screen, List stacks) { + return stacks; + } +} From fdc7e511dee58f842031fc327c884741337240bf Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Sun, 16 Jun 2024 21:18:29 -0500 Subject: [PATCH 34/67] Revert "1.21" This reverts commit 8d78ad0eb67b8bb9129f447204f93bde50031eed. --- .../emi/platform/fabric/EmiAgnosFabric.java | 11 +- .../emi/platform/fabric/EmiClientFabric.java | 4 +- .../java/dev/emi/emi/screen/FakeScreen.java | 2 +- gradle.properties | 11 +- neoforge/build.gradle | 3 +- .../platform/neoforge/EmiAgnosNeoForge.java | 6 - .../platform/neoforge/EmiClientNeoForge.java | 7 +- xplat/src/main/java/dev/emi/emi/EmiPort.java | 9 +- .../java/dev/emi/emi/EmiRenderHelper.java | 13 +- .../main/java/dev/emi/emi/VanillaPlugin.java | 6 +- .../java/dev/emi/emi/api/stack/EmiStack.java | 11 +- .../dev/emi/emi/api/stack/ItemEmiStack.java | 7 +- .../emi/emi/api/stack/TagEmiIngredient.java | 4 +- .../emi/handler/InventoryRecipeHandler.java | 4 +- .../handler/StonecuttingRecipeHandler.java | 3 +- .../main/java/dev/emi/emi/jemi/JemiStack.java | 4 +- .../emi/jemi/impl/JemiIngredientAcceptor.java | 4 +- .../emi/mixin/CraftingResultSlotMixin.java | 2 +- .../dev/emi/emi/mixin/ItemStackMixin.java | 4 +- .../accessor/BakedModelManagerAccessor.java | 4 +- .../java/dev/emi/emi/platform/EmiAgnos.java | 8 -- .../dev/emi/emi/recipe/EmiShapedRecipe.java | 10 +- .../recipe/special/EmiAnvilEnchantRecipe.java | 4 +- .../EmiGrindstoneDisenchantingBookRecipe.java | 2 +- .../EmiGrindstoneDisenchantingRecipe.java | 9 +- .../recipe/special/EmiSmithingTrimRecipe.java | 6 +- .../emi/emi/registry/EmiStackProviders.java | 4 +- .../java/dev/emi/emi/registry/EmiTags.java | 7 +- .../dev/emi/emi/runtime/EmiDrawContext.java | 4 +- .../java/dev/emi/emi/runtime/EmiSidebars.java | 3 +- .../java/dev/emi/emi/screen/StackBatcher.java | 81 ++++++----- .../emi/screen/widget/config/ListWidget.java | 128 ++++++++++-------- .../main/resources/assets/emi/lang/en_us.json | 1 - 33 files changed, 192 insertions(+), 194 deletions(-) diff --git a/fabric/src/main/java/dev/emi/emi/platform/fabric/EmiAgnosFabric.java b/fabric/src/main/java/dev/emi/emi/platform/fabric/EmiAgnosFabric.java index 009bbe67..6ff9ce76 100644 --- a/fabric/src/main/java/dev/emi/emi/platform/fabric/EmiAgnosFabric.java +++ b/fabric/src/main/java/dev/emi/emi/platform/fabric/EmiAgnosFabric.java @@ -6,8 +6,6 @@ import java.util.Optional; import java.util.function.Consumer; -import org.apache.commons.lang3.text.WordUtils; - import dev.emi.emi.EmiPort; import dev.emi.emi.EmiRenderHelper; import dev.emi.emi.EmiUtil; @@ -33,14 +31,15 @@ import net.fabricmc.loader.api.ModContainer; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.tooltip.TooltipComponent; -import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.texture.Sprite; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.component.ComponentChanges; +import net.minecraft.component.ComponentMap; import net.minecraft.fluid.Fluid; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.PotionItem; +import net.minecraft.nbt.NbtCompound; import net.minecraft.potion.Potion; import net.minecraft.potion.Potions; import net.minecraft.recipe.BrewingRecipeRegistry; @@ -48,6 +47,7 @@ import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.text.Text; import net.minecraft.util.Identifier; +import org.apache.commons.lang3.text.WordUtils; public class EmiAgnosFabric extends EmiAgnos { static { @@ -220,9 +220,4 @@ protected Map getFuelMapAgnos() { } return fuelMap; } - - @Override - protected BakedModel getBakedTagModelAgnos(Identifier id) { - return MinecraftClient.getInstance().getBakedModelManager().getModel(id); - } } diff --git a/fabric/src/main/java/dev/emi/emi/platform/fabric/EmiClientFabric.java b/fabric/src/main/java/dev/emi/emi/platform/fabric/EmiClientFabric.java index 082a4658..261cf799 100644 --- a/fabric/src/main/java/dev/emi/emi/platform/fabric/EmiClientFabric.java +++ b/fabric/src/main/java/dev/emi/emi/platform/fabric/EmiClientFabric.java @@ -17,8 +17,6 @@ import dev.emi.emi.registry.EmiTags; import io.netty.buffer.Unpooled; import net.fabricmc.api.ClientModInitializer; -import net.fabricmc.fabric.api.client.model.loading.v1.ModelLoadingPlugin; -import net.fabricmc.fabric.api.client.model.loading.v1.ModelModifier; import net.fabricmc.fabric.api.client.model.loading.v1.PreparableModelLoadingPlugin; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry; @@ -63,7 +61,7 @@ public Identifier getFabricId() { PreparableModelLoadingPlugin.>register((manager, executor) -> { return CompletableFuture.supplyAsync(() -> { List ids = Lists.newArrayList(); - EmiTags.registerTagModels(manager, id -> ids.add(id.id()), ""); + EmiTags.registerTagModels(manager, id -> ids.add(id)); return ids; }, executor); }, (ids, context) -> { diff --git a/fabric/src/main/java/dev/emi/emi/screen/FakeScreen.java b/fabric/src/main/java/dev/emi/emi/screen/FakeScreen.java index 72947fd8..6718cbe1 100644 --- a/fabric/src/main/java/dev/emi/emi/screen/FakeScreen.java +++ b/fabric/src/main/java/dev/emi/emi/screen/FakeScreen.java @@ -8,8 +8,8 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.tooltip.TooltipComponent; +import net.minecraft.client.item.TooltipData; import net.minecraft.item.ItemStack; -import net.minecraft.item.tooltip.TooltipData; public class FakeScreen extends Screen { public static final FakeScreen INSTANCE = new FakeScreen(); diff --git a/gradle.properties b/gradle.properties index 78864f77..a5ca02f3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ org.gradle.jvmargs=-Xmx2048M -minecraft_version=1.21 +minecraft_version=1.20.6 enabled_platforms=fabric,neoforge archives_base_name=emi @@ -9,14 +9,13 @@ maven_group=dev.emi architectury_version=4.9.83 -yarn_mappings=1.21+build.2 +yarn_mappings=1.20.6+build.1 -fabric_loader_version=0.15.11 -fabric_api_version=0.100.1+1.21 +fabric_loader_version=0.15.10 +fabric_api_version=0.97.8+1.20.6 forge_version=1.20.4-49.0.9 -neoforge_version=21.0.10-beta -neoforge_yarn_patch=1.21+build.4 +neoforge_version=20.6.75-beta jei_version=jei-1.20.4-fabric:17.3.0.49 diff --git a/neoforge/build.gradle b/neoforge/build.gradle index a5e65e65..f4bc92d3 100644 --- a/neoforge/build.gradle +++ b/neoforge/build.gradle @@ -62,7 +62,8 @@ dependencies { minecraft "com.mojang:minecraft:${rootProject.minecraft_version}" mappings loom.layered { it.mappings("net.fabricmc:yarn:${project.yarn_mappings}:v2") - it.mappings("dev.architectury:yarn-mappings-patch-neoforge:${project.neoforge_yarn_patch}") + // Needed to fix "Unfixable conflicts" in 1.20.5 + it.mappings(project.projectDir.toPath().resolve("mappings/fix.tiny").toFile()) } neoForge "net.neoforged:neoforge:${rootProject.neoforge_version}" diff --git a/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiAgnosNeoForge.java b/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiAgnosNeoForge.java index f90b6a0b..420dedab 100644 --- a/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiAgnosNeoForge.java +++ b/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiAgnosNeoForge.java @@ -40,7 +40,6 @@ import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.render.model.BasicBakedModel; import net.minecraft.client.texture.Sprite; -import net.minecraft.client.util.ModelIdentifier; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.fluid.Fluid; import net.minecraft.item.Item; @@ -289,9 +288,4 @@ protected Map getFuelMapAgnos() { } return fuelMap; } - - @Override - protected BakedModel getBakedTagModelAgnos(Identifier id) { - return MinecraftClient.getInstance().getBakedModelManager().getModel(new ModelIdentifier(id, ModelIdentifier.STANDALONE_VARIANT)); - } } diff --git a/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiClientNeoForge.java b/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiClientNeoForge.java index ae8d9344..b9786196 100644 --- a/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiClientNeoForge.java +++ b/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiClientNeoForge.java @@ -16,7 +16,6 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.ingame.HandledScreen; -import net.minecraft.client.util.ModelIdentifier; import net.neoforged.api.distmarker.Dist; import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.fml.ModList; @@ -52,7 +51,7 @@ public static void clientInit(FMLClientSetupEvent event) { @SubscribeEvent public static void registerAdditionalModels(ModelEvent.RegisterAdditional event) { MinecraftClient client = MinecraftClient.getInstance(); - EmiTags.registerTagModels(client.getResourceManager(), event::register, ModelIdentifier.STANDALONE_VARIANT); + EmiTags.registerTagModels(client.getResourceManager(), event::register); } @SubscribeEvent @@ -77,7 +76,7 @@ public static void renderScreenForeground(ContainerScreenEvent.Render.Foreground context.push(); context.matrices().translate(-screen.getGuiLeft(), -screen.getGuiTop(), 0.0); EmiPort.setPositionTexShader(); - EmiScreenManager.render(context, event.getMouseX(), event.getMouseY(), client.getRenderTickCounter().getTickDelta(false)); + EmiScreenManager.render(context, event.getMouseX(), event.getMouseY(), client.getTickDelta()); context.pop(); } } @@ -93,7 +92,7 @@ public static void postRenderScreen(ScreenEvent.Render.Post event) { MinecraftClient client = MinecraftClient.getInstance(); context.push(); EmiPort.setPositionTexShader(); - EmiScreenManager.drawForeground(context, event.getMouseX(), event.getMouseY(), client.getRenderTickCounter().getTickDelta(false)); + EmiScreenManager.drawForeground(context, event.getMouseX(), event.getMouseY(), client.getTickDelta()); context.pop(); } } diff --git a/xplat/src/main/java/dev/emi/emi/EmiPort.java b/xplat/src/main/java/dev/emi/emi/EmiPort.java index a6a9993d..17de6a0c 100644 --- a/xplat/src/main/java/dev/emi/emi/EmiPort.java +++ b/xplat/src/main/java/dev/emi/emi/EmiPort.java @@ -148,7 +148,7 @@ public static void setPositionTexShader() { } public static void setPositionColorTexShader() { - RenderSystem.setShader(GameRenderer::getPositionTexColorProgram); + RenderSystem.setShader(GameRenderer::getPositionColorTexProgram); } public static Registry getItemRegistry() { @@ -168,8 +168,7 @@ public static Registry getPotionRegistry() { } public static Registry getEnchantmentRegistry() { - MinecraftClient client = MinecraftClient.getInstance(); - return client.world.getRegistryManager().get(RegistryKeys.ENCHANTMENT); + return Registries.ENCHANTMENT; } public static ButtonWidget newButton(int x, int y, int w, int h, Text name, PressAction action) { @@ -228,10 +227,10 @@ public static ComponentChanges emptyExtraData() { } public static Identifier id(String id) { - return Identifier.of(id); + return new Identifier(id); } public static Identifier id(String namespace, String path) { - return Identifier.of(namespace, path); + return new Identifier(namespace, path); } } diff --git a/xplat/src/main/java/dev/emi/emi/EmiRenderHelper.java b/xplat/src/main/java/dev/emi/emi/EmiRenderHelper.java index 3d171dc5..ef9a19b8 100644 --- a/xplat/src/main/java/dev/emi/emi/EmiRenderHelper.java +++ b/xplat/src/main/java/dev/emi/emi/EmiRenderHelper.java @@ -94,7 +94,8 @@ public static void drawTintedSprite(MatrixStack matrices, Sprite sprite, int col float g = ((color >> 8) & 255) / 256f; float b = (color & 255) / 256f; - BufferBuilder bufferBuilder = Tessellator.getInstance().begin(DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR); + BufferBuilder bufferBuilder = Tessellator.getInstance().getBuffer(); + bufferBuilder.begin(DrawMode.QUADS, VertexFormats.POSITION_COLOR_TEXTURE); float xMin = (float) x; float yMin = (float) y; float xMax = xMin + width; @@ -106,10 +107,10 @@ public static void drawTintedSprite(MatrixStack matrices, Sprite sprite, int col float uMax = sprite.getMaxU() - uSpan / 16 * (16 - (width + xOff)); float vMax = sprite.getMaxV() - vSpan / 16 * (16 - (height + yOff)); Matrix4f model = matrices.peek().getPositionMatrix(); - bufferBuilder.vertex(model, xMin, yMax, 1).color(r, g, b, 1).texture(uMin, vMax); - bufferBuilder.vertex(model, xMax, yMax, 1).color(r, g, b, 1).texture(uMax, vMax); - bufferBuilder.vertex(model, xMax, yMin, 1).color(r, g, b, 1).texture(uMax, vMin); - bufferBuilder.vertex(model, xMin, yMin, 1).color(r, g, b, 1).texture(uMin, vMin); + bufferBuilder.vertex(model, xMin, yMax, 1).color(r, g, b, 1).texture(uMin, vMax).next(); + bufferBuilder.vertex(model, xMax, yMax, 1).color(r, g, b, 1).texture(uMax, vMax).next(); + bufferBuilder.vertex(model, xMax, yMin, 1).color(r, g, b, 1).texture(uMax, vMin).next(); + bufferBuilder.vertex(model, xMin, yMin, 1).color(r, g, b, 1).texture(uMin, vMin).next(); EmiPort.draw(bufferBuilder); } @@ -343,7 +344,7 @@ public T add(T widget) { context.matrices().translate(x + 4, y + 4, 0); recipe.addWidgets(holder); - float delta = MinecraftClient.getInstance().getRenderTickCounter().getTickDelta(false); + float delta = MinecraftClient.getInstance().getTickDelta(); for (Widget widget : widgets) { widget.render(context.raw(), -1000, -1000, delta); } diff --git a/xplat/src/main/java/dev/emi/emi/VanillaPlugin.java b/xplat/src/main/java/dev/emi/emi/VanillaPlugin.java index a6791005..0a8e3754 100644 --- a/xplat/src/main/java/dev/emi/emi/VanillaPlugin.java +++ b/xplat/src/main/java/dev/emi/emi/VanillaPlugin.java @@ -152,9 +152,7 @@ import net.minecraft.recipe.StonecuttingRecipe; import net.minecraft.recipe.SuspiciousStewRecipe; import net.minecraft.recipe.TippedArrowRecipe; -import net.minecraft.recipe.input.RecipeInput; import net.minecraft.registry.entry.RegistryEntry; -import net.minecraft.registry.tag.EnchantmentTags; import net.minecraft.registry.tag.ItemTags; import net.minecraft.registry.tag.TagKey; import net.minecraft.screen.BlastFurnaceScreenHandler; @@ -548,7 +546,7 @@ private static void addRepair(EmiRegistry registry, Set hiddenItems) { synthetic("anvil/repairing/material", EmiUtil.subId(Items.SHIELD) + "/" + EmiUtil.subId(Items.OAK_PLANKS)))); for (Enchantment e : EmiAnvilEnchantRecipe.ENCHANTMENTS) { - if (!EmiPort.getEnchantmentRegistry().getEntry(e).isIn(EnchantmentTags.CURSE)) { + if (!e.isCursed()) { int max = Math.min(10, e.getMaxLevel()); int min = e.getMinLevel(); while (min <= max) { @@ -820,7 +818,7 @@ private static Identifier synthetic(String type, String name) { return EmiPort.id("emi", "/" + type + "/" + name); } - private static > Iterable getRecipes(EmiRegistry registry, RecipeType type) { + private static > Iterable getRecipes(EmiRegistry registry, RecipeType type) { return registry.getRecipeManager().listAllOfType(type).stream().map(e -> e.value())::iterator; } diff --git a/xplat/src/main/java/dev/emi/emi/api/stack/EmiStack.java b/xplat/src/main/java/dev/emi/emi/api/stack/EmiStack.java index ee66a4fd..0827b49c 100644 --- a/xplat/src/main/java/dev/emi/emi/api/stack/EmiStack.java +++ b/xplat/src/main/java/dev/emi/emi/api/stack/EmiStack.java @@ -1,10 +1,14 @@ package dev.emi.emi.api.stack; import java.util.List; +import java.util.Optional; import java.util.function.Function; import net.minecraft.component.ComponentChanges; -import net.minecraft.component.ComponentType; +import net.minecraft.component.ComponentHolder; +import net.minecraft.component.ComponentMap; +import net.minecraft.component.ComponentMapImpl; +import net.minecraft.component.DataComponentType; import org.jetbrains.annotations.Nullable; import com.google.common.collect.Lists; @@ -18,6 +22,7 @@ import net.minecraft.fluid.Fluids; import net.minecraft.item.ItemConvertible; import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NbtCompound; import net.minecraft.text.Text; import net.minecraft.util.Identifier; @@ -83,13 +88,13 @@ public EmiStack setChance(float chance) { public abstract ComponentChanges getComponentChanges(); - public @Nullable T get(ComponentType type) { + public @Nullable T get(DataComponentType type) { var opt = getComponentChanges().get(type); //noinspection OptionalAssignedToNull return opt != null ? opt.orElse(null) : null; } - public T getOrDefault(ComponentType type, T fallback) { + public T getOrDefault(DataComponentType type, T fallback) { var componentValue = this.get(type); return componentValue != null ? componentValue : fallback; } diff --git a/xplat/src/main/java/dev/emi/emi/api/stack/ItemEmiStack.java b/xplat/src/main/java/dev/emi/emi/api/stack/ItemEmiStack.java index 2ae870fa..4acbb1e2 100644 --- a/xplat/src/main/java/dev/emi/emi/api/stack/ItemEmiStack.java +++ b/xplat/src/main/java/dev/emi/emi/api/stack/ItemEmiStack.java @@ -2,12 +2,11 @@ import java.util.List; +import net.minecraft.client.item.TooltipType; import net.minecraft.component.ComponentChanges; -import net.minecraft.component.ComponentType; +import net.minecraft.component.DataComponentType; import net.minecraft.item.Item; import net.minecraft.item.Items; -import net.minecraft.item.tooltip.TooltipType; - import org.jetbrains.annotations.ApiStatus; import com.google.common.collect.Lists; @@ -81,7 +80,7 @@ public ComponentChanges getComponentChanges() { } @Override - public @Nullable T get(ComponentType type) { + public @Nullable T get(DataComponentType type) { // Check the changes first var changedOpt = this.componentChanges.get(type); //noinspection OptionalAssignedToNull diff --git a/xplat/src/main/java/dev/emi/emi/api/stack/TagEmiIngredient.java b/xplat/src/main/java/dev/emi/emi/api/stack/TagEmiIngredient.java index 7a270826..e1e155ee 100644 --- a/xplat/src/main/java/dev/emi/emi/api/stack/TagEmiIngredient.java +++ b/xplat/src/main/java/dev/emi/emi/api/stack/TagEmiIngredient.java @@ -14,7 +14,6 @@ import dev.emi.emi.config.EmiConfig; import dev.emi.emi.mixin.accessor.BakedModelManagerAccessor; import dev.emi.emi.mixin.accessor.ItemRendererAccessor; -import dev.emi.emi.platform.EmiAgnos; import dev.emi.emi.registry.EmiTags; import dev.emi.emi.runtime.EmiDrawContext; import dev.emi.emi.screen.tooltip.RemainderTooltipComponent; @@ -111,7 +110,8 @@ public void render(DrawContext draw, int x, int y, float delta, int flags) { stacks.get(0).render(context.raw(), x, y, delta, -1 ^ RENDER_AMOUNT); } } else { - BakedModel model = EmiAgnos.getBakedTagModel(EmiTags.getCustomModel(key)); + BakedModel model = ((BakedModelManagerAccessor) client.getBakedModelManager()).getModels() + .getOrDefault(EmiTags.getCustomModel(key), client.getBakedModelManager().getMissingModel()); context.matrices().push(); context.matrices().translate(x + 8, y + 8, 150); diff --git a/xplat/src/main/java/dev/emi/emi/handler/InventoryRecipeHandler.java b/xplat/src/main/java/dev/emi/emi/handler/InventoryRecipeHandler.java index ae82eb07..50e4570d 100644 --- a/xplat/src/main/java/dev/emi/emi/handler/InventoryRecipeHandler.java +++ b/xplat/src/main/java/dev/emi/emi/handler/InventoryRecipeHandler.java @@ -83,7 +83,7 @@ public boolean supportsRecipe(EmiRecipe recipe) { @Override public boolean canCraft(EmiRecipe recipe, EmiCraftContext context) { ScreenHandler sh = context.getScreenHandler(); - if (sh instanceof AbstractRecipeScreenHandler arsh) { + if (sh instanceof AbstractRecipeScreenHandler arsh) { if (recipe instanceof EmiCraftingRecipe crafting) { return crafting.canFit(arsh.getCraftingWidth(), arsh.getCraftingHeight()) && StandardRecipeHandler.super.canCraft(recipe, context); @@ -96,7 +96,7 @@ public boolean canCraft(EmiRecipe recipe, EmiCraftContext c public List getTooltip(EmiRecipe recipe, EmiCraftContext context) { if (!canCraft(recipe, context)) { ScreenHandler sh = context.getScreenHandler(); - if (sh instanceof AbstractRecipeScreenHandler arsh) { + if (sh instanceof AbstractRecipeScreenHandler arsh) { if (recipe instanceof EmiCraftingRecipe crafting) { if (!crafting.canFit(arsh.getCraftingWidth(), arsh.getCraftingHeight())) { return List.of(TooltipComponent.of(EmiPort.ordered(TOO_SMALL))); diff --git a/xplat/src/main/java/dev/emi/emi/handler/StonecuttingRecipeHandler.java b/xplat/src/main/java/dev/emi/emi/handler/StonecuttingRecipeHandler.java index 9cffb24a..793ad09f 100644 --- a/xplat/src/main/java/dev/emi/emi/handler/StonecuttingRecipeHandler.java +++ b/xplat/src/main/java/dev/emi/emi/handler/StonecuttingRecipeHandler.java @@ -17,7 +17,6 @@ import net.minecraft.recipe.RecipeEntry; import net.minecraft.recipe.RecipeType; import net.minecraft.recipe.StonecuttingRecipe; -import net.minecraft.recipe.input.SingleStackRecipeInput; import net.minecraft.screen.StonecutterScreenHandler; import net.minecraft.screen.slot.Slot; import net.minecraft.screen.slot.SlotActionType; @@ -56,7 +55,7 @@ public boolean craft(EmiRecipe recipe, EmiCraftContext boolean action = StandardRecipeHandler.super.craft(recipe, context); MinecraftClient client = MinecraftClient.getInstance(); World world = client.world; - SingleStackRecipeInput inv = new SingleStackRecipeInput(recipe.getInputs().get(0).getEmiStacks().get(0).getItemStack()); + Inventory inv = new SimpleInventory(recipe.getInputs().get(0).getEmiStacks().get(0).getItemStack()); List recipes = world.getRecipeManager().getAllMatches(RecipeType.STONECUTTING, inv, world).stream().map(RecipeEntry::value).toList(); for (int i = 0; i < recipes.size(); i++) { if (EmiPort.getId(recipes.get(i)) != null && EmiPort.getId(recipes.get(i)).equals(recipe.getId())) { diff --git a/xplat/src/main/java/dev/emi/emi/jemi/JemiStack.java b/xplat/src/main/java/dev/emi/emi/jemi/JemiStack.java index d6d19cda..ef0b9e44 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/JemiStack.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/JemiStack.java @@ -17,8 +17,10 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.tooltip.TooltipComponent; +import net.minecraft.client.item.TooltipType; import net.minecraft.component.ComponentChanges; -import net.minecraft.item.tooltip.TooltipType; +import net.minecraft.component.ComponentMap; +import net.minecraft.nbt.NbtCompound; import net.minecraft.text.Text; import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; diff --git a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiIngredientAcceptor.java b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiIngredientAcceptor.java index 6e433499..47805589 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiIngredientAcceptor.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiIngredientAcceptor.java @@ -5,6 +5,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import dev.emi.emi.runtime.EmiLog; +import net.minecraft.client.item.TooltipType; import org.jetbrains.annotations.Nullable; import com.google.common.collect.Lists; @@ -15,14 +17,12 @@ import dev.emi.emi.jemi.JemiStack; import dev.emi.emi.jemi.JemiUtil; import dev.emi.emi.jemi.impl.JemiRecipeSlot.IngredientRenderer; -import dev.emi.emi.runtime.EmiLog; import mezz.jei.api.gui.builder.IIngredientAcceptor; import mezz.jei.api.gui.ingredient.IRecipeSlotTooltipCallback; import mezz.jei.api.ingredients.IIngredientType; import mezz.jei.api.ingredients.ITypedIngredient; import mezz.jei.api.recipe.RecipeIngredientRole; import net.minecraft.fluid.Fluid; -import net.minecraft.item.tooltip.TooltipType; import net.minecraft.nbt.NbtCompound; import net.minecraft.text.Text; diff --git a/xplat/src/main/java/dev/emi/emi/mixin/CraftingResultSlotMixin.java b/xplat/src/main/java/dev/emi/emi/mixin/CraftingResultSlotMixin.java index 7db8a28a..c68d5e62 100644 --- a/xplat/src/main/java/dev/emi/emi/mixin/CraftingResultSlotMixin.java +++ b/xplat/src/main/java/dev/emi/emi/mixin/CraftingResultSlotMixin.java @@ -33,7 +33,7 @@ public class CraftingResultSlotMixin { private void onCrafted(ItemStack stack, CallbackInfo info) { World world = player.getWorld(); if (world.isClient) { - Optional opt = world.getRecipeManager().getFirstMatch(RecipeType.CRAFTING, input.createPositionedRecipeInput().input(), world).map(RecipeEntry::value); + Optional opt = world.getRecipeManager().getFirstMatch(RecipeType.CRAFTING, input, world).map(RecipeEntry::value); if (opt.isPresent()) { EmiRecipe recipe = EmiApi.getRecipeManager().getRecipe(EmiPort.getId(opt.get())); if (recipe != null) { diff --git a/xplat/src/main/java/dev/emi/emi/mixin/ItemStackMixin.java b/xplat/src/main/java/dev/emi/emi/mixin/ItemStackMixin.java index 8fd94552..eb841805 100644 --- a/xplat/src/main/java/dev/emi/emi/mixin/ItemStackMixin.java +++ b/xplat/src/main/java/dev/emi/emi/mixin/ItemStackMixin.java @@ -2,6 +2,8 @@ import java.util.List; +import net.minecraft.client.item.TooltipType; +import net.minecraft.item.Item; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -13,9 +15,7 @@ import dev.emi.emi.config.EmiConfig; import dev.emi.emi.search.EmiSearch; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraft.item.tooltip.TooltipType; import net.minecraft.text.Text; import net.minecraft.util.Formatting; diff --git a/xplat/src/main/java/dev/emi/emi/mixin/accessor/BakedModelManagerAccessor.java b/xplat/src/main/java/dev/emi/emi/mixin/accessor/BakedModelManagerAccessor.java index 92da7017..4e5cacd9 100644 --- a/xplat/src/main/java/dev/emi/emi/mixin/accessor/BakedModelManagerAccessor.java +++ b/xplat/src/main/java/dev/emi/emi/mixin/accessor/BakedModelManagerAccessor.java @@ -7,11 +7,11 @@ import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.render.model.BakedModelManager; -import net.minecraft.client.util.ModelIdentifier; +import net.minecraft.util.Identifier; @Mixin(BakedModelManager.class) public interface BakedModelManagerAccessor { @Accessor("models") - Map getModels(); + Map getModels(); } diff --git a/xplat/src/main/java/dev/emi/emi/platform/EmiAgnos.java b/xplat/src/main/java/dev/emi/emi/platform/EmiAgnos.java index 3d2ba0f4..c40ac119 100644 --- a/xplat/src/main/java/dev/emi/emi/platform/EmiAgnos.java +++ b/xplat/src/main/java/dev/emi/emi/platform/EmiAgnos.java @@ -9,7 +9,6 @@ import dev.emi.emi.api.stack.FluidEmiStack; import dev.emi.emi.registry.EmiPluginContainer; import net.minecraft.client.gui.tooltip.TooltipComponent; -import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.component.ComponentChanges; import net.minecraft.component.ComponentMap; @@ -18,7 +17,6 @@ import net.minecraft.item.ItemStack; import net.minecraft.nbt.NbtCompound; import net.minecraft.text.Text; -import net.minecraft.util.Identifier; public abstract class EmiAgnos { public static EmiAgnos delegate; @@ -143,10 +141,4 @@ public static Map getFuelMap() { } protected abstract Map getFuelMapAgnos(); - - public static BakedModel getBakedTagModel(Identifier id) { - return delegate.getBakedTagModelAgnos(id); - } - - protected abstract BakedModel getBakedTagModelAgnos(Identifier id); } diff --git a/xplat/src/main/java/dev/emi/emi/recipe/EmiShapedRecipe.java b/xplat/src/main/java/dev/emi/emi/recipe/EmiShapedRecipe.java index 8d6fbdd7..3b8c9ecd 100644 --- a/xplat/src/main/java/dev/emi/emi/recipe/EmiShapedRecipe.java +++ b/xplat/src/main/java/dev/emi/emi/recipe/EmiShapedRecipe.java @@ -14,7 +14,6 @@ import net.minecraft.item.ItemStack; import net.minecraft.recipe.CraftingRecipe; import net.minecraft.recipe.ShapedRecipe; -import net.minecraft.recipe.input.CraftingRecipeInput; public class EmiShapedRecipe extends EmiCraftingRecipe { @@ -41,12 +40,9 @@ public static void setRemainders(List input, CraftingRecipe recip List stacks = input.get(i).getEmiStacks(); for (EmiStack stack : stacks) { inv.setStack(i, stack.getItemStack().copy()); - CraftingRecipeInput cri = CraftingRecipeInput.create(inv.getWidth(), inv.getHeight(), inv.getHeldStacks()); - if (cri.getWidth() <= 3 && cri.getHeight() <= 3) { - ItemStack remainder = recipe.getRemainder(cri).get((i / 3 * cri.getWidth()) + (i % 3)); - if (!remainder.isEmpty()) { - stack.setRemainder(EmiStack.of(remainder)); - } + ItemStack remainder = recipe.getRemainder(inv).get(i); + if (!remainder.isEmpty()) { + stack.setRemainder(EmiStack.of(remainder)); } } inv.clear(); diff --git a/xplat/src/main/java/dev/emi/emi/recipe/special/EmiAnvilEnchantRecipe.java b/xplat/src/main/java/dev/emi/emi/recipe/special/EmiAnvilEnchantRecipe.java index 6aec426e..5309f78d 100644 --- a/xplat/src/main/java/dev/emi/emi/recipe/special/EmiAnvilEnchantRecipe.java +++ b/xplat/src/main/java/dev/emi/emi/recipe/special/EmiAnvilEnchantRecipe.java @@ -78,14 +78,14 @@ public void addWidgets(WidgetHolder widgets) { private ItemStack getTool() { ItemStack itemStack = tool.getDefaultStack(); - itemStack.addEnchantment(EmiPort.getEnchantmentRegistry().getEntry(enchantment), level); + itemStack.addEnchantment(enchantment, level); return itemStack; } private EmiStack getBook() { ItemStack item = new ItemStack(Items.ENCHANTED_BOOK); var enchBuilder = new ItemEnchantmentsComponent.Builder(ItemEnchantmentsComponent.DEFAULT); - enchBuilder.add(EmiPort.getEnchantmentRegistry().getEntry(enchantment), level); + enchBuilder.add(enchantment, level); item.set(DataComponentTypes.STORED_ENCHANTMENTS, enchBuilder.build()); return EmiStack.of(item); } diff --git a/xplat/src/main/java/dev/emi/emi/recipe/special/EmiGrindstoneDisenchantingBookRecipe.java b/xplat/src/main/java/dev/emi/emi/recipe/special/EmiGrindstoneDisenchantingBookRecipe.java index e0baf89b..99b9b41f 100644 --- a/xplat/src/main/java/dev/emi/emi/recipe/special/EmiGrindstoneDisenchantingBookRecipe.java +++ b/xplat/src/main/java/dev/emi/emi/recipe/special/EmiGrindstoneDisenchantingBookRecipe.java @@ -78,7 +78,7 @@ private EmiStack getBook() { ItemStack book = new ItemStack(Items.ENCHANTED_BOOK); var enchBuilder = new ItemEnchantmentsComponent.Builder(ItemEnchantmentsComponent.DEFAULT); - enchBuilder.add(EmiPort.getEnchantmentRegistry().getEntry(enchantment), level); + enchBuilder.add(enchantment, level); book.set(DataComponentTypes.STORED_ENCHANTMENTS, enchBuilder.build()); return EmiStack.of(book); diff --git a/xplat/src/main/java/dev/emi/emi/recipe/special/EmiGrindstoneDisenchantingRecipe.java b/xplat/src/main/java/dev/emi/emi/recipe/special/EmiGrindstoneDisenchantingRecipe.java index 8c460f3c..109cc508 100644 --- a/xplat/src/main/java/dev/emi/emi/recipe/special/EmiGrindstoneDisenchantingRecipe.java +++ b/xplat/src/main/java/dev/emi/emi/recipe/special/EmiGrindstoneDisenchantingRecipe.java @@ -16,7 +16,6 @@ import net.minecraft.enchantment.Enchantment; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraft.registry.tag.EnchantmentTags; import net.minecraft.util.Identifier; public class EmiGrindstoneDisenchantingRecipe implements EmiRecipe { @@ -93,16 +92,16 @@ private EmiStack getTool(Random random, Boolean enchanted){ } for (Enchantment e : list) { - if (e == enchantment || !Enchantment.canBeCombined(EmiPort.getEnchantmentRegistry().getEntry(e), EmiPort.getEnchantmentRegistry().getEntry(enchantment))) { + if (e == enchantment || !e.canCombine(enchantment)) { continue outer; } } list.add(enchantment); - if (EmiPort.getEnchantmentRegistry().getEntry(enchantment).isIn(EnchantmentTags.CURSE)) { - itemStack.addEnchantment(EmiPort.getEnchantmentRegistry().getEntry(enchantment), lvl); + if (enchantment.isCursed()) { + itemStack.addEnchantment(enchantment, lvl); } else if (enchanted) { - itemStack.addEnchantment(EmiPort.getEnchantmentRegistry().getEntry(enchantment), lvl); + itemStack.addEnchantment(enchantment, lvl); } } return EmiStack.of(itemStack); diff --git a/xplat/src/main/java/dev/emi/emi/recipe/special/EmiSmithingTrimRecipe.java b/xplat/src/main/java/dev/emi/emi/recipe/special/EmiSmithingTrimRecipe.java index 4e942477..7ea21bbc 100644 --- a/xplat/src/main/java/dev/emi/emi/recipe/special/EmiSmithingTrimRecipe.java +++ b/xplat/src/main/java/dev/emi/emi/recipe/special/EmiSmithingTrimRecipe.java @@ -11,8 +11,10 @@ import dev.emi.emi.api.widget.WidgetHolder; import dev.emi.emi.recipe.EmiSmithingRecipe; import net.minecraft.client.MinecraftClient; +import net.minecraft.inventory.Inventory; +import net.minecraft.inventory.SimpleInventory; +import net.minecraft.item.ItemStack; import net.minecraft.recipe.SmithingRecipe; -import net.minecraft.recipe.input.SmithingRecipeInput; public class EmiSmithingTrimRecipe extends EmiSmithingRecipe { private final SmithingRecipe recipe; @@ -40,7 +42,7 @@ public void addWidgets(WidgetHolder widgets) { private EmiStack getStack(Random r, int i) { EmiStack input = this.input.getEmiStacks().get(r.nextInt(this.input.getEmiStacks().size())); EmiStack addition = this.addition.getEmiStacks().get(r.nextInt(this.addition.getEmiStacks().size())); - SmithingRecipeInput inv = new SmithingRecipeInput(template.getEmiStacks().get(0).getItemStack(), input.getItemStack(), addition.getItemStack()); + Inventory inv = new SimpleInventory(template.getEmiStacks().get(0).getItemStack(), input.getItemStack(), addition.getItemStack(), ItemStack.EMPTY); MinecraftClient client = MinecraftClient.getInstance(); return new EmiStack[] { input, diff --git a/xplat/src/main/java/dev/emi/emi/registry/EmiStackProviders.java b/xplat/src/main/java/dev/emi/emi/registry/EmiStackProviders.java index 2ac94034..f5855015 100644 --- a/xplat/src/main/java/dev/emi/emi/registry/EmiStackProviders.java +++ b/xplat/src/main/java/dev/emi/emi/registry/EmiStackProviders.java @@ -21,7 +21,6 @@ import net.minecraft.recipe.CraftingRecipe; import net.minecraft.recipe.RecipeEntry; import net.minecraft.recipe.RecipeType; -import net.minecraft.recipe.input.CraftingRecipeInput; import net.minecraft.screen.slot.CraftingResultSlot; import net.minecraft.screen.slot.Slot; import net.minecraft.util.Identifier; @@ -60,10 +59,9 @@ public static EmiStackInteraction getStackAt(Screen screen, int x, int y, boolea // Emi be making assumptions try { RecipeInputInventory inv = ((CraftingResultSlotAccessor) craf).getInput(); - CraftingRecipeInput input = CraftingRecipeInput.create(inv.getWidth(), inv.getHeight(), inv.getHeldStacks()); MinecraftClient client = MinecraftClient.getInstance(); List list - = client.world.getRecipeManager().getAllMatches(RecipeType.CRAFTING, input, client.world) + = client.world.getRecipeManager().getAllMatches(RecipeType.CRAFTING, inv, client.world) .stream().map(RecipeEntry::value).toList(); if (!list.isEmpty()) { Identifier id = EmiPort.getId(list.get(0)); diff --git a/xplat/src/main/java/dev/emi/emi/registry/EmiTags.java b/xplat/src/main/java/dev/emi/emi/registry/EmiTags.java index ca602f3a..78be07ba 100644 --- a/xplat/src/main/java/dev/emi/emi/registry/EmiTags.java +++ b/xplat/src/main/java/dev/emi/emi/registry/EmiTags.java @@ -213,7 +213,7 @@ public static boolean hasCustomModel(TagKey key) { return getCustomModel(key) != null; } - public static void registerTagModels(ResourceManager manager, Consumer consumer, String variant) { + public static void registerTagModels(ResourceManager manager, Consumer consumer) { EmiTags.MODELED_TAGS.clear(); for (Identifier id : EmiPort.findResources(manager, "models/tag", s -> s.endsWith(".json"))) { String path = id.getPath(); @@ -223,11 +223,9 @@ public static void registerTagModels(ResourceManager manager, Consumer key = TagKey.of(RegistryKey.ofRegistry(EmiPort.id("minecraft", parts[0])), EmiPort.id(id.getNamespace(), path.substring(1 + parts[0].length()))); Identifier mid = EmiPort.id(id.getNamespace(), "tag/" + path); EmiTags.MODELED_TAGS.put(key, mid); - consumer.accept(new ModelIdentifier(mid, variant)); + consumer.accept(mid); } } - /* - Disable legacy tag models in 1.21+ due to modeling complications for (Identifier id : EmiPort.findResources(manager, "models/item/tags", s -> s.endsWith(".json"))) { String path = id.getPath(); path = path.substring(0, path.length() - 5); @@ -238,7 +236,6 @@ public static void registerTagModels(ResourceManager manager, Consumer EXTRA_RENDER_LAYERS = Lists.newArrayList(); private static boolean isEnabled() { - return false; - // TODO return EmiConfig.useBatchedRenderer && !isIncompatibleSodiumLoaded; + return EmiConfig.useBatchedRenderer && !isIncompatibleSodiumLoaded; } public StackBatcher() { - Map buffers = new HashMap<>(); + Map buffers = new HashMap<>(); assign(buffers, RenderLayer.getSolid()); assign(buffers, RenderLayer.getCutout()); assign(buffers, RenderLayer.getTranslucent()); @@ -120,17 +117,17 @@ public StackBatcher() { assign(buffers, TexturedRenderLayers.getEntityCutout()); assign(buffers, TexturedRenderLayers.getEntityTranslucentCull()); assign(buffers, RenderLayer.getGlint()); - //assign(buffers, RenderLayer.getDirectGlint()); + assign(buffers, RenderLayer.getDirectGlint()); assign(buffers, RenderLayer.getEntityGlint()); for (RenderLayer layer : EXTRA_RENDER_LAYERS) { assign(buffers, layer); } - imm = new BatcherVertexConsumerProvider(new BufferAllocator(256), buffers); + imm = new BatcherVertexConsumerProvider(new BufferBuilder(256), buffers); unlitFacade = new UnlitFacade(imm); } - private void assign(Map buffers, RenderLayer layer) { - buffers.put(layer, new BufferAllocator(layer.getExpectedBufferSize())); + private void assign(Map buffers, RenderLayer layer) { + buffers.put(layer, new BufferBuilder(layer.getExpectedBufferSize())); } public boolean isPopulated() { @@ -234,17 +231,18 @@ private void bake() { imm.drawCurrentLayer(); buffers.values().forEach(VertexBuffer::close); buffers.clear(); - for (Map.Entry entry : imm.getPendingLayerBuffers().entrySet()) { - bake(entry.getKey(), entry.getValue()); + for (RenderLayer layer : imm.getLayerBuffers().keySet()) { + bake(layer); } } - public void bake(RenderLayer layer, BufferBuilder bldr) { - // TODO if (!imm.getActiveConsumers().remove(bldr)) return; + public void bake(RenderLayer layer) { + BufferBuilder bldr = imm.getBufferInternal(layer); + if (!imm.getActiveConsumers().remove(bldr)) return; VertexBuffer vb = new VertexBuffer(VertexBuffer.Usage.DYNAMIC); EmiPort.upload(vb, bldr); buffers.put(layer, vb); - // TODO bldr.reset(); + bldr.reset(); } // Apparently BufferBuilder leaks memory in vanilla. Go figure @@ -277,24 +275,22 @@ public void unclaimAll() { } /* - * This class is mostly a copy of a 1.21 implementation of VertexConsumerProvider.Immediate + * This class is mostly a copy of a 1.18.2 implementation of VertexConsumerProvider.Immediate * The reimplementation allows compatibility with shader mods, as well as less hackery. */ private static class BatcherVertexConsumerProvider implements VertexConsumerProvider { - protected final BufferAllocator fallbackBuffer; - protected final Map layerBuffers; - protected final Map pending = new HashMap<>(); + protected final BufferBuilder fallbackBuffer; + protected final Map layerBuffers; protected Optional currentLayer = Optional.empty(); - protected final Set activeConsumers = Sets.newHashSet(); + protected final Set activeConsumers = Sets.newHashSet(); - protected BatcherVertexConsumerProvider(BufferAllocator fallbackBuffer, Map layerBuffers) { + protected BatcherVertexConsumerProvider(BufferBuilder fallbackBuffer, Map layerBuffers) { this.fallbackBuffer = fallbackBuffer; this.layerBuffers = layerBuffers; } @Override public VertexConsumer getBuffer(RenderLayer renderLayer) { - /* TODO Optional optional = renderLayer.asOptional(); BufferBuilder bufferBuilder = this.getBufferInternal(renderLayer); if (!Objects.equals(this.currentLayer, optional)) { @@ -308,10 +304,9 @@ public VertexConsumer getBuffer(RenderLayer renderLayer) { this.currentLayer = optional; } return bufferBuilder; - */ return null; } - private BufferAllocator getBufferInternal(RenderLayer layer) { + private BufferBuilder getBufferInternal(RenderLayer layer) { return this.layerBuffers.getOrDefault(layer, this.fallbackBuffer); } @@ -326,19 +321,26 @@ public void drawCurrentLayer() { } public void draw(RenderLayer layer) { - BufferAllocator bufferAllocator = this.getBufferInternal(layer); - if (!Objects.equals(this.currentLayer.orElse(null), layer) && bufferAllocator == this.fallbackBuffer) { + BufferBuilder bufferBuilder = this.getBufferInternal(layer); + boolean bl = Objects.equals(this.currentLayer, layer.asOptional()); + if (!bl && bufferBuilder == this.fallbackBuffer) { return; } - if (!this.activeConsumers.remove(bufferAllocator)) { + if (!this.activeConsumers.remove(bufferBuilder)) { return; } - // TODO layer.draw(bufferAllocator, VertexSorter.BY_Z); - this.currentLayer = Optional.empty(); + layer.draw(bufferBuilder, VertexSorter.BY_Z); + if (bl) { + this.currentLayer = Optional.empty(); + } } - - public Map getPendingLayerBuffers() { - return pending; + + public Map getLayerBuffers() { + return layerBuffers; + } + + public Set getActiveConsumers() { + return activeConsumers; } } @@ -371,11 +373,16 @@ public VertexConsumer normal(float x, float y, float z) { // all other methods are direct delegation @Override - public VertexConsumer vertex(float x, float y, float z) { + public VertexConsumer vertex(double x, double y, double z) { delegate.vertex(x, y, z); return this; } + @Override + public void unfixColor() { + delegate.unfixColor(); + } + @Override public VertexConsumer texture(float u, float v) { delegate.texture(u, v); @@ -388,12 +395,22 @@ public VertexConsumer overlay(int u, int v) { return this; } + @Override + public void next() { + delegate.next(); + } + @Override public VertexConsumer light(int u, int v) { delegate.light(u, v); return this; } + @Override + public void fixedColor(int r, int g, int b, int a) { + delegate.fixedColor(r, g, b, a); + } + @Override public VertexConsumer color(int r, int g, int b, int a) { delegate.color(r, g, b, a); diff --git a/xplat/src/main/java/dev/emi/emi/screen/widget/config/ListWidget.java b/xplat/src/main/java/dev/emi/emi/screen/widget/config/ListWidget.java index a80f6ba7..0ad84d05 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/widget/config/ListWidget.java +++ b/xplat/src/main/java/dev/emi/emi/screen/widget/config/ListWidget.java @@ -24,7 +24,6 @@ import net.minecraft.client.gui.tooltip.TooltipComponent; import net.minecraft.client.gui.widget.TextFieldWidget; import net.minecraft.client.render.BufferBuilder; -import net.minecraft.client.render.BufferRenderer; import net.minecraft.client.render.GameRenderer; import net.minecraft.client.render.Tessellator; import net.minecraft.client.render.VertexFormat; @@ -160,26 +159,31 @@ public void render(DrawContext draw, int mouseX, int mouseY, float delta) { int i = this.getScrollbarPositionX(); int j = i + 6; Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder bufferBuilder = tessellator.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR); + BufferBuilder bufferBuilder = tessellator.getBuffer(); RenderSystem.setShader(GameRenderer::getPositionTexColorProgram); this.hoveredEntry = this.isMouseOver(mouseX, mouseY) ? this.getEntryAtPosition(mouseX, mouseY) : null; { // Render background RenderSystem.setShaderTexture(0, Screen.MENU_BACKGROUND_TEXTURE); RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - bufferBuilder.vertex(this.left, this.bottom, 0) + bufferBuilder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR); + bufferBuilder.vertex((double)this.left, (double)this.bottom, 0.0) .texture((float)this.left / 32.0F, (float)(this.bottom + (int)this.getScrollAmount()) / 32.0F) - .color(32, 32, 32, 255); - bufferBuilder.vertex(this.right, this.bottom, 0) + .color(32, 32, 32, 255) + .next(); + bufferBuilder.vertex((double)this.right, (double)this.bottom, 0.0) .texture((float)this.right / 32.0F, (float)(this.bottom + (int)this.getScrollAmount()) / 32.0F) - .color(32, 32, 32, 255); - bufferBuilder.vertex(this.right, this.top, 0) + .color(32, 32, 32, 255) + .next(); + bufferBuilder.vertex((double)this.right, (double)this.top, 0.0) .texture((float)this.right / 32.0F, (float)(this.top + (int)this.getScrollAmount()) / 32.0F) - .color(32, 32, 32, 255); - bufferBuilder.vertex(this.left, this.top, 0) + .color(32, 32, 32, 255) + .next(); + bufferBuilder.vertex((double)this.left, (double)this.top, 0.0) .texture((float)this.left / 32.0F, (float)(this.top + (int)this.getScrollAmount()) / 32.0F) - .color(32, 32, 32, 255); - BufferRenderer.drawWithGlobalProgram(bufferBuilder.end()); + .color(32, 32, 32, 255) + .next(); + tessellator.draw(); } int k = this.getRowLeft(); @@ -192,22 +196,25 @@ public void render(DrawContext draw, int mouseX, int mouseY, float delta) { RenderSystem.setShaderTexture(0, Screen.MENU_BACKGROUND_TEXTURE); RenderSystem.enableDepthTest(); RenderSystem.depthFunc(519); - bufferBuilder = tessellator.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR); - bufferBuilder.vertex(this.left, this.top, -100).texture(0.0F, (float)this.top / 32.0F).color(64, 64, 64, 255); - bufferBuilder.vertex((this.left + this.width), this.top, -100) + bufferBuilder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR); + bufferBuilder.vertex((double)this.left, (double)this.top, -100.0).texture(0.0F, (float)this.top / 32.0F).color(64, 64, 64, 255).next(); + bufferBuilder.vertex((double)(this.left + this.width), (double)this.top, -100.0) .texture((float)this.width / 32.0F, (float)this.top / 32.0F) - .color(64, 64, 64, 255); - bufferBuilder.vertex((this.left + this.width), 0, -100).texture((float)this.width / 32.0F, 0.0F).color(64, 64, 64, 255); - bufferBuilder.vertex(this.left, 0, -100).texture(0.0F, 0.0F).color(64, 64, 64, 255); - bufferBuilder.vertex(this.left, this.height, -100).texture(0.0F, (float)this.height / 32.0F).color(64, 64, 64, 255); - bufferBuilder.vertex((this.left + this.width), this.height, -100) + .color(64, 64, 64, 255) + .next(); + bufferBuilder.vertex((double)(this.left + this.width), 0.0, -100.0).texture((float)this.width / 32.0F, 0.0F).color(64, 64, 64, 255).next(); + bufferBuilder.vertex((double)this.left, 0.0, -100.0).texture(0.0F, 0.0F).color(64, 64, 64, 255).next(); + bufferBuilder.vertex((double)this.left, (double)this.height, -100.0).texture(0.0F, (float)this.height / 32.0F).color(64, 64, 64, 255).next(); + bufferBuilder.vertex((double)(this.left + this.width), (double)this.height, -100.0) .texture((float)this.width / 32.0F, (float)this.height / 32.0F) - .color(64, 64, 64, 255); - bufferBuilder.vertex((this.left + this.width), this.bottom, -100) + .color(64, 64, 64, 255) + .next(); + bufferBuilder.vertex((double)(this.left + this.width), (double)this.bottom, -100.0) .texture((float)this.width / 32.0F, (float)this.bottom / 32.0F) - .color(64, 64, 64, 255); - bufferBuilder.vertex(this.left, this.bottom, -100).texture(0.0F, (float)this.bottom / 32.0F).color(64, 64, 64, 255); - BufferRenderer.drawWithGlobalProgram(bufferBuilder.end()); + .color(64, 64, 64, 255) + .next(); + bufferBuilder.vertex((double)this.left, (double)this.bottom, -100.0).texture(0.0F, (float)this.bottom / 32.0F).color(64, 64, 64, 255).next(); + tessellator.draw(); RenderSystem.depthFunc(515); RenderSystem.disableDepthTest(); RenderSystem.enableBlend(); @@ -216,16 +223,16 @@ public void render(DrawContext draw, int mouseX, int mouseY, float delta) { ); RenderSystem.setShader(GameRenderer::getPositionColorProgram); n = 4; - bufferBuilder = tessellator.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR); - bufferBuilder.vertex(this.left, (this.top + 4), 0).color(0, 0, 0, 0); - bufferBuilder.vertex(this.right, (this.top + 4), 0).color(0, 0, 0, 0); - bufferBuilder.vertex(this.right, this.top, 0).color(0, 0, 0, 255); - bufferBuilder.vertex(this.left, this.top, 0).color(0, 0, 0, 255); - bufferBuilder.vertex(this.left, this.bottom, 0).color(0, 0, 0, 255); - bufferBuilder.vertex(this.right, this.bottom, 0).color(0, 0, 0, 255); - bufferBuilder.vertex(this.right, (this.bottom - 4), 0).color(0, 0, 0, 0); - bufferBuilder.vertex(this.left, (this.bottom - 4), 0).color(0, 0, 0, 0); - BufferRenderer.drawWithGlobalProgram(bufferBuilder.end()); + bufferBuilder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR); + bufferBuilder.vertex((double)this.left, (double)(this.top + 4), 0.0).color(0, 0, 0, 0).next(); + bufferBuilder.vertex((double)this.right, (double)(this.top + 4), 0.0).color(0, 0, 0, 0).next(); + bufferBuilder.vertex((double)this.right, (double)this.top, 0.0).color(0, 0, 0, 255).next(); + bufferBuilder.vertex((double)this.left, (double)this.top, 0.0).color(0, 0, 0, 255).next(); + bufferBuilder.vertex((double)this.left, (double)this.bottom, 0.0).color(0, 0, 0, 255).next(); + bufferBuilder.vertex((double)this.right, (double)this.bottom, 0.0).color(0, 0, 0, 255).next(); + bufferBuilder.vertex((double)this.right, (double)(this.bottom - 4), 0.0).color(0, 0, 0, 0).next(); + bufferBuilder.vertex((double)this.left, (double)(this.bottom - 4), 0.0).color(0, 0, 0, 0).next(); + tessellator.draw(); } if ((o = this.getMaxScroll()) > 0) { @@ -236,20 +243,20 @@ public void render(DrawContext draw, int mouseX, int mouseY, float delta) { if (n < this.top) { n = this.top; } - bufferBuilder = tessellator.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR); - bufferBuilder.vertex(i, this.bottom, 0).color(0, 0, 0, 255); - bufferBuilder.vertex(j, this.bottom, 0).color(0, 0, 0, 255); - bufferBuilder.vertex(j, this.top, 0).color(0, 0, 0, 255); - bufferBuilder.vertex(i, this.top, 0).color(0, 0, 0, 255); - bufferBuilder.vertex(i, n + m, 0).color(128, 128, 128, 255); - bufferBuilder.vertex(j, n + m, 0).color(128, 128, 128, 255); - bufferBuilder.vertex(j, n, 0).color(128, 128, 128, 255); - bufferBuilder.vertex(i, n, 0).color(128, 128, 128, 255); - bufferBuilder.vertex(i, n + m - 1, 0).color(192, 192, 192, 255); - bufferBuilder.vertex(j - 1, n + m - 1, 0).color(192, 192, 192, 255); - bufferBuilder.vertex(j - 1, n, 0).color(192, 192, 192, 255); - bufferBuilder.vertex(i, n, 0).color(192, 192, 192, 255); - BufferRenderer.drawWithGlobalProgram(bufferBuilder.end()); + bufferBuilder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR); + bufferBuilder.vertex(i, this.bottom, 0.0).color(0, 0, 0, 255).next(); + bufferBuilder.vertex(j, this.bottom, 0.0).color(0, 0, 0, 255).next(); + bufferBuilder.vertex(j, this.top, 0.0).color(0, 0, 0, 255).next(); + bufferBuilder.vertex(i, this.top, 0.0).color(0, 0, 0, 255).next(); + bufferBuilder.vertex(i, n + m, 0.0).color(128, 128, 128, 255).next(); + bufferBuilder.vertex(j, n + m, 0.0).color(128, 128, 128, 255).next(); + bufferBuilder.vertex(j, n, 0.0).color(128, 128, 128, 255).next(); + bufferBuilder.vertex(i, n, 0.0).color(128, 128, 128, 255).next(); + bufferBuilder.vertex(i, n + m - 1, 0.0).color(192, 192, 192, 255).next(); + bufferBuilder.vertex(j - 1, n + m - 1, 0.0).color(192, 192, 192, 255).next(); + bufferBuilder.vertex(j - 1, n, 0.0).color(192, 192, 192, 255).next(); + bufferBuilder.vertex(i, n, 0.0).color(192, 192, 192, 255).next(); + tessellator.draw(); } RenderSystem.disableBlend(); } @@ -445,7 +452,7 @@ public boolean isMouseOver(double mouseX, double mouseY) { protected void renderList(DrawContext draw, int x, int y, int mouseX, int mouseY, float delta) { int i = this.getEntryCount(); Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder bufferBuilder = tessellator.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION); + BufferBuilder bufferBuilder = tessellator.getBuffer(); for (int j = 0; j < i; ++j) { int p; int k = this.getRowTop(j); @@ -465,18 +472,19 @@ protected void renderList(DrawContext draw, int x, int y, int mouseX, int mouseY RenderSystem.setShader(GameRenderer::getPositionProgram); float f = this.isFocused() ? 1.0f : 0.5f; RenderSystem.setShaderColor(f, f, f, 1.0f); - bufferBuilder.vertex(p, m + n + 2, 0); - bufferBuilder.vertex(q, m + n + 2, 0); - bufferBuilder.vertex(q, m - 2, 0); - bufferBuilder.vertex(p, m - 2, 0); - BufferRenderer.drawWithGlobalProgram(bufferBuilder.end()); + bufferBuilder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION); + bufferBuilder.vertex(p, m + n + 2, 0.0).next(); + bufferBuilder.vertex(q, m + n + 2, 0.0).next(); + bufferBuilder.vertex(q, m - 2, 0.0).next(); + bufferBuilder.vertex(p, m - 2, 0.0).next(); + tessellator.draw(); RenderSystem.setShaderColor(0.0f, 0.0f, 0.0f, 1.0f); - bufferBuilder = tessellator.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION); - bufferBuilder.vertex(p + 1, m + n + 1, 0); - bufferBuilder.vertex(q - 1, m + n + 1, 0); - bufferBuilder.vertex(q - 1, m - 1, 0); - bufferBuilder.vertex(p + 1, m - 1, 0); - BufferRenderer.drawWithGlobalProgram(bufferBuilder.end()); + bufferBuilder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION); + bufferBuilder.vertex(p + 1, m + n + 1, 0.0).next(); + bufferBuilder.vertex(q - 1, m + n + 1, 0.0).next(); + bufferBuilder.vertex(q - 1, m - 1, 0.0).next(); + bufferBuilder.vertex(p + 1, m - 1, 0.0).next(); + tessellator.draw(); } p = this.getRowLeft(); ((Entry)entry).render(draw, j, k, p, o - 3, n, mouseX, mouseY, Objects.equals(this.hoveredEntry, entry), delta); diff --git a/xplat/src/main/resources/assets/emi/lang/en_us.json b/xplat/src/main/resources/assets/emi/lang/en_us.json index 4825a82d..3dad6183 100644 --- a/xplat/src/main/resources/assets/emi/lang/en_us.json +++ b/xplat/src/main/resources/assets/emi/lang/en_us.json @@ -419,7 +419,6 @@ "tag.minecraft.enchantable.foot_armor": "Enchantable Foot Armor", "tag.minecraft.enchantable.head_armor": "Enchantable Head Armor", "tag.minecraft.enchantable.leg_armor": "Enchantable Leg Armor", - "tag.minecraft.enchantable.mace": "Enchantable Mace", "tag.minecraft.enchantable.mining": "Mining Enchantable", "tag.minecraft.enchantable.mining_loot": "Mining Looting Enchantable", "tag.minecraft.enchantable.sharp_weapon": "Enchantable Sharp Weapons", From 6d7254ebfb55cf83d44bb58d4447fc799ab6126d Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Sun, 16 Jun 2024 21:18:35 -0500 Subject: [PATCH 35/67] Revert "Fix 1.21 neo" This reverts commit 615d816a81de7627292934c1c3d99b4b6931cfd1. --- .../emi/emi/platform/neoforge/EmiPacketHandler.java | 5 ++--- .../main/java/dev/emi/emi/network/EmiNetwork.java | 13 +++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiPacketHandler.java b/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiPacketHandler.java index 7f209267..a4608a82 100644 --- a/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiPacketHandler.java +++ b/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiPacketHandler.java @@ -1,6 +1,5 @@ package dev.emi.emi.platform.neoforge; -import dev.emi.emi.EmiPort; import dev.emi.emi.network.CommandS2CPacket; import dev.emi.emi.network.CreateItemC2SPacket; import dev.emi.emi.network.EmiChessPacket; @@ -16,8 +15,8 @@ import net.neoforged.neoforge.network.handling.IPayloadContext; public class EmiPacketHandler { - private static final CustomPayload.Id ID_CHESS_CLIENTBOUND = new CustomPayload.Id(EmiPort.id("emi:chess_s2c")); - private static final CustomPayload.Id ID_CHESS_SERVERBOUND = new CustomPayload.Id(EmiPort.id("emi:chess_c2s")); + private static final CustomPayload.Id ID_CHESS_CLIENTBOUND = CustomPayload.id("emi:chess_s2c"); + private static final CustomPayload.Id ID_CHESS_SERVERBOUND = CustomPayload.id("emi:chess_c2s"); public static void init(RegisterPayloadHandlersEvent event) { var registrar = event.registrar("emi").optional(); diff --git a/xplat/src/main/java/dev/emi/emi/network/EmiNetwork.java b/xplat/src/main/java/dev/emi/emi/network/EmiNetwork.java index 5bcf73af..0b3c35cd 100644 --- a/xplat/src/main/java/dev/emi/emi/network/EmiNetwork.java +++ b/xplat/src/main/java/dev/emi/emi/network/EmiNetwork.java @@ -3,16 +3,17 @@ import java.util.function.BiConsumer; import java.util.function.Consumer; -import dev.emi.emi.EmiPort; import net.minecraft.network.packet.CustomPayload; import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.Identifier; public class EmiNetwork { - public static final CustomPayload.Id FILL_RECIPE = new CustomPayload.Id(EmiPort.id("emi:fill_recipe")); - public static final CustomPayload.Id CREATE_ITEM = new CustomPayload.Id(EmiPort.id("emi:create_item")); - public static final CustomPayload.Id COMMAND = new CustomPayload.Id(EmiPort.id("emi:command")); - public static final CustomPayload.Id CHESS = new CustomPayload.Id(EmiPort.id("emi:chess")); - public static final CustomPayload.Id PING = new CustomPayload.Id(EmiPort.id("emi:ping")); + // TODO + public static final CustomPayload.Id FILL_RECIPE = CustomPayload.id("emi/fill_recipe"); + public static final CustomPayload.Id CREATE_ITEM = CustomPayload.id("emi/create_item"); + public static final CustomPayload.Id COMMAND = CustomPayload.id("emi/command"); + public static final CustomPayload.Id CHESS = CustomPayload.id("emi/chess"); + public static final CustomPayload.Id PING = CustomPayload.id("emi/ping"); private static BiConsumer clientSender; private static Consumer serverSender; From b21281e4175fca7d72efd0ae33a2fb99a695b65c Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Sun, 16 Jun 2024 21:31:25 -0500 Subject: [PATCH 36/67] Fix forge networking --- .../emi/emi/platform/forge/EmiPacketHandler.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/forge/src/main/java/dev/emi/emi/platform/forge/EmiPacketHandler.java b/forge/src/main/java/dev/emi/emi/platform/forge/EmiPacketHandler.java index 080354a4..c253a24f 100644 --- a/forge/src/main/java/dev/emi/emi/platform/forge/EmiPacketHandler.java +++ b/forge/src/main/java/dev/emi/emi/platform/forge/EmiPacketHandler.java @@ -44,16 +44,20 @@ public static void init() { private static BiConsumer serverHandler(BiConsumer handler) { return (t, context) -> { - handler.accept(t, context.getSender()); - context.setPacketHandled(true); + context.enqueueWork(() -> { + handler.accept(t, context.getSender()); + context.setPacketHandled(true); + }); }; } private static BiConsumer clientHandler(BiConsumer handler) { return (t, context) -> { - MinecraftClient client = MinecraftClient.getInstance(); - handler.accept(t, client.player); - context.setPacketHandled(true); + context.enqueueWork(() -> { + MinecraftClient client = MinecraftClient.getInstance(); + handler.accept(t, client.player); + context.setPacketHandled(true); + }); }; } } From 57575b1e0d9c9b54ecab5b1640518331a74b3172 Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Fri, 28 Jun 2024 00:59:09 -0500 Subject: [PATCH 37/67] Fix 1.20.5 packets --- .../src/main/java/dev/emi/emi/network/EmiNetwork.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/xplat/src/main/java/dev/emi/emi/network/EmiNetwork.java b/xplat/src/main/java/dev/emi/emi/network/EmiNetwork.java index 0b3c35cd..f7a69dad 100644 --- a/xplat/src/main/java/dev/emi/emi/network/EmiNetwork.java +++ b/xplat/src/main/java/dev/emi/emi/network/EmiNetwork.java @@ -9,11 +9,11 @@ public class EmiNetwork { // TODO - public static final CustomPayload.Id FILL_RECIPE = CustomPayload.id("emi/fill_recipe"); - public static final CustomPayload.Id CREATE_ITEM = CustomPayload.id("emi/create_item"); - public static final CustomPayload.Id COMMAND = CustomPayload.id("emi/command"); - public static final CustomPayload.Id CHESS = CustomPayload.id("emi/chess"); - public static final CustomPayload.Id PING = CustomPayload.id("emi/ping"); + public static final CustomPayload.Id FILL_RECIPE = CustomPayload.id("emi:fill_recipe"); + public static final CustomPayload.Id CREATE_ITEM = CustomPayload.id("emi:create_item"); + public static final CustomPayload.Id COMMAND = CustomPayload.id("emi:command"); + public static final CustomPayload.Id CHESS = CustomPayload.id("emi:chess"); + public static final CustomPayload.Id PING = CustomPayload.id("emi:ping"); private static BiConsumer clientSender; private static Consumer serverSender; From 4d076162c8658488b63813b637ab1ce353636064 Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Fri, 28 Jun 2024 01:03:46 -0500 Subject: [PATCH 38/67] Revert "Fix 1.20.5 packets" This reverts commit 57575b1e0d9c9b54ecab5b1640518331a74b3172. --- .../src/main/java/dev/emi/emi/network/EmiNetwork.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/xplat/src/main/java/dev/emi/emi/network/EmiNetwork.java b/xplat/src/main/java/dev/emi/emi/network/EmiNetwork.java index f7a69dad..0b3c35cd 100644 --- a/xplat/src/main/java/dev/emi/emi/network/EmiNetwork.java +++ b/xplat/src/main/java/dev/emi/emi/network/EmiNetwork.java @@ -9,11 +9,11 @@ public class EmiNetwork { // TODO - public static final CustomPayload.Id FILL_RECIPE = CustomPayload.id("emi:fill_recipe"); - public static final CustomPayload.Id CREATE_ITEM = CustomPayload.id("emi:create_item"); - public static final CustomPayload.Id COMMAND = CustomPayload.id("emi:command"); - public static final CustomPayload.Id CHESS = CustomPayload.id("emi:chess"); - public static final CustomPayload.Id PING = CustomPayload.id("emi:ping"); + public static final CustomPayload.Id FILL_RECIPE = CustomPayload.id("emi/fill_recipe"); + public static final CustomPayload.Id CREATE_ITEM = CustomPayload.id("emi/create_item"); + public static final CustomPayload.Id COMMAND = CustomPayload.id("emi/command"); + public static final CustomPayload.Id CHESS = CustomPayload.id("emi/chess"); + public static final CustomPayload.Id PING = CustomPayload.id("emi/ping"); private static BiConsumer clientSender; private static Consumer serverSender; From 0f57d2eefa0038e4a132d6bf6167884d8df5b88e Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Fri, 28 Jun 2024 01:14:41 -0500 Subject: [PATCH 39/67] Fix neo brewing recipe access --- .../java/dev/emi/emi/platform/neoforge/EmiAgnosNeoForge.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiAgnosNeoForge.java b/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiAgnosNeoForge.java index f3148575..8cbc657b 100644 --- a/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiAgnosNeoForge.java +++ b/neoforge/src/main/java/dev/emi/emi/platform/neoforge/EmiAgnosNeoForge.java @@ -142,7 +142,7 @@ protected void addBrewingRecipesAgnos(EmiRegistry registry) { String pid = EmiUtil.subId(stack.getItem()); for (BrewingRecipeRegistry.Recipe recipe : BrewingRecipeRegistry.POTION_RECIPES) { try { - if (recipe.ingredient().getMatchingStacks().length > 0) { + if (recipe.ingredient.getMatchingStacks().length > 0) { Identifier id = EmiPort.id("emi", "/brewing/" + pid + "/" + EmiUtil.subId(recipe.ingredient.getMatchingStacks()[0].getItem()) + "/" + EmiUtil.subId(EmiPort.getPotionRegistry().getId(recipe.input)) From a08b05c76e644baae05acadc3c2558b2786e3c26 Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Tue, 2 Jul 2024 18:25:54 -0500 Subject: [PATCH 40/67] Revert "Upgrade gradle" This reverts commit fbbe9723c941437ceb22c1453f04bdfb3683addc. --- gradle/wrapper/gradle-wrapper.jar | Bin 43462 -> 59536 bytes gradlew.bat | 35 ++++++++++++++---------------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index d64cd4917707c1f8861d8cb53dd15194d4248596..7454180f2ae8848c63b8b4dea2cb829da983f2fa 100644 GIT binary patch literal 59536 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 QuEJmfE|#`Dqx|px0L@K;Y5)KL literal 43462 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 diff --git a/gradlew.bat b/gradlew.bat index 7101f8e4..ac1b06f9 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%"=="" @echo off +@if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,8 +25,7 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -@rem This is normally unused +if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -41,13 +40,13 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute +if "%ERRORLEVEL%" == "0" goto execute -echo. 1>&2 -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. goto fail @@ -57,11 +56,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. 1>&2 -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. goto fail @@ -76,15 +75,13 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd +if "%ERRORLEVEL%"=="0" goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 :mainEnd if "%OS%"=="Windows_NT" endlocal From 7d041baf55d72356bc66fff955af90cbc7c97052 Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Tue, 2 Jul 2024 18:27:10 -0500 Subject: [PATCH 41/67] Revert "Adjust JEMI for 1.21" This reverts commit c57c8d4fe56865b65cae2f2497782e7465fca5d2. --- .../emi/platform/fabric/EmiAgnosFabric.java | 7 +--- gradle.properties | 2 +- gradlew | 41 ++++++------------- .../java/dev/emi/emi/jemi/JemiPlugin.java | 2 +- .../emi/jemi/impl/JemiIngredientAcceptor.java | 3 +- .../emi/jemi/impl/JemiRecipeSlotBuilder.java | 6 +-- 6 files changed, 21 insertions(+), 40 deletions(-) diff --git a/fabric/src/main/java/dev/emi/emi/platform/fabric/EmiAgnosFabric.java b/fabric/src/main/java/dev/emi/emi/platform/fabric/EmiAgnosFabric.java index 66d0b8e7..8f176c08 100644 --- a/fabric/src/main/java/dev/emi/emi/platform/fabric/EmiAgnosFabric.java +++ b/fabric/src/main/java/dev/emi/emi/platform/fabric/EmiAgnosFabric.java @@ -11,7 +11,6 @@ import dev.emi.emi.EmiUtil; import dev.emi.emi.api.EmiPlugin; import dev.emi.emi.api.EmiRegistry; -import dev.emi.emi.api.FabricEmiStack; import dev.emi.emi.api.stack.EmiIngredient; import dev.emi.emi.api.stack.EmiStack; import dev.emi.emi.api.stack.FluidEmiStack; @@ -23,7 +22,6 @@ import dev.emi.emi.screen.FakeScreen; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -import mezz.jei.api.fabric.ingredients.fluids.IJeiFluidIngredient; import net.fabricmc.fabric.api.client.rendering.v1.ColorProviderRegistry; import net.fabricmc.fabric.api.registry.FuelRegistry; import net.fabricmc.fabric.api.transfer.v1.client.fluid.FluidVariantRendering; @@ -200,10 +198,7 @@ protected void renderFluidAgnos(FluidEmiStack stack, MatrixStack matrices, int x @Override protected EmiStack createFluidStackAgnos(Object object) { - if (object instanceof IJeiFluidIngredient fluid) { - return FabricEmiStack.of(fluid.getFluidVariant(), fluid.getAmount()); - } - return EmiStack.EMPTY; + return JemiUtil.getFluidFromJei(object); } @Override diff --git a/gradle.properties b/gradle.properties index 5903ce8b..8d14ab1c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -18,4 +18,4 @@ forge_version=1.20.4-49.0.9 neoforge_version=20.4.190 -jei_version=jei-1.21-fabric:19.0.0.14 +jei_version=jei-1.20.4-fabric:17.3.0.49 diff --git a/gradlew b/gradlew index 1aa94a42..1b6c7873 100755 --- a/gradlew +++ b/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -80,11 +80,13 @@ do esac done -# This is normally unused -# shellcheck disable=SC2034 +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +APP_NAME="Gradle" APP_BASE_NAME=${0##*/} -# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -131,29 +133,22 @@ location of your Java installation." fi else JAVACMD=java - if ! command -v java >/dev/null 2>&1 - then - die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." - fi fi # Increase the maximum file descriptors if we can. if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) - # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) - # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -198,15 +193,11 @@ if "$cygwin" || "$msys" ; then done fi - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, -# and any embedded shellness will be escaped. -# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be -# treated as '${Hostname}' itself on the command line. +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ @@ -214,12 +205,6 @@ set -- \ org.gradle.wrapper.GradleWrapperMain \ "$@" -# Stop when "xargs" is not available. -if ! command -v xargs >/dev/null 2>&1 -then - die "xargs is not available" -fi - # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. diff --git a/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java b/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java index 79e43784..c11bad0e 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java @@ -383,7 +383,7 @@ private void parseSubtypes(EmiRegistry registry) { } for (Fluid fluid : EmiPort.getFluidRegistry()) { IIngredientTypeWithSubtypes type = (IIngredientTypeWithSubtypes) JemiUtil.getFluidType(); - if (hasSubtype.test(type, JemiUtil.getFluidHelper().create(fluid.getRegistryEntry(), 1000))) { + if (hasSubtype.test(type, JemiUtil.getFluidHelper().create(fluid, 1000))) { registry.setDefaultComparison(fluid, Comparison.compareData(stack -> { ITypedIngredient typed = JemiUtil.getTyped(stack).orElse(null); if (typed != null) { diff --git a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiIngredientAcceptor.java b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiIngredientAcceptor.java index 1767f68a..7804a0f1 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiIngredientAcceptor.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiIngredientAcceptor.java @@ -15,6 +15,7 @@ import dev.emi.emi.jemi.JemiStack; import dev.emi.emi.jemi.JemiUtil; import dev.emi.emi.jemi.impl.JemiRecipeSlot.IngredientRenderer; +import dev.emi.emi.runtime.EmiLog; import mezz.jei.api.gui.builder.IIngredientAcceptor; import mezz.jei.api.gui.ingredient.IRecipeSlotTooltipCallback; import mezz.jei.api.ingredients.IIngredientType; @@ -110,7 +111,7 @@ public JemiIngredientAcceptor addFluidStack(Fluid fluid, long amount) { addStack(EmiStack.of(fluid, amount)); return this; } - + @Override public JemiIngredientAcceptor addFluidStack(Fluid fluid, long amount, NbtCompound tag) { addStack(EmiStack.of(fluid, tag, amount)); diff --git a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlotBuilder.java b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlotBuilder.java index 7ed2a816..4592bcd1 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlotBuilder.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlotBuilder.java @@ -17,8 +17,8 @@ import mezz.jei.api.ingredients.IIngredientRenderer; import mezz.jei.api.ingredients.IIngredientType; import mezz.jei.api.recipe.RecipeIngredientRole; -import net.minecraft.component.ComponentChanges; import net.minecraft.fluid.Fluid; +import net.minecraft.nbt.NbtCompound; public class JemiRecipeSlotBuilder implements IRecipeSlotBuilder { public final JemiIngredientAcceptor acceptor; @@ -60,8 +60,8 @@ public IRecipeSlotBuilder addFluidStack(Fluid fluid, long amount) { } @Override - public IRecipeSlotBuilder addFluidStack(Fluid fluid, long amount, ComponentChanges componentChanges) { - acceptor.addFluidStack(fluid, amount, componentChanges); + public IRecipeSlotBuilder addFluidStack(Fluid fluid, long amount, NbtCompound tag) { + acceptor.addFluidStack(fluid, amount, tag); return this; } From 27cab092dbe3ba2da02128caf828ddaa5cc9ed2a Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Tue, 2 Jul 2024 18:27:27 -0500 Subject: [PATCH 42/67] Revert "Resolve fabric networking issues" This reverts commit 5661599b114b2dff5e5151e289e1b435c11f7305. --- .../main/java/dev/emi/emi/platform/fabric/EmiMainFabric.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/fabric/src/main/java/dev/emi/emi/platform/fabric/EmiMainFabric.java b/fabric/src/main/java/dev/emi/emi/platform/fabric/EmiMainFabric.java index 9f8647ed..697da96f 100644 --- a/fabric/src/main/java/dev/emi/emi/platform/fabric/EmiMainFabric.java +++ b/fabric/src/main/java/dev/emi/emi/platform/fabric/EmiMainFabric.java @@ -2,7 +2,6 @@ import java.util.function.Function; -import dev.emi.emi.network.CommandS2CPacket; import dev.emi.emi.network.CreateItemC2SPacket; import dev.emi.emi.network.EmiChessPacket; import dev.emi.emi.network.EmiNetwork; @@ -36,10 +35,6 @@ public void onInitialize() { registerPacketReader(EmiNetwork.CREATE_ITEM, CreateItemC2SPacket::new); registerPacketReader(EmiNetwork.CHESS, EmiChessPacket.C2S::new); - PayloadTypeRegistry.playS2C().register(EmiNetwork.PING, PacketCodec.ofStatic((buf, v) -> v.write(buf), PingS2CPacket::new)); - PayloadTypeRegistry.playS2C().register(EmiNetwork.COMMAND, PacketCodec.ofStatic((buf, v) -> v.write(buf), CommandS2CPacket::new)); - PayloadTypeRegistry.playS2C().register(EmiNetwork.CHESS, PacketCodec.ofStatic((buf, v) -> v.write(buf), EmiChessPacket.S2C::new)); - ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { EmiNetwork.sendToClient(handler.player, new PingS2CPacket()); }); From 2bf63373450fc6ceb16b3c6310764285397ae836 Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Thu, 8 Aug 2024 18:19:48 -0500 Subject: [PATCH 43/67] Revert "Misc Jemi fixes (#646)" This reverts commit ee35c78b0f5b0b1e91cc0ba1571df8dcd88cbef3. --- gradle.properties | 2 +- .../main/java/dev/emi/emi/jemi/JemiPlugin.java | 15 +++++++-------- .../dev/emi/emi/jemi/JemiStackSerializer.java | 4 ++-- .../dev/emi/emi/jemi/runtime/JemiRecipesGui.java | 6 ------ 4 files changed, 10 insertions(+), 17 deletions(-) diff --git a/gradle.properties b/gradle.properties index f62c7e6d..b8d2e83b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -18,4 +18,4 @@ forge_version=1.20.4-49.0.9 neoforge_version=20.6.75-beta -jei_version=jei-1.21-fabric:19.5.3.67 +jei_version=jei-1.21-fabric:19.0.0.14 diff --git a/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java b/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java index daafd81f..79e43784 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java @@ -69,7 +69,6 @@ import net.minecraft.fluid.Fluid; import net.minecraft.item.Item; import net.minecraft.recipe.CraftingRecipe; -import net.minecraft.recipe.RecipeEntry; import net.minecraft.recipe.SpecialCraftingRecipe; import net.minecraft.screen.ScreenHandler; import net.minecraft.text.MutableText; @@ -97,7 +96,7 @@ public void registerItemSubtypes(ISubtypeRegistration registration) { @SuppressWarnings("unchecked") IIngredientTypeWithSubtypes castedType = (IIngredientTypeWithSubtypes) type; SubtypeInterpreters interpreters = ((SubtypeRegistration) registration).getInterpreters(); - return interpreters.contains(castedType, ingredient); + return interpreters.contains(castedType, castedType.getBase(ingredient)); }; } return; @@ -237,7 +236,7 @@ public void register(EmiRegistry registry) { if (type == RecipeTypes.INFORMATION) { addInfoRecipes(registry, (IRecipeCategory) c); } else if (type == RecipeTypes.CRAFTING) { - addCraftingRecipes(registry, (IRecipeCategory>) c); + addCraftingRecipes(registry, (IRecipeCategory) c); } continue; } @@ -303,15 +302,15 @@ private void addInfoRecipes(EmiRegistry registry, IRecipeCategory> category) { + private void addCraftingRecipes(EmiRegistry registry, IRecipeCategory category) { Set replaced = Sets.newHashSet(); Set replacements = Sets.newHashSet(); - List> recipes = Stream.concat( + List recipes = Stream.concat( runtime.getRecipeManager().createRecipeLookup(category.getRecipeType()).includeHidden().get(), - registry.getRecipeManager().listAllOfType(net.minecraft.recipe.RecipeType.CRAFTING).stream() - .filter(r -> r.value() instanceof SpecialCraftingRecipe) + registry.getRecipeManager().listAllOfType(net.minecraft.recipe.RecipeType.CRAFTING).stream().map(e -> e.value()) + .filter(r -> r instanceof SpecialCraftingRecipe) ).distinct().toList(); - for (RecipeEntry recipe : recipes) { + for (CraftingRecipe recipe : recipes) { try { if (category.isHandled(recipe)) { JemiRecipeLayoutBuilder builder = new JemiRecipeLayoutBuilder(); diff --git a/xplat/src/main/java/dev/emi/emi/jemi/JemiStackSerializer.java b/xplat/src/main/java/dev/emi/emi/jemi/JemiStackSerializer.java index bab74f54..a9b66dc4 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/JemiStackSerializer.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/JemiStackSerializer.java @@ -31,9 +31,9 @@ public EmiStack create(String uid, long amount) { if (type == VanillaTypes.ITEM_STACK || type == JemiUtil.getFluidType()) { continue; } - Optional opt = manager.getTypedIngredientByUid(type, uid).map(JemiUtil::getStack); + Optional opt = manager.getIngredientByUid(type, uid); if (opt.isPresent()) { - return opt.get().setAmount(amount); + return JemiUtil.getStack(type, opt.get()).setAmount(amount); } } return EmiStack.EMPTY; diff --git a/xplat/src/main/java/dev/emi/emi/jemi/runtime/JemiRecipesGui.java b/xplat/src/main/java/dev/emi/emi/jemi/runtime/JemiRecipesGui.java index d15e69d2..9e9110d5 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/runtime/JemiRecipesGui.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/runtime/JemiRecipesGui.java @@ -14,7 +14,6 @@ import mezz.jei.api.recipe.IFocus; import mezz.jei.api.recipe.RecipeIngredientRole; import mezz.jei.api.recipe.RecipeType; -import mezz.jei.api.recipe.category.IRecipeCategory; import mezz.jei.api.runtime.IRecipesGui; import net.minecraft.client.MinecraftClient; @@ -46,11 +45,6 @@ public void showTypes(List> recipeTypes) { } } - @Override - public void showRecipes(IRecipeCategory recipeCategory, List recipes, List> focuses) { - showTypes(List.of(recipeCategory.getRecipeType())); - } - @Override public Optional getIngredientUnderMouse(IIngredientType ingredientType) { MinecraftClient client = MinecraftClient.getInstance(); From 723051f5ff25a97e0d77166dedade90c00ab136b Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Thu, 8 Aug 2024 18:20:45 -0500 Subject: [PATCH 44/67] Revert "Re-enable StackBatcher for 1.21 (#624)" This reverts commit 76f4a8c3231a3be6e9d578ee26494e53aed8deb0. --- xplat/src/main/java/dev/emi/emi/EmiPort.java | 5 +++ .../java/dev/emi/emi/screen/StackBatcher.java | 45 ++++++++++++++----- 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/xplat/src/main/java/dev/emi/emi/EmiPort.java b/xplat/src/main/java/dev/emi/emi/EmiPort.java index ac4b26b4..17de6a0c 100644 --- a/xplat/src/main/java/dev/emi/emi/EmiPort.java +++ b/xplat/src/main/java/dev/emi/emi/EmiPort.java @@ -121,6 +121,11 @@ public static boolean canTallFlowerDuplicate(TallFlowerBlock tallFlowerBlock) { } } + public static void upload(VertexBuffer vb, BufferBuilder bldr) { + vb.bind(); + vb.upload(bldr.end()); + } + public static void setShader(VertexBuffer buf, Matrix4f mat) { buf.bind(); buf.draw(mat, RenderSystem.getProjectionMatrix(), RenderSystem.getShader()); diff --git a/xplat/src/main/java/dev/emi/emi/screen/StackBatcher.java b/xplat/src/main/java/dev/emi/emi/screen/StackBatcher.java index dbdd9f93..8d4c123f 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/StackBatcher.java +++ b/xplat/src/main/java/dev/emi/emi/screen/StackBatcher.java @@ -13,7 +13,6 @@ import java.util.Optional; import java.util.Set; -import net.minecraft.client.render.BuiltBuffer; import org.joml.Matrix4f; import com.google.common.collect.Lists; @@ -46,20 +45,42 @@ */ public class StackBatcher { private static MethodHandle sodiumSpriteHandle; + private static boolean isIncompatibleSodiumLoaded; static { try { Class clazz = null; + // TODO this is a 1.18 -> 1.19 refactor for Sodium try { - // Try Sodium 0.5 name - clazz = Class.forName("me.jellysquid.mods.sodium.client.render.texture.SpriteUtil"); + clazz = Class.forName("net.caffeinemc.sodium.render.texture.SpriteUtil"); } catch (Throwable t) { } + if (clazz == null) { + clazz = Class.forName("me.jellysquid.mods.sodium.client.render.texture.SpriteUtil"); + } sodiumSpriteHandle = MethodHandles.lookup() .findStatic(clazz, "markSpriteActive", MethodType.methodType(void.class, Sprite.class)); if (sodiumSpriteHandle != null) { EmiLog.info("Discovered Sodium"); } + + if(EmiAgnos.isModLoaded("sodium") || EmiAgnos.isModLoaded("rubidium")) { + // Check for the modern VertexBufferWriter API. If so, we are likely on Sodium 0.5+ (or a derivative), + // which can generally handle a custom VertexConsumer properly. + try { + Class.forName("net.caffeinemc.mods.sodium.api.vertex.buffer.VertexBufferWriter"); + } catch(Throwable t) { + // Check for the legacy VBW API which *cannot* handle this + try { + Class.forName("me.jellysquid.mods.sodium.client.render.vertex.VertexBufferWriter"); + // Success means the class exists + isIncompatibleSodiumLoaded = true; + EmiLog.info("Batching stack renderer disabled for compatibility with legacy Sodium"); + } catch(Throwable t2) { + // Old enough Sodiums shouldn't have an issue + } + } + } } catch (Throwable e) { } } @@ -213,15 +234,13 @@ private void bake() { for (RenderLayer layer : imm.getLayerBuffers().keySet()) { bake(layer); } - imm.getPendingLayerBuffers().clear(); } public void bake(RenderLayer layer) { BufferBuilder bldr = imm.getBufferInternal(layer); if (!imm.getActiveConsumers().remove(bldr)) return; VertexBuffer vb = new VertexBuffer(VertexBuffer.Usage.DYNAMIC); - vb.bind(); - vb.upload(builtBuffer); + EmiPort.upload(vb, bldr); buffers.put(layer, vb); bldr.reset(); } @@ -279,11 +298,13 @@ public VertexConsumer getBuffer(RenderLayer renderLayer) { if (this.currentLayer.isPresent() && !this.layerBuffers.containsKey(renderLayer2 = this.currentLayer.get())) { this.draw(renderLayer2); } - - this.pending.put(renderLayer, bufferBuilder); + if (this.activeConsumers.add(bufferBuilder)) { + bufferBuilder.begin(renderLayer.getDrawMode(), renderLayer.getVertexFormat()); + } + this.currentLayer = optional; } - return bufferBuilder; + */ return null; } private BufferBuilder getBufferInternal(RenderLayer layer) { @@ -291,12 +312,12 @@ private BufferBuilder getBufferInternal(RenderLayer layer) { } public void drawCurrentLayer() { - if (this.currentLayer != null) { - RenderLayer renderLayer = this.currentLayer; + if (this.currentLayer.isPresent()) { + RenderLayer renderLayer = this.currentLayer.get(); if (!this.layerBuffers.containsKey(renderLayer)) { this.draw(renderLayer); } - this.currentLayer = null; + this.currentLayer = Optional.empty(); } } From 1bfbd0b58f5ff9a0be6bd357460ca6ec6e5687e0 Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Thu, 8 Aug 2024 18:22:37 -0500 Subject: [PATCH 45/67] Properly revert 1.21 StackBatcher changes --- xplat/src/main/java/dev/emi/emi/screen/StackBatcher.java | 1 - 1 file changed, 1 deletion(-) diff --git a/xplat/src/main/java/dev/emi/emi/screen/StackBatcher.java b/xplat/src/main/java/dev/emi/emi/screen/StackBatcher.java index 8d4c123f..5b87066c 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/StackBatcher.java +++ b/xplat/src/main/java/dev/emi/emi/screen/StackBatcher.java @@ -304,7 +304,6 @@ public VertexConsumer getBuffer(RenderLayer renderLayer) { this.currentLayer = optional; } return bufferBuilder; - */ return null; } private BufferBuilder getBufferInternal(RenderLayer layer) { From 0fc9a1a1c66eaa1859ed444a9c139fe3b7ace172 Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Thu, 8 Aug 2024 18:25:09 -0500 Subject: [PATCH 46/67] Fix serializer --- .../emi/api/stack/serializer/EmiStackSerializer.java | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/xplat/src/main/java/dev/emi/emi/api/stack/serializer/EmiStackSerializer.java b/xplat/src/main/java/dev/emi/emi/api/stack/serializer/EmiStackSerializer.java index a174ec85..91626969 100644 --- a/xplat/src/main/java/dev/emi/emi/api/stack/serializer/EmiStackSerializer.java +++ b/xplat/src/main/java/dev/emi/emi/api/stack/serializer/EmiStackSerializer.java @@ -1,6 +1,5 @@ package dev.emi.emi.api.stack.serializer; -import com.mojang.serialization.DynamicOps; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -22,16 +21,6 @@ public interface EmiStackSerializer extends EmiIngredientSer EmiStack create(Identifier id, NbtCompound nbt, long amount); - private static DynamicOps withRegistryAccess(DynamicOps ops) { - MinecraftClient instance = MinecraftClient.getInstance(); - if (instance == null || instance.world == null) { - //Note: instance can be null in datagen, just fall back to a variant that doesn't have registry access - // as in the majority of cases this will work fine - return ops; - } - return instance.world.getRegistryManager().getOps(ops); - } - @Override default EmiIngredient deserialize(JsonElement element) { Identifier id = null; From 2df533755f8d03cef9beaf1a2b8193eaeb08af10 Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Sun, 8 Sep 2024 15:10:45 -0500 Subject: [PATCH 47/67] Remove base call for subtypes --- xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java b/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java index dfefbeeb..0a295a6b 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java @@ -96,7 +96,7 @@ public void registerItemSubtypes(ISubtypeRegistration registration) { @SuppressWarnings("unchecked") IIngredientTypeWithSubtypes castedType = (IIngredientTypeWithSubtypes) type; SubtypeInterpreters interpreters = ((SubtypeRegistration) registration).getInterpreters(); - return interpreters.contains(castedType, castedType.getBase(ingredient)); + return interpreters.contains(castedType, ingredient); }; } return; From 201d6992a99256b079a3856af94552886b8b69e6 Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Sun, 8 Sep 2024 15:11:44 -0500 Subject: [PATCH 48/67] Revert 1.20.1 JEMI base removal --- xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java b/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java index 0a295a6b..dfefbeeb 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java @@ -96,7 +96,7 @@ public void registerItemSubtypes(ISubtypeRegistration registration) { @SuppressWarnings("unchecked") IIngredientTypeWithSubtypes castedType = (IIngredientTypeWithSubtypes) type; SubtypeInterpreters interpreters = ((SubtypeRegistration) registration).getInterpreters(); - return interpreters.contains(castedType, ingredient); + return interpreters.contains(castedType, castedType.getBase(ingredient)); }; } return; From d1c9e8b5df4945db17520def135e530769d94241 Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Sun, 29 Sep 2024 17:56:39 -0500 Subject: [PATCH 49/67] Revert "JEMI updates for modern JEI" This reverts commit 80b99b979dfd2dca7e5cebe8b78d15d7268b27f5. --- xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java | 2 +- xplat/src/main/java/dev/emi/emi/jemi/JemiRecipe.java | 9 ++++----- xplat/src/main/java/dev/emi/emi/jemi/JemiStack.java | 6 ++---- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java b/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java index 7257aec9..ee08f5a3 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java @@ -106,7 +106,7 @@ public void registerItemSubtypes(ISubtypeRegistration registration) { hasSubtype = (type, ingredient) -> { @SuppressWarnings("unchecked") IIngredientTypeWithSubtypes castedType = (IIngredientTypeWithSubtypes) type; - return subtypeManager.hasSubtypes(castedType, ingredient); + return subtypeManager.getSubtypeInfo(castedType, ingredient, UidContext.Recipe) != IIngredientSubtypeInterpreter.NONE; }; } diff --git a/xplat/src/main/java/dev/emi/emi/jemi/JemiRecipe.java b/xplat/src/main/java/dev/emi/emi/jemi/JemiRecipe.java index 6cd74c9a..59cd297e 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/JemiRecipe.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/JemiRecipe.java @@ -15,13 +15,11 @@ import dev.emi.emi.jemi.impl.JemiRecipeLayoutBuilder; import dev.emi.emi.jemi.impl.JemiRecipeSlot; import dev.emi.emi.jemi.impl.JemiRecipeSlotBuilder; -import dev.emi.emi.jemi.impl.JemiTooltipBuilder; import dev.emi.emi.jemi.widget.JemiSlotWidget; import dev.emi.emi.jemi.widget.JemiTankWidget; import dev.emi.emi.runtime.EmiDrawContext; import dev.emi.emi.screen.EmiScreenManager; import mezz.jei.api.gui.IRecipeLayoutDrawable; -import mezz.jei.api.gui.inputs.IJeiUserInput; import mezz.jei.api.recipe.RecipeIngredientRole; import mezz.jei.api.recipe.category.IRecipeCategory; import mezz.jei.library.focus.FocusGroup; @@ -171,9 +169,10 @@ public void render(DrawContext draw, int mouseX, int mouseY, float delta) { @Override public List getTooltip(int mouseX, int mouseY) { - JemiTooltipBuilder builder = new JemiTooltipBuilder(); - category.getTooltip(builder, recipe, recipeLayoutDrawable.getRecipeSlotsView(), mouseX, mouseY); - return builder.tooltip; + return category.getTooltipStrings(recipe, recipeLayoutDrawable.getRecipeSlotsView(), mouseX, mouseY) + .stream() + .map(t -> TooltipComponent.of(t.asOrderedText())) + .toList(); } @Override diff --git a/xplat/src/main/java/dev/emi/emi/jemi/JemiStack.java b/xplat/src/main/java/dev/emi/emi/jemi/JemiStack.java index 7ce4045f..ef0b9e44 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/JemiStack.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/JemiStack.java @@ -8,7 +8,6 @@ import dev.emi.emi.EmiUtil; import dev.emi.emi.api.stack.EmiStack; import dev.emi.emi.config.EmiConfig; -import dev.emi.emi.jemi.impl.JemiTooltipBuilder; import dev.emi.emi.runtime.EmiDrawContext; import mezz.jei.api.ingredients.IIngredientHelper; import mezz.jei.api.ingredients.IIngredientRenderer; @@ -94,9 +93,8 @@ public List getTooltipText() { public List getTooltip() { List list = Lists.newArrayList(); MinecraftClient client = MinecraftClient.getInstance(); - JemiTooltipBuilder builder = new JemiTooltipBuilder(); - renderer.getTooltip(builder, ingredient, client.options.advancedItemTooltips ? TooltipType.ADVANCED : TooltipType.BASIC); - list.addAll(builder.tooltip); + list.addAll(renderer.getTooltip(ingredient, client.options.advancedItemTooltips ? TooltipType.ADVANCED : TooltipType.BASIC) + .stream().map(EmiPort::ordered).map(TooltipComponent::of).toList()); Identifier id = getId(); if (EmiConfig.appendModId && id != null) { From eff85e956dc96c8188523305bb5f4507db0092a9 Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Sun, 29 Sep 2024 17:58:54 -0500 Subject: [PATCH 50/67] Revert "Revert "JEMI updates for modern JEI"" This reverts commit d1c9e8b5df4945db17520def135e530769d94241. --- xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java | 2 +- xplat/src/main/java/dev/emi/emi/jemi/JemiRecipe.java | 9 +++++---- xplat/src/main/java/dev/emi/emi/jemi/JemiStack.java | 6 ++++-- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java b/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java index 83f2784a..8e03b443 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java @@ -106,7 +106,7 @@ public void registerItemSubtypes(ISubtypeRegistration registration) { hasSubtype = (type, ingredient) -> { @SuppressWarnings("unchecked") IIngredientTypeWithSubtypes castedType = (IIngredientTypeWithSubtypes) type; - return subtypeManager.getSubtypeInfo(castedType, ingredient, UidContext.Recipe) != IIngredientSubtypeInterpreter.NONE; + return subtypeManager.hasSubtypes(castedType, ingredient); }; } diff --git a/xplat/src/main/java/dev/emi/emi/jemi/JemiRecipe.java b/xplat/src/main/java/dev/emi/emi/jemi/JemiRecipe.java index aa9521c1..405b9599 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/JemiRecipe.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/JemiRecipe.java @@ -20,11 +20,13 @@ import dev.emi.emi.jemi.impl.JemiRecipeLayoutBuilder; import dev.emi.emi.jemi.impl.JemiRecipeSlot; import dev.emi.emi.jemi.impl.JemiRecipeSlotBuilder; +import dev.emi.emi.jemi.impl.JemiTooltipBuilder; import dev.emi.emi.jemi.widget.JemiSlotWidget; import dev.emi.emi.jemi.widget.JemiTankWidget; import dev.emi.emi.runtime.EmiDrawContext; import dev.emi.emi.screen.EmiScreenManager; import mezz.jei.api.gui.IRecipeLayoutDrawable; +import mezz.jei.api.gui.inputs.IJeiUserInput; import mezz.jei.api.recipe.RecipeIngredientRole; import mezz.jei.api.recipe.category.IRecipeCategory; import mezz.jei.library.focus.FocusGroup; @@ -170,10 +172,9 @@ public void render(DrawContext draw, int mouseX, int mouseY, float delta) { @Override public List getTooltip(int mouseX, int mouseY) { - return category.getTooltipStrings(recipe, recipeLayoutDrawable.getRecipeSlotsView(), mouseX, mouseY) - .stream() - .map(t -> TooltipComponent.of(t.asOrderedText())) - .toList(); + JemiTooltipBuilder builder = new JemiTooltipBuilder(); + category.getTooltip(builder, recipe, recipeLayoutDrawable.getRecipeSlotsView(), mouseX, mouseY); + return builder.tooltip; } @Override diff --git a/xplat/src/main/java/dev/emi/emi/jemi/JemiStack.java b/xplat/src/main/java/dev/emi/emi/jemi/JemiStack.java index 93f77e60..082a7f39 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/JemiStack.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/JemiStack.java @@ -8,6 +8,7 @@ import dev.emi.emi.EmiUtil; import dev.emi.emi.api.stack.EmiStack; import dev.emi.emi.config.EmiConfig; +import dev.emi.emi.jemi.impl.JemiTooltipBuilder; import dev.emi.emi.runtime.EmiDrawContext; import mezz.jei.api.ingredients.IIngredientHelper; import mezz.jei.api.ingredients.IIngredientRenderer; @@ -91,8 +92,9 @@ public List getTooltipText() { public List getTooltip() { List list = Lists.newArrayList(); MinecraftClient client = MinecraftClient.getInstance(); - list.addAll(renderer.getTooltip(ingredient, client.options.advancedItemTooltips ? TooltipContext.Default.ADVANCED : TooltipContext.Default.BASIC) - .stream().map(EmiPort::ordered).map(TooltipComponent::of).toList()); + JemiTooltipBuilder builder = new JemiTooltipBuilder(); + renderer.getTooltip(builder, ingredient, client.options.advancedItemTooltips ? TooltipContext.Default.ADVANCED : TooltipContext.Default.BASIC); + list.addAll(builder.tooltip); Identifier id = getId(); if (EmiConfig.appendModId && id != null) { From 0d680b834de3bf2b98915d28504af2cbcf2dc376 Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Sun, 29 Sep 2024 17:59:32 -0500 Subject: [PATCH 51/67] Revert "Revert "Revert "JEMI updates for modern JEI""" This reverts commit eff85e956dc96c8188523305bb5f4507db0092a9. --- xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java | 2 +- xplat/src/main/java/dev/emi/emi/jemi/JemiRecipe.java | 9 ++++----- xplat/src/main/java/dev/emi/emi/jemi/JemiStack.java | 6 ++---- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java b/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java index 0bb9757d..161532b6 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/JemiPlugin.java @@ -106,7 +106,7 @@ public void registerItemSubtypes(ISubtypeRegistration registration) { hasSubtype = (type, ingredient) -> { @SuppressWarnings("unchecked") IIngredientTypeWithSubtypes castedType = (IIngredientTypeWithSubtypes) type; - return subtypeManager.hasSubtypes(castedType, ingredient); + return subtypeManager.getSubtypeInfo(castedType, ingredient, UidContext.Recipe) != IIngredientSubtypeInterpreter.NONE; }; } diff --git a/xplat/src/main/java/dev/emi/emi/jemi/JemiRecipe.java b/xplat/src/main/java/dev/emi/emi/jemi/JemiRecipe.java index 62148039..5b016a1d 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/JemiRecipe.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/JemiRecipe.java @@ -20,13 +20,11 @@ import dev.emi.emi.jemi.impl.JemiRecipeLayoutBuilder; import dev.emi.emi.jemi.impl.JemiRecipeSlot; import dev.emi.emi.jemi.impl.JemiRecipeSlotBuilder; -import dev.emi.emi.jemi.impl.JemiTooltipBuilder; import dev.emi.emi.jemi.widget.JemiSlotWidget; import dev.emi.emi.jemi.widget.JemiTankWidget; import dev.emi.emi.runtime.EmiDrawContext; import dev.emi.emi.screen.EmiScreenManager; import mezz.jei.api.gui.IRecipeLayoutDrawable; -import mezz.jei.api.gui.inputs.IJeiUserInput; import mezz.jei.api.recipe.RecipeIngredientRole; import mezz.jei.api.recipe.category.IRecipeCategory; import mezz.jei.library.focus.FocusGroup; @@ -172,9 +170,10 @@ public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { @Override public List getTooltip(int mouseX, int mouseY) { - JemiTooltipBuilder builder = new JemiTooltipBuilder(); - category.getTooltip(builder, recipe, recipeLayoutDrawable.getRecipeSlotsView(), mouseX, mouseY); - return builder.tooltip; + return category.getTooltipStrings(recipe, recipeLayoutDrawable.getRecipeSlotsView(), mouseX, mouseY) + .stream() + .map(t -> TooltipComponent.of(t.asOrderedText())) + .toList(); } @Override diff --git a/xplat/src/main/java/dev/emi/emi/jemi/JemiStack.java b/xplat/src/main/java/dev/emi/emi/jemi/JemiStack.java index 2035e4be..01b04152 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/JemiStack.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/JemiStack.java @@ -8,7 +8,6 @@ import dev.emi.emi.EmiUtil; import dev.emi.emi.api.stack.EmiStack; import dev.emi.emi.config.EmiConfig; -import dev.emi.emi.jemi.impl.JemiTooltipBuilder; import dev.emi.emi.runtime.EmiDrawContext; import mezz.jei.api.ingredients.IIngredientHelper; import mezz.jei.api.ingredients.IIngredientRenderer; @@ -92,9 +91,8 @@ public List getTooltipText() { public List getTooltip() { List list = Lists.newArrayList(); MinecraftClient client = MinecraftClient.getInstance(); - JemiTooltipBuilder builder = new JemiTooltipBuilder(); - renderer.getTooltip(builder, ingredient, client.options.advancedItemTooltips ? TooltipContext.Default.ADVANCED : TooltipContext.Default.BASIC); - list.addAll(builder.tooltip); + list.addAll(renderer.getTooltip(ingredient, client.options.advancedItemTooltips ? TooltipContext.Default.ADVANCED : TooltipContext.Default.BASIC) + .stream().map(EmiPort::ordered).map(TooltipComponent::of).toList()); Identifier id = getId(); if (EmiConfig.appendModId && id != null) { From 50c14113af5c2aa4a377c594203053c17fac5ba4 Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Sun, 6 Oct 2024 23:48:09 -0500 Subject: [PATCH 52/67] Revert "Update JEMI integration" This reverts commit b478fdd1dabbd7ba1cc69db85b53f4fc576c3239. --- .../emi/emi/jemi/impl/JemiIngredientAcceptor.java | 6 ------ .../emi/emi/jemi/impl/JemiRecipeLayoutBuilder.java | 5 ----- .../java/dev/emi/emi/jemi/impl/JemiRecipeSlot.java | 12 ------------ .../dev/emi/emi/jemi/impl/JemiRecipeSlotBuilder.java | 3 +-- .../java/dev/emi/emi/jemi/widget/JemiSlotWidget.java | 4 +--- 5 files changed, 2 insertions(+), 28 deletions(-) diff --git a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiIngredientAcceptor.java b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiIngredientAcceptor.java index 799c322d..3c336617 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiIngredientAcceptor.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiIngredientAcceptor.java @@ -14,7 +14,6 @@ import dev.emi.emi.EmiPort; import dev.emi.emi.api.stack.EmiIngredient; import dev.emi.emi.api.stack.EmiStack; -import dev.emi.emi.config.FluidUnit; import dev.emi.emi.jemi.JemiStack; import dev.emi.emi.jemi.JemiUtil; import dev.emi.emi.jemi.impl.JemiRecipeSlot.IngredientRenderer; @@ -108,11 +107,6 @@ public JemiIngredientAcceptor addIngredientsUnsafe(List ingredients) { return this; } - @Override - public JemiIngredientAcceptor addFluidStack(Fluid fluid) { - return addFluidStack(fluid, FluidUnit.BUCKET); - } - @Override public JemiIngredientAcceptor addFluidStack(Fluid fluid, long amount) { addStack(EmiStack.of(fluid, amount)); diff --git a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeLayoutBuilder.java b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeLayoutBuilder.java index 559c8a04..c6c3d9a6 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeLayoutBuilder.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeLayoutBuilder.java @@ -14,11 +14,6 @@ public class JemiRecipeLayoutBuilder implements IRecipeLayoutBuilder { public final List slots = Lists.newArrayList(); public boolean shapeless = false; - @Override - public IRecipeSlotBuilder addSlot(RecipeIngredientRole role) { - return addSlot(role, 0, 0); - } - @Override public IRecipeSlotBuilder addSlot(RecipeIngredientRole recipeIngredientRole, int x, int y) { JemiRecipeSlotBuilder builder = new JemiRecipeSlotBuilder(recipeIngredientRole, x, y); diff --git a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlot.java b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlot.java index 1587d9a6..b3ea3e40 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlot.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlot.java @@ -1,13 +1,9 @@ package dev.emi.emi.jemi.impl; -import java.util.List; import java.util.Map; import java.util.Optional; import java.util.stream.Stream; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.annotations.Unmodifiable; - import dev.emi.emi.api.stack.EmiIngredient; import dev.emi.emi.api.stack.EmiStack; import dev.emi.emi.api.widget.SlotWidget; @@ -24,7 +20,6 @@ @SuppressWarnings("unchecked") public class JemiRecipeSlot implements IRecipeSlotView { public final RecipeIngredientRole role; - public final boolean large; public final int x, y; public final Optional name; public final IRecipeSlotTooltipCallback tooltipCallback; @@ -37,7 +32,6 @@ public class JemiRecipeSlot implements IRecipeSlotView { public JemiRecipeSlot(JemiRecipeSlotBuilder builder) { this.role = builder.acceptor.role; - this.large = builder.large; this.x = builder.x; this.y = builder.y; this.name = builder.name; @@ -51,7 +45,6 @@ public JemiRecipeSlot(JemiRecipeSlotBuilder builder) { public JemiRecipeSlot(RecipeIngredientRole role, EmiStack stack) { this.role = role; - this.large = false; this.x = 0; this.y = 0; this.name = Optional.empty(); @@ -68,11 +61,6 @@ public Stream getIngredients(IIngredientType ingredientType) { return (Stream) getAllIngredients().filter(t -> t.getType() == ingredientType).map(t -> t.getIngredient()); } - @Override - public @Unmodifiable List<@Nullable ITypedIngredient> getAllIngredientsList() { - return getAllIngredients().toList(); - } - @Override public Stream> getAllIngredients() { return stack.getEmiStacks().stream().map(JemiUtil::getTyped).filter(Optional::isPresent).map(Optional::get); diff --git a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlotBuilder.java b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlotBuilder.java index c9b58d55..7ed2a816 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlotBuilder.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlotBuilder.java @@ -22,8 +22,7 @@ public class JemiRecipeSlotBuilder implements IRecipeSlotBuilder { public final JemiIngredientAcceptor acceptor; - public boolean large = false; - public int x, y; + public final int x, y; public Optional name = Optional.empty(); public IRecipeSlotTooltipCallback tooltipCallback; public OffsetDrawable background, overlay; diff --git a/xplat/src/main/java/dev/emi/emi/jemi/widget/JemiSlotWidget.java b/xplat/src/main/java/dev/emi/emi/jemi/widget/JemiSlotWidget.java index 3cee87ad..4afd516d 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/widget/JemiSlotWidget.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/widget/JemiSlotWidget.java @@ -28,7 +28,7 @@ public class JemiSlotWidget extends SlotWidget { private final JemiRecipeSlot slot; public JemiSlotWidget(JemiRecipeSlot slot, EmiRecipe recipe) { - super(slot.stack, slot.x - (slot.large ? 6 : 1) , slot.y - (slot.large ? 6 : 1)); + super(slot.stack, slot.x - 1, slot.y - 1); this.slot = slot; slot.widget = this; if (slot.getRole() == RecipeIngredientRole.OUTPUT) { @@ -38,8 +38,6 @@ public JemiSlotWidget(JemiRecipeSlot slot, EmiRecipe recipe) { IIngredientRenderer renderer = getRenderer(); if (renderer != null) { this.customBackground(null, 0, 0, renderer.getWidth() + 2, renderer.getHeight() + 2); - } else if (slot.large) { - this.large(true); } } From 962ae266d0bf645e397fe7cc983b96621844eeee Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Sun, 6 Oct 2024 23:49:21 -0500 Subject: [PATCH 53/67] Revert "Revert "Update JEMI integration"" This reverts commit 50c14113af5c2aa4a377c594203053c17fac5ba4. --- .../emi/emi/jemi/impl/JemiIngredientAcceptor.java | 6 ++++++ .../emi/emi/jemi/impl/JemiRecipeLayoutBuilder.java | 5 +++++ .../java/dev/emi/emi/jemi/impl/JemiRecipeSlot.java | 12 ++++++++++++ .../dev/emi/emi/jemi/impl/JemiRecipeSlotBuilder.java | 3 ++- .../java/dev/emi/emi/jemi/widget/JemiSlotWidget.java | 4 +++- 5 files changed, 28 insertions(+), 2 deletions(-) diff --git a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiIngredientAcceptor.java b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiIngredientAcceptor.java index 39f9b05e..f3b0635a 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiIngredientAcceptor.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiIngredientAcceptor.java @@ -13,6 +13,7 @@ import dev.emi.emi.EmiPort; import dev.emi.emi.api.stack.EmiIngredient; import dev.emi.emi.api.stack.EmiStack; +import dev.emi.emi.config.FluidUnit; import dev.emi.emi.jemi.JemiStack; import dev.emi.emi.jemi.JemiUtil; import dev.emi.emi.jemi.impl.JemiRecipeSlot.IngredientRenderer; @@ -107,6 +108,11 @@ public JemiIngredientAcceptor addIngredientsUnsafe(List ingredients) { return this; } + @Override + public JemiIngredientAcceptor addFluidStack(Fluid fluid) { + return addFluidStack(fluid, FluidUnit.BUCKET); + } + @Override public JemiIngredientAcceptor addFluidStack(Fluid fluid, long amount) { addStack(EmiStack.of(fluid, amount)); diff --git a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeLayoutBuilder.java b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeLayoutBuilder.java index 39757efa..f31b6cff 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeLayoutBuilder.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeLayoutBuilder.java @@ -15,6 +15,11 @@ public class JemiRecipeLayoutBuilder implements IRecipeLayoutBuilder { public final List slots = Lists.newArrayList(); public boolean shapeless = false; + @Override + public IRecipeSlotBuilder addSlot(RecipeIngredientRole role) { + return addSlot(role, 0, 0); + } + @Override public IRecipeSlotBuilder addSlot(RecipeIngredientRole recipeIngredientRole, int x, int y) { JemiRecipeSlotBuilder builder = new JemiRecipeSlotBuilder(recipeIngredientRole, x, y); diff --git a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlot.java b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlot.java index 982ee70b..09d86414 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlot.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlot.java @@ -1,9 +1,13 @@ package dev.emi.emi.jemi.impl; +import java.util.List; import java.util.Map; import java.util.Optional; import java.util.stream.Stream; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.Unmodifiable; + import dev.emi.emi.api.stack.EmiIngredient; import dev.emi.emi.api.stack.EmiStack; import dev.emi.emi.api.widget.SlotWidget; @@ -21,6 +25,7 @@ @SuppressWarnings("unchecked") public class JemiRecipeSlot implements IRecipeSlotView { public final RecipeIngredientRole role; + public final boolean large; public final int x, y; public final Optional name; public final IRecipeSlotTooltipCallback tooltipCallback; @@ -34,6 +39,7 @@ public class JemiRecipeSlot implements IRecipeSlotView { public JemiRecipeSlot(JemiRecipeSlotBuilder builder) { this.role = builder.acceptor.role; + this.large = builder.large; this.x = builder.x; this.y = builder.y; this.name = builder.name; @@ -48,6 +54,7 @@ public JemiRecipeSlot(JemiRecipeSlotBuilder builder) { public JemiRecipeSlot(RecipeIngredientRole role, EmiStack stack) { this.role = role; + this.large = false; this.x = 0; this.y = 0; this.name = Optional.empty(); @@ -65,6 +72,11 @@ public Stream getIngredients(IIngredientType ingredientType) { return (Stream) getAllIngredients().filter(t -> t.getType() == ingredientType).map(t -> t.getIngredient()); } + @Override + public @Unmodifiable List<@Nullable ITypedIngredient> getAllIngredientsList() { + return getAllIngredients().toList(); + } + @Override public Stream> getAllIngredients() { return stack.getEmiStacks().stream().map(JemiUtil::getTyped).filter(Optional::isPresent).map(Optional::get); diff --git a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlotBuilder.java b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlotBuilder.java index a913de23..1d03c85e 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlotBuilder.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlotBuilder.java @@ -24,7 +24,8 @@ public class JemiRecipeSlotBuilder implements IRecipeSlotBuilder { public final JemiIngredientAcceptor acceptor; - public final int x, y; + public boolean large = false; + public int x, y; public Optional name = Optional.empty(); public IRecipeSlotTooltipCallback tooltipCallback; public IRecipeSlotRichTooltipCallback richTooltipCallback; diff --git a/xplat/src/main/java/dev/emi/emi/jemi/widget/JemiSlotWidget.java b/xplat/src/main/java/dev/emi/emi/jemi/widget/JemiSlotWidget.java index ef2270c3..749429ab 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/widget/JemiSlotWidget.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/widget/JemiSlotWidget.java @@ -29,7 +29,7 @@ public class JemiSlotWidget extends SlotWidget { private final JemiRecipeSlot slot; public JemiSlotWidget(JemiRecipeSlot slot, EmiRecipe recipe) { - super(slot.stack, slot.x - 1, slot.y - 1); + super(slot.stack, slot.x - (slot.large ? 6 : 1) , slot.y - (slot.large ? 6 : 1)); this.slot = slot; slot.widget = this; if (slot.getRole() == RecipeIngredientRole.OUTPUT) { @@ -39,6 +39,8 @@ public JemiSlotWidget(JemiRecipeSlot slot, EmiRecipe recipe) { IIngredientRenderer renderer = getRenderer(); if (renderer != null) { this.customBackground(null, 0, 0, renderer.getWidth() + 2, renderer.getHeight() + 2); + } else if (slot.large) { + this.large(true); } } From 335505305fee3bd3ed5ca947e25fd37b56f545df Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Sun, 6 Oct 2024 23:52:05 -0500 Subject: [PATCH 54/67] Update loom --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 233b68a2..aedd7e82 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ plugins { id "architectury-plugin" version "3.4-SNAPSHOT" - id "dev.architectury.loom" version "1.4-SNAPSHOT" apply false + id "dev.architectury.loom" version "1.7-SNAPSHOT" apply false } architectury { From 52fe89d353aed10b76ec0f2d95ae8161356b2eb3 Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Sun, 6 Oct 2024 23:56:40 -0500 Subject: [PATCH 55/67] Update gradle --- gradle/wrapper/gradle-wrapper.jar | Bin 59536 -> 43462 bytes gradle/wrapper/gradle-wrapper.properties | 4 ++- gradlew | 41 ++++++++++++++++------- gradlew.bat | 35 ++++++++++--------- 4 files changed, 50 insertions(+), 30 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7454180f2ae8848c63b8b4dea2cb829da983f2fa..d64cd4917707c1f8861d8cb53dd15194d4248596 100644 GIT binary patch literal 43462 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 literal 59536 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 QuEJmfE|#`Dqx|px0L@K;Y5)KL diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a5952066..a4413138 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 1b6c7873..1aa94a42 100755 --- a/gradlew +++ b/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -80,13 +80,11 @@ do esac done -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" +# This is normally unused +# shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -133,22 +131,29 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -193,11 +198,15 @@ if "$cygwin" || "$msys" ; then done fi -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ @@ -205,6 +214,12 @@ set -- \ org.gradle.wrapper.GradleWrapperMain \ "$@" +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. diff --git a/gradlew.bat b/gradlew.bat index ac1b06f9..7101f8e4 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +25,8 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,13 +41,13 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute +if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -56,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal From 91a3542683e6b641a61c589a61499913b7a031e5 Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Mon, 7 Oct 2024 00:02:36 -0500 Subject: [PATCH 56/67] Bump neo version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 8a66c997..3c09c0dc 100644 --- a/gradle.properties +++ b/gradle.properties @@ -16,6 +16,6 @@ fabric_api_version=0.91.3+1.20.4 forge_version=1.20.4-49.0.9 -neoforge_version=20.4.190 +neoforge_version=20.4.237 jei_version=jei-1.20.4-fabric:17.3.0.49 From 720defb37d2e5936d88551aa8cd6f45d73cbe928 Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Mon, 7 Oct 2024 00:15:48 -0500 Subject: [PATCH 57/67] 1.20 JEMI tweaks --- .../java/dev/emi/emi/jemi/impl/JemiIngredientAcceptor.java | 5 ----- .../java/dev/emi/emi/jemi/impl/JemiRecipeLayoutBuilder.java | 4 ---- .../src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlot.java | 5 ----- 3 files changed, 14 deletions(-) diff --git a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiIngredientAcceptor.java b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiIngredientAcceptor.java index f3b0635a..50fe91d5 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiIngredientAcceptor.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiIngredientAcceptor.java @@ -108,11 +108,6 @@ public JemiIngredientAcceptor addIngredientsUnsafe(List ingredients) { return this; } - @Override - public JemiIngredientAcceptor addFluidStack(Fluid fluid) { - return addFluidStack(fluid, FluidUnit.BUCKET); - } - @Override public JemiIngredientAcceptor addFluidStack(Fluid fluid, long amount) { addStack(EmiStack.of(fluid, amount)); diff --git a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeLayoutBuilder.java b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeLayoutBuilder.java index f31b6cff..d30a2efb 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeLayoutBuilder.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeLayoutBuilder.java @@ -15,10 +15,6 @@ public class JemiRecipeLayoutBuilder implements IRecipeLayoutBuilder { public final List slots = Lists.newArrayList(); public boolean shapeless = false; - @Override - public IRecipeSlotBuilder addSlot(RecipeIngredientRole role) { - return addSlot(role, 0, 0); - } @Override public IRecipeSlotBuilder addSlot(RecipeIngredientRole recipeIngredientRole, int x, int y) { diff --git a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlot.java b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlot.java index 09d86414..3a6bfc68 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlot.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlot.java @@ -72,11 +72,6 @@ public Stream getIngredients(IIngredientType ingredientType) { return (Stream) getAllIngredients().filter(t -> t.getType() == ingredientType).map(t -> t.getIngredient()); } - @Override - public @Unmodifiable List<@Nullable ITypedIngredient> getAllIngredientsList() { - return getAllIngredients().toList(); - } - @Override public Stream> getAllIngredients() { return stack.getEmiStacks().stream().map(JemiUtil::getTyped).filter(Optional::isPresent).map(Optional::get); From a74229c292441a580c737f96614b3a424f0d6359 Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Mon, 7 Oct 2024 00:16:45 -0500 Subject: [PATCH 58/67] Revert "Revert "Revert "Update JEMI integration""" This reverts commit 962ae266d0bf645e397fe7cc983b96621844eeee. --- .../java/dev/emi/emi/jemi/impl/JemiIngredientAcceptor.java | 1 - .../dev/emi/emi/jemi/impl/JemiRecipeLayoutBuilder.java | 1 - .../main/java/dev/emi/emi/jemi/impl/JemiRecipeSlot.java | 7 ------- .../java/dev/emi/emi/jemi/impl/JemiRecipeSlotBuilder.java | 3 +-- .../main/java/dev/emi/emi/jemi/widget/JemiSlotWidget.java | 4 +--- 5 files changed, 2 insertions(+), 14 deletions(-) diff --git a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiIngredientAcceptor.java b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiIngredientAcceptor.java index 0e7c3563..7804a0f1 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiIngredientAcceptor.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiIngredientAcceptor.java @@ -12,7 +12,6 @@ import dev.emi.emi.EmiPort; import dev.emi.emi.api.stack.EmiIngredient; import dev.emi.emi.api.stack.EmiStack; -import dev.emi.emi.config.FluidUnit; import dev.emi.emi.jemi.JemiStack; import dev.emi.emi.jemi.JemiUtil; import dev.emi.emi.jemi.impl.JemiRecipeSlot.IngredientRenderer; diff --git a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeLayoutBuilder.java b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeLayoutBuilder.java index e6075bc9..c6c3d9a6 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeLayoutBuilder.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeLayoutBuilder.java @@ -14,7 +14,6 @@ public class JemiRecipeLayoutBuilder implements IRecipeLayoutBuilder { public final List slots = Lists.newArrayList(); public boolean shapeless = false; - @Override public IRecipeSlotBuilder addSlot(RecipeIngredientRole recipeIngredientRole, int x, int y) { JemiRecipeSlotBuilder builder = new JemiRecipeSlotBuilder(recipeIngredientRole, x, y); diff --git a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlot.java b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlot.java index edac4bd7..60882f8c 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlot.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlot.java @@ -1,13 +1,9 @@ package dev.emi.emi.jemi.impl; -import java.util.List; import java.util.Map; import java.util.Optional; import java.util.stream.Stream; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.annotations.Unmodifiable; - import dev.emi.emi.api.stack.EmiIngredient; import dev.emi.emi.api.stack.EmiStack; import dev.emi.emi.api.widget.SlotWidget; @@ -24,7 +20,6 @@ @SuppressWarnings("unchecked") public class JemiRecipeSlot implements IRecipeSlotView { public final RecipeIngredientRole role; - public final boolean large; public final int x, y; public final Optional name; public final IRecipeSlotTooltipCallback tooltipCallback; @@ -37,7 +32,6 @@ public class JemiRecipeSlot implements IRecipeSlotView { public JemiRecipeSlot(JemiRecipeSlotBuilder builder) { this.role = builder.acceptor.role; - this.large = builder.large; this.x = builder.x; this.y = builder.y; this.name = builder.name; @@ -51,7 +45,6 @@ public JemiRecipeSlot(JemiRecipeSlotBuilder builder) { public JemiRecipeSlot(RecipeIngredientRole role, EmiStack stack) { this.role = role; - this.large = false; this.x = 0; this.y = 0; this.name = Optional.empty(); diff --git a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlotBuilder.java b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlotBuilder.java index 51b36ea3..4592bcd1 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlotBuilder.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlotBuilder.java @@ -22,8 +22,7 @@ public class JemiRecipeSlotBuilder implements IRecipeSlotBuilder { public final JemiIngredientAcceptor acceptor; - public boolean large = false; - public int x, y; + public final int x, y; public Optional name = Optional.empty(); public IRecipeSlotTooltipCallback tooltipCallback; public OffsetDrawable background, overlay; diff --git a/xplat/src/main/java/dev/emi/emi/jemi/widget/JemiSlotWidget.java b/xplat/src/main/java/dev/emi/emi/jemi/widget/JemiSlotWidget.java index 2f10f786..39105018 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/widget/JemiSlotWidget.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/widget/JemiSlotWidget.java @@ -28,7 +28,7 @@ public class JemiSlotWidget extends SlotWidget { private final JemiRecipeSlot slot; public JemiSlotWidget(JemiRecipeSlot slot, EmiRecipe recipe) { - super(slot.stack, slot.x - (slot.large ? 6 : 1) , slot.y - (slot.large ? 6 : 1)); + super(slot.stack, slot.x - 1, slot.y - 1); this.slot = slot; slot.widget = this; if (slot.getRole() == RecipeIngredientRole.OUTPUT) { @@ -38,8 +38,6 @@ public JemiSlotWidget(JemiRecipeSlot slot, EmiRecipe recipe) { IIngredientRenderer renderer = getRenderer(); if (renderer != null) { this.customBackground(null, 0, 0, renderer.getWidth() + 2, renderer.getHeight() + 2); - } else if (slot.large) { - this.large(true); } } From 7524b5f9616b6adec28ea0a3a391ae86b0c87b82 Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Mon, 7 Oct 2024 17:37:30 -0500 Subject: [PATCH 59/67] Backport JEI fixes to 1.20.1 --- gradle.properties | 2 +- .../emi/jemi/impl/JemiIngredientAcceptor.java | 6 ++++ .../jemi/impl/JemiRecipeLayoutBuilder.java | 4 +++ .../emi/jemi/impl/JemiRecipeSlotBuilder.java | 35 +++++++++++++++++++ 4 files changed, 46 insertions(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index c6cef783..9f051498 100644 --- a/gradle.properties +++ b/gradle.properties @@ -16,4 +16,4 @@ fabric_api_version=0.83.1+1.20.1 forge_version=1.20.1-47.0.1 -jei_version=jei-1.20.1-fabric:15.12.3.53 +jei_version=jei-1.20.1-fabric:15.20.0.102 diff --git a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiIngredientAcceptor.java b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiIngredientAcceptor.java index 50fe91d5..c5765dd7 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiIngredientAcceptor.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiIngredientAcceptor.java @@ -108,6 +108,12 @@ public JemiIngredientAcceptor addIngredientsUnsafe(List ingredients) { return this; } + @Override + public JemiIngredientAcceptor addFluidStack(Fluid fluid) { + addStack(EmiStack.of(fluid)); + return this; + } + @Override public JemiIngredientAcceptor addFluidStack(Fluid fluid, long amount) { addStack(EmiStack.of(fluid, amount)); diff --git a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeLayoutBuilder.java b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeLayoutBuilder.java index d30a2efb..f31b6cff 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeLayoutBuilder.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeLayoutBuilder.java @@ -15,6 +15,10 @@ public class JemiRecipeLayoutBuilder implements IRecipeLayoutBuilder { public final List slots = Lists.newArrayList(); public boolean shapeless = false; + @Override + public IRecipeSlotBuilder addSlot(RecipeIngredientRole role) { + return addSlot(role, 0, 0); + } @Override public IRecipeSlotBuilder addSlot(RecipeIngredientRole recipeIngredientRole, int x, int y) { diff --git a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlotBuilder.java b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlotBuilder.java index 1d03c85e..51deecc6 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlotBuilder.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlotBuilder.java @@ -57,6 +57,12 @@ public IRecipeSlotBuilder addIngredientsUnsafe(List ingredients) { return this; } + @Override + public IRecipeSlotBuilder addFluidStack(Fluid fluid) { + acceptor.addFluidStack(fluid); + return this; + } + @Override public IRecipeSlotBuilder addFluidStack(Fluid fluid, long amount) { acceptor.addFluidStack(fluid, amount); @@ -126,4 +132,33 @@ public IRecipeSlotBuilder addRichTooltipCallback(IRecipeSlotRichTooltipCallback richTooltipCallback = tooltipCallback; return this; } + + @Override + public IRecipeSlotBuilder setPosition(int xPos, int yPos) { + this.x = xPos; + this.y = yPos; + return this; + } + + @Override + public int getWidth() { + return large ? 26 : 18; + } + + @Override + public int getHeight() { + return large ? 26 : 18; + } + + @Override + public IRecipeSlotBuilder setStandardSlotBackground() { + large = false; + return this; + } + + @Override + public IRecipeSlotBuilder setOutputSlotBackground() { + large = true; + return this; + } } From d16ca3a96f5d92d24a0737e3007785c31c11d2ed Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Mon, 7 Oct 2024 17:59:48 -0500 Subject: [PATCH 60/67] Revert "Backport JEI fixes to 1.20.1" This reverts commit 7524b5f9616b6adec28ea0a3a391ae86b0c87b82. --- .../java/dev/emi/emi/jemi/impl/JemiIngredientAcceptor.java | 6 ------ .../java/dev/emi/emi/jemi/impl/JemiRecipeSlotBuilder.java | 6 ------ 2 files changed, 12 deletions(-) diff --git a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiIngredientAcceptor.java b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiIngredientAcceptor.java index ae75e0ad..7804a0f1 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiIngredientAcceptor.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiIngredientAcceptor.java @@ -106,12 +106,6 @@ public JemiIngredientAcceptor addIngredientsUnsafe(List ingredients) { return this; } - @Override - public JemiIngredientAcceptor addFluidStack(Fluid fluid) { - addStack(EmiStack.of(fluid)); - return this; - } - @Override public JemiIngredientAcceptor addFluidStack(Fluid fluid, long amount) { addStack(EmiStack.of(fluid, amount)); diff --git a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlotBuilder.java b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlotBuilder.java index d89bfb56..4592bcd1 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlotBuilder.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/impl/JemiRecipeSlotBuilder.java @@ -53,12 +53,6 @@ public IRecipeSlotBuilder addIngredientsUnsafe(List ingredients) { return this; } - @Override - public IRecipeSlotBuilder addFluidStack(Fluid fluid) { - acceptor.addFluidStack(fluid); - return this; - } - @Override public IRecipeSlotBuilder addFluidStack(Fluid fluid, long amount) { acceptor.addFluidStack(fluid, amount); From b08ccd5444576e2e2ea1a3d01dbcecb7a7bec4fd Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Mon, 14 Oct 2024 17:26:06 -0500 Subject: [PATCH 61/67] Add JEI version dependency for 1.20.1 beta --- forge/src/main/resources/META-INF/mods.toml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/forge/src/main/resources/META-INF/mods.toml b/forge/src/main/resources/META-INF/mods.toml index a6f35461..d924ec63 100644 --- a/forge/src/main/resources/META-INF/mods.toml +++ b/forge/src/main/resources/META-INF/mods.toml @@ -11,4 +11,11 @@ authors = "Emi" description = ''' A featureful and accessible item and recipe viewer ''' -logoFile = "icon.png" \ No newline at end of file +logoFile = "icon.png" + +[[dependencies.emi]] +modId = "jei" +mandatory = false +versionRange = "[15.20.0.0,)" +ordering = "BEFORE" +side = "CLIENT" \ No newline at end of file From 35a9924759395648ce5ac4359ed4241337b79ff1 Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Thu, 31 Oct 2024 21:51:44 -0500 Subject: [PATCH 62/67] Revert "Update config UI to use modern look (#757)" This reverts commit 9c3765ae9907326de20684e0c9890ae6f9e8a245. --- xplat/src/main/java/dev/emi/emi/screen/ConfigScreen.java | 6 ++++++ .../emi/emi/screen/widget/config/ConfigJumpButton.java | 3 --- .../java/dev/emi/emi/screen/widget/config/ListWidget.java | 8 +------- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/xplat/src/main/java/dev/emi/emi/screen/ConfigScreen.java b/xplat/src/main/java/dev/emi/emi/screen/ConfigScreen.java index d8823204..1f6da065 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/ConfigScreen.java +++ b/xplat/src/main/java/dev/emi/emi/screen/ConfigScreen.java @@ -370,11 +370,17 @@ public void render(DrawContext raw, int mouseX, int mouseY, float delta) { list.render(context.raw(), mouseX, mouseY, delta); super.render(context.raw(), mouseX, mouseY, delta); list.render(context.raw(), mouseX, mouseY, delta); + super.render(context.raw(), mouseX, mouseY, delta); if (list.getHoveredEntry() != null) { EmiRenderHelper.drawTooltip(this, context, list.getHoveredEntry().getTooltip(mouseX, mouseY), mouseX, mouseY, Math.min(width / 2 - 16, maxWidth)); } } + @Override + public void renderBackground(DrawContext context, int mouseX, int mouseY, float delta) { + // Prevent double background draw + } + @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { if (activeBind != null) { diff --git a/xplat/src/main/java/dev/emi/emi/screen/widget/config/ConfigJumpButton.java b/xplat/src/main/java/dev/emi/emi/screen/widget/config/ConfigJumpButton.java index c6e5e941..bfd45560 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/widget/config/ConfigJumpButton.java +++ b/xplat/src/main/java/dev/emi/emi/screen/widget/config/ConfigJumpButton.java @@ -26,10 +26,7 @@ public void renderWidget(DrawContext raw, int mouseX, int mouseY, float delta) { if (this.isMouseOver(mouseX, mouseY)) { context.setColor(0.5f, 0.6f, 1f); } - context.push(); - context.matrices().translate(0, 0, 100); super.renderWidget(raw, mouseX, mouseY, delta); - context.pop(); context.resetColor(); } } diff --git a/xplat/src/main/java/dev/emi/emi/screen/widget/config/ListWidget.java b/xplat/src/main/java/dev/emi/emi/screen/widget/config/ListWidget.java index 37a487d1..e922ff4b 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/widget/config/ListWidget.java +++ b/xplat/src/main/java/dev/emi/emi/screen/widget/config/ListWidget.java @@ -5,7 +5,6 @@ import java.util.Objects; import java.util.function.Predicate; -import net.minecraft.util.Identifier; import org.jetbrains.annotations.Nullable; import com.google.common.collect.Lists; @@ -37,9 +36,6 @@ * This is the lesser of two evils, at least this way I have vanilla compat. */ public class ListWidget extends AbstractParentElement implements Drawable, Selectable { - private static final Identifier MENU_LIST_BACKGROUND_TEXTURE = EmiPort.id("minecraft", "textures/gui/menu_list_background.png"); - private static final Identifier INWORLD_MENU_LIST_BACKGROUND_TEXTURE = EmiPort.id("minecraft", "textures/gui/inworld_menu_list_background.png"); - protected final MinecraftClient client; private final List children = Lists.newArrayList(); protected int width; @@ -189,12 +185,10 @@ public void render(DrawContext draw, int mouseX, int mouseY, float delta) { .next(); tessellator.draw(); } - - draw.enableScissor(left, top, right, bottom); + int k = this.getRowLeft(); int l = this.top + 4 - (int)this.getScrollAmount(); this.renderList(draw, k, l, mouseX, mouseY, delta); - draw.disableScissor(); { // Render horizontal shadows From 1ecdac47b2297851408f87c081786a852f3266ae Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Thu, 31 Oct 2024 22:17:54 -0500 Subject: [PATCH 63/67] Adjust recipe id checking --- xplat/src/main/java/dev/emi/emi/registry/EmiRecipes.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/xplat/src/main/java/dev/emi/emi/registry/EmiRecipes.java b/xplat/src/main/java/dev/emi/emi/registry/EmiRecipes.java index eaaeead7..8ac7628c 100644 --- a/xplat/src/main/java/dev/emi/emi/registry/EmiRecipes.java +++ b/xplat/src/main/java/dev/emi/emi/registry/EmiRecipes.java @@ -36,6 +36,7 @@ import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap; import it.unimi.dsi.fastutil.objects.ObjectArraySet; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.resource.language.I18n; import net.minecraft.util.Identifier; @@ -164,7 +165,8 @@ public Manager(List categories, Map Date: Sun, 3 Nov 2024 14:01:06 -0600 Subject: [PATCH 64/67] Revert "Update config enum screen to be consistent with config screen" This reverts commit af59b089b8b71d0f76770696769b24e4737602ad. --- .../src/main/java/dev/emi/emi/screen/ConfigEnumScreen.java | 6 +++++- xplat/src/main/java/dev/emi/emi/screen/ConfigScreen.java | 2 -- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/xplat/src/main/java/dev/emi/emi/screen/ConfigEnumScreen.java b/xplat/src/main/java/dev/emi/emi/screen/ConfigEnumScreen.java index ec8e4803..c894bf99 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/ConfigEnumScreen.java +++ b/xplat/src/main/java/dev/emi/emi/screen/ConfigEnumScreen.java @@ -54,7 +54,6 @@ public void render(DrawContext raw, int mouseX, int mouseY, float delta) { this.renderBackgroundTexture(context.raw()); list.render(context.raw(), mouseX, mouseY, delta); super.render(context.raw(), mouseX, mouseY, delta); - list.render(context.raw(), mouseX, mouseY, delta); ListWidget.Entry entry = list.getHoveredEntry(); if (entry instanceof SelectionWidget widget) { if (widget.button.isHovered()) { @@ -63,6 +62,11 @@ public void render(DrawContext raw, int mouseX, int mouseY, float delta) { } } + @Override + public void renderBackground(DrawContext context, int mouseX, int mouseY, float delta) { + // Prevent double background draw + } + @Override public void close() { MinecraftClient.getInstance().setScreen(last); diff --git a/xplat/src/main/java/dev/emi/emi/screen/ConfigScreen.java b/xplat/src/main/java/dev/emi/emi/screen/ConfigScreen.java index 1f6da065..de776c98 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/ConfigScreen.java +++ b/xplat/src/main/java/dev/emi/emi/screen/ConfigScreen.java @@ -369,8 +369,6 @@ public void render(DrawContext raw, int mouseX, int mouseY, float delta) { this.renderBackgroundTexture(context.raw()); list.render(context.raw(), mouseX, mouseY, delta); super.render(context.raw(), mouseX, mouseY, delta); - list.render(context.raw(), mouseX, mouseY, delta); - super.render(context.raw(), mouseX, mouseY, delta); if (list.getHoveredEntry() != null) { EmiRenderHelper.drawTooltip(this, context, list.getHoveredEntry().getTooltip(mouseX, mouseY), mouseX, mouseY, Math.min(width / 2 - 16, maxWidth)); } From e26b4baf4ec85c845cd821f69ff93ec90761f091 Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Sun, 3 Nov 2024 14:03:20 -0600 Subject: [PATCH 65/67] Revert "Add JEI version dependency for 1.20.1 beta" This reverts commit b08ccd5444576e2e2ea1a3d01dbcecb7a7bec4fd. --- forge/src/main/resources/META-INF/mods.toml | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/forge/src/main/resources/META-INF/mods.toml b/forge/src/main/resources/META-INF/mods.toml index d924ec63..a6f35461 100644 --- a/forge/src/main/resources/META-INF/mods.toml +++ b/forge/src/main/resources/META-INF/mods.toml @@ -11,11 +11,4 @@ authors = "Emi" description = ''' A featureful and accessible item and recipe viewer ''' -logoFile = "icon.png" - -[[dependencies.emi]] -modId = "jei" -mandatory = false -versionRange = "[15.20.0.0,)" -ordering = "BEFORE" -side = "CLIENT" \ No newline at end of file +logoFile = "icon.png" \ No newline at end of file From a39b8d5158201762325ab102ad02db6b37d753b3 Mon Sep 17 00:00:00 2001 From: Santiago Hernandez <73335686+TheLegendofSaram@users.noreply.github.com> Date: Thu, 13 Mar 2025 02:50:47 -0300 Subject: [PATCH 66/67] Mexican Spanish Translation (#883) * Mexican Spanish Translation Just a translation for your mod * Update es_mx.json --- .../main/resources/assets/emi/lang/es_mx.json | 809 ++++++++++++++++++ 1 file changed, 809 insertions(+) create mode 100644 xplat/src/main/resources/assets/emi/lang/es_mx.json diff --git a/xplat/src/main/resources/assets/emi/lang/es_mx.json b/xplat/src/main/resources/assets/emi/lang/es_mx.json new file mode 100644 index 00000000..fa6b14c2 --- /dev/null +++ b/xplat/src/main/resources/assets/emi/lang/es_mx.json @@ -0,0 +1,809 @@ +{ + "key.keyboard.control": "Ctrl", + "key.keyboard.alt": "Alt", + "key.keyboard.shift": "Mayús", + + "key.emi.toggle_visibility": "Alternar Visibilidad", + "config.emi.tooltip.binds.toggle_visibility": "Permite ocultar o mostrar EMI", + "key.emi.focus_search": "Enfocar Búsqueda", + "config.emi.tooltip.binds.focus_search": "Coloca tu cursor\nen la barra de búsqueda", + "key.emi.clear_search": "Limpiar Búsqueda", + "config.emi.tooltip.binds.clear_search": "Permite vaciar\nla barra de búsqueda", + "key.emi.view_recipes": "Ver Recetas", + "config.emi.tooltip.binds.view_recipes": "Muestra la lista de recetas", + "key.emi.view_uses": "Ver Usos", + "config.emi.tooltip.binds.view_uses": "Muestra la lista de usos", + "key.emi.favorite": "Favorito", + "config.emi.tooltip.binds.favorite": "Marcar como favorito", + "key.emi.set_default": "Establecer por Defecto", + "config.emi.tooltip.binds.set_default": "Establecer como receta por defecto", + "key.emi.default_stack": "Pila por Defecto", + "key.emi.view_stack_tree": "Ver Árbol de Pilas", + "config.emi.tooltip.binds.view_stack_tree": "Permite ver el gráfico\nde un objeto específico", + "key.emi.view_tree": "Ver Árbol", + "config.emi.tooltip.binds.view_tree": "Permite ver el gráfico activo", + "key.emi.back": "Atrás", + "config.emi.tooltip.binds.back": "Permite retroceder\nuna página", + "key.emi.forward": "Adelante", + "key.emi.craft_one": "Fabricar Uno", + "config.emi.tooltip.binds.craft_one": "Coloca los ingredientes\npara fabricar un objeto", + "key.emi.craft_all": "Fabricar Todo", + "config.emi.tooltip.binds.craft_all": "Coloca los ingredientes\npara fabricar todos los objetos", + "key.emi.craft_one_to_inventory": "Fabricar Uno al Inventario", + "config.emi.tooltip.binds.craft_one_to_inventory": "Fabrica un objeto", + "key.emi.craft_all_to_inventory": "Fabricar Todo al Inventario", + "config.emi.tooltip.binds.craft_all_to_inventory": "Fabrica todos los objetos", + "key.emi.craft_one_to_cursor": "Fabricar Uno al Cursor", + "config.emi.tooltip.binds.craft_one_to_cursor": "Fabrica un objeto\ny lo coloca en tu cursor", + "key.emi.show_craft": "Mostrar Fabricación", + "config.emi.tooltip.binds.show_craft": "Muestra la receta que se utilizaría", + "key.emi.cheat_one_to_inventory": "Hacer Trampa: Uno al Inventario", + "config.emi.tooltip.binds.cheat_one_to_inventory": "Crea un objeto", + "key.emi.cheat_stack_to_inventory": "Hacer Trampa: Pila al Inventario", + "config.emi.tooltip.binds.cheat_stack_to_inventory": "Crea una pila de este objeto", + "key.emi.cheat_one_to_cursor": "Hacer Trampa: Uno al Cursor", + "config.emi.tooltip.binds.cheat_one_to_cursor": "Crea un objeto\ny lo coloca en tu cursor", + "key.emi.cheat_stack_to_cursor": "Hacer Trampa: Pila al Cursor", + "config.emi.tooltip.binds.cheat_stack_to_cursor": "Crea una pila de este objeto\ny lo coloca en tu cursor", + "key.emi.delete_cursor_stack": "Eliminar Pila del Cursor", + "key.emi.copy_recipe_id": "Copiar ID de Receta", + "key.emi.hide_stack": "Ocultar Pila", + "key.emi.hide_stack_by_id": "Ocultar Pila por ID", + + "emi.index_source.creative": "Creativo", + "emi.index_source.registered": "Registrado", + "emi.index_source.creative_plus_registered": "Creativo + Registrado", + "emi.help_level.verbose": "Detallado", + "emi.help_level.normal": "Normal", + "emi.help_level.none": "Ninguno", + "emi.align.horizontal.left": "Izquierda", + "emi.align.horizontal.center": "Centro", + "emi.align.horizontal.right": "Derecha", + "emi.align.vertical.top": "Arriba", + "emi.align.vertical.center": "Centro", + "emi.align.vertical.bottom": "Abajo", + "emi.sidebar.type.none": "Ninguno", + "emi.sidebar.type.index": "Índice", + "emi.sidebar.type.index.description": "Muestra todos los objetos", + "emi.sidebar.type.craftables": "Fabricables", + "emi.sidebar.type.craftables.description": "Muestra todos los objetos fabricables", + "emi.sidebar.type.favorites": "Favoritos", + "emi.sidebar.type.favorites.description": "Muestra los favoritos", + "emi.sidebar.type.lookup_history": "Historial de Búsquedas", + "emi.sidebar.type.lookup_history.description": "Muestra los objetos buscados anteriormente", + "emi.sidebar.type.craft_history": "Historial de Fabricación", + "emi.sidebar.type.craft_history.description": "Muestra los objetos fabricados anteriormente", + "emi.sidebar.type.empty": "Vacío", + "emi.sidebar.type.empty.description": "No muestra nada", + "emi.sidebar.type.chess": "Ajedrez", + "emi.sidebar.type.chess.description": "Ajedrez", + "emi.sidebar.theme.transparent": "Transparente", + "emi.sidebar.theme.vanilla": "Vanilla", + "emi.sidebar.theme.modern": "Moderno", + "emi.header.visible": "Visible", + "emi.header.invisible": "Invisible", + "emi.sidebar.size.columns": "Columnas", + "emi.sidebar.size.rows": "Filas", + "emi.sidebar.margins.top": "Superior", + "emi.sidebar.margins.right": "Derecho", + "emi.sidebar.margins.bottom": "Inferior", + "emi.sidebar.margins.left": "Izquierdo", + "emi.sidebar.none": "Ninguno", + "emi.sidebar.left": "Izquierda", + "emi.sidebar.right": "Derecha", + "emi.sidebar.top": "Arriba", + "emi.sidebar.bottom": "Abajo", + "emi.effect_location.top": "Arriba", + "emi.effect_location.left_compressed": "Izquierda (Comprimido)", + "emi.effect_location.right_compressed": "Derecha (Comprimido)", + "emi.effect_location.left": "Izquierda", + "emi.effect_location.right": "Derecha", + "emi.effect_location.hidden": "Oculto", + "emi.recipe_book_action.default": "Predeterminado", + "emi.recipe_book_action.toggle_craftables": "Alternar Fabricables", + "emi.recipe_book_action.toggle_visibility": "Alternar Visibilidad", + "emi.button_visibility.auto": "Automático", + "emi.button_visibility.shown": "Mostrado", + "emi.button_visibility.hidden": "Oculto", + + "config.emi.group.general": "General", + "config.emi.group.general.search": "Búsqueda", + "config.emi.group.ui": "Interfaz", + "config.emi.group.ui.mod_id": "ID del Mod", + "config.emi.group.ui.recipe_screen": "Pantalla de Recetas", + "config.emi.group.ui.recipe_buttons": "Botones de Recetas", + "config.emi.group.ui.left_sidebar": "Barra Lateral Izquierda", + "config.emi.group.ui.right_sidebar": "Barra Lateral Derecha", + "config.emi.group.ui.top_sidebar": "Barra Superior", + "config.emi.group.ui.bottom_sidebar": "Barra Inferior", + "config.emi.group.binds": "Atajos", + "config.emi.group.dev": "Desarrollo", + + "config.emi.group.binds.crafts": "Fabricaciones", + "config.emi.group.binds.cheats": "Trampas", + + "config.emi.general.enabled": "Habilitado", + "config.emi.general.cheat_mode": "Modo Trampa", + "config.emi.general.help_level": "Nivel de Ayuda", + "config.emi.general.index_source": "Fuente del Índice", + "config.emi.general.search_sidebar": "Barra Lateral de Búsqueda", + "config.emi.general.search_tooltip_by_default": "Buscar en Descripciones por Defecto", + "config.emi.general.search_mod_name_by_default": "Buscar Nombre del Mod por Defecto", + "config.emi.general.search_tags_by_default": "Buscar Etiquetas por Defecto", + + "config.emi.ui.effect_location": "Ubicación de Efectos", + "config.emi.ui.center_search_bar": "Centrar Barra de Búsqueda", + "config.emi.ui.show_hover_overlay": "Mostrar Superposición al Pasar", + "config.emi.ui.append_mod_id": "Añadir ID del Mod", + "config.emi.ui.append_item_mod_id": "Añadir ID del Mod del Objeto", + "config.emi.ui.recipe_book_action": "Acción del Libro de Recetas", + "config.emi.ui.search_sidebar_focus": "Enfoque de Barra Lateral de Búsqueda", + "config.emi.ui.empty_search_sidebar_focus": "Enfoque de Barra Lateral de Búsqueda Vacía", + + "config.emi.ui.left_sidebar_pages": "Páginas", + "config.emi.ui.left_sidebar_subpanels": "Subpaneles", + "config.emi.ui.left_sidebar_size": "Tamaño", + "config.emi.ui.left_sidebar_margins": "Márgenes", + "config.emi.ui.left_sidebar_align": "Alineación", + "config.emi.ui.left_sidebar_header": "Encabezado", + "config.emi.ui.left_sidebar_theme": "Tema", + + "config.emi.ui.right_sidebar_pages": "Páginas", + "config.emi.ui.right_sidebar_subpanels": "Subpaneles", + "config.emi.ui.right_sidebar_size": "Tamaño", + "config.emi.ui.right_sidebar_margins": "Márgenes", + "config.emi.ui.right_sidebar_align": "Alineación", + "config.emi.ui.right_sidebar_header": "Encabezado", + "config.emi.ui.right_sidebar_theme": "Tema", + + "config.emi.ui.top_sidebar_pages": "Páginas", + "config.emi.ui.top_sidebar_subpanels": "Subpaneles", + "config.emi.ui.top_sidebar_size": "Tamaño", + "config.emi.ui.top_sidebar_margins": "Márgenes", + "config.emi.ui.top_sidebar_align": "Alineación", + "config.emi.ui.top_sidebar_header": "Encabezado", + "config.emi.ui.top_sidebar_theme": "Tema", + + "config.emi.ui.bottom_sidebar_pages": "Páginas", + "config.emi.ui.bottom_sidebar_subpanels": "Subpaneles", + "config.emi.ui.bottom_sidebar_size": "Tamaño", + "config.emi.ui.bottom_sidebar_margins": "Márgenes", + "config.emi.ui.bottom_sidebar_align": "Alineación", + "config.emi.ui.bottom_sidebar_header": "Encabezado", + "config.emi.ui.bottom_sidebar_theme": "Tema", + + "config.emi.ui.maximum_recipe_screen_height": "Altura Máxima de la Pantalla de Recetas", + "config.emi.ui.minimum_recipe_screen_width": "Ancho Mínimo de la Pantalla de Recetas", + "config.emi.ui.vertical_margin": "Margen Vertical de la Pantalla de Recetas", + "config.emi.ui.workstation_location": "Ubicación de la Mesa de Trabajo", + "config.emi.ui.miscraft_prevention": "Prevención de Errores de Fabricación", + "config.emi.ui.fluid_unit": "Unidad de Fluido", + "config.emi.ui.show_cost_per_batch": "Mostrar Costo por Lote", + "config.emi.ui.emi_config_button_visibility": "Visibilidad del Botón de Configuración de EMI", + "config.emi.ui.recipe_tree_button_visibility": "Visibilidad del Botón de Árbol de Recetas", + "config.emi.ui.recipe_default_button": "Botón de Receta por Defecto", + "config.emi.ui.recipe_tree_button": "Botón de Árbol de Recetas", + "config.emi.ui.recipe_fill_button": "Botón de Llenar Receta", + "config.emi.ui.recipe_screenshot_button": "Botón de Captura de Receta", + "config.emi.ui.recipe_screenshot_scale": "Escala de Captura de Receta", + "config.emi.ui.use_batched_renderer": "Usar Renderizador por Lotes", + + "config.emi.dev.dev_mode": "Modo Desarrollador", + "config.emi.dev.edit_mode": "Modo Edición", + "config.emi.dev.log_untranslated_tags": "Registrar Etiquetas No Traducidas", + "config.emi.dev.log_non_tag_ingredients": "Registrar Ingredientes Sin Etiqueta", + "config.emi.dev.show_recipe_ids": "Mostrar IDs de Recetas", + "config.emi.dev.show_recipe_decorators": "Mostrar Decoradores de Recetas", + "config.emi.dev.highlight_defaulted": "Resaltar por Defecto", + "config.emi.dev.highlight_exclusion_areas": "Resaltar Áreas de Exclusión", + + "config.emi.presets.sidebars": "Barras Laterales", + "config.emi.presets.binds": "Atajos", + "config.emi.presets.restore": "Restaurar", + + "config.emi.presets.productive": "Productivo", + "config.emi.presets.recipe_book_plus": "Libro de Recetas Plus", + "config.emi.presets.low_distraction": "Baja Distracción", + "config.emi.presets.empty_search_craftable": "Búsqueda Vacía Fabricable", + + "config.emi.presets.author_binds": "Atajos del Autor", + + "config.emi.presets.backup": "Restaurar Copia de Seguridad", + "config.emi.presets.defaults": "Restaurar Valores Predeterminados", + + "emi.unit.liters": "Litros", + "emi.unit.millibuckets": "Milibaldosas", + "emi.unit.droplets": "Gotas", + "emi.fluid.amount.liters": "%s L", + "emi.fluid.amount.millibuckets": "%smB", + "emi.fluid.amount.droplets": "%s g", + + "emi.disabled": "EMI desactivado! Alterna con", + "emi.reloading": "EMI recargándose...", + "emi.reloading.waiting": "EMI esperando datos de recetas del servidor...", + "emi.reloading.error": "§cEMI experimentó una excepción crítica durante la recarga, revisa el registro", + "emi.reloading.worry": "§cExperimentando retraso, ¿está todo bien?", + "emi.reloading.still_baking_recipes": "§dHorneando recetas...", + "emi.search": "Buscar en EMI...", + "emi.search_config": "Buscar configuración...", + "emi.delete_stack": "§cEliminar pila sostenida", + "emi.inapplicable": "La mesa de trabajo actual no soporta esta receta", + "emi.not_enough_ingredients": "No hay suficientes ingredientes para fabricar", + "emi.too_small": "La rejilla de fabricación es muy pequeña para los ingredientes", + "emi.favorite_recipe": "Presiona %s para marcar la receta como favorita", + "emi.resolve.resolve": "Presiona %s para usar en este árbol de recetas", + "emi.resolve.default": "Presiona %s para alternar por defecto para todos los árboles", + "emi.page": "Página %s de %s", + "emi.page.short": "%s/%s", + "emi.total_cost": "Costo Total", + "emi.cost_per": "Costo por lote:", + "emi.leftovers": "Sobrantes", + "emi.view_all_recipes": "Haz clic para ver todas las recetas", + "emi.tree_welcome": "Bienvenido a %s", + "emi.no_tree": "Aún no has establecido un árbol de recetas para ver...", + "emi.random_tree": "¿Quizás te gustaría ver uno aleatorio?", + "emi.random_tree_input": "Presiona §6[ctrl + r]", + "emi.edit_mode.hide_one": "Presiona %s para ocultar la pila", + "emi.edit_mode.hide_all": "Presiona %s para ocultar pilas por ID", + "emi.sidebar.cycle": "Presiona %s para cambiar barras laterales", + "emi.sidebar.favorite_stack": "Presiona %s para agregar/quitar una pila favorita", + "tooltip.emi.chance.consume": "Probabilidad de consumo: %s%%", + "tooltip.emi.chance.produce": "Probabilidad de producción: %s%%", + "tooltip.emi.accepts": "Acepta:", + "tooltip.emi.fill_recipe": "Llenar Receta", + "tooltip.emi.fill_recipe_no_server": "No se puede Llenar Receta sin EMI en el servidor", + "tooltip.emi.set_default": "Establecer como receta por defecto", + "tooltip.emi.current_defaults": "Actualmente la receta por defecto para:", + "tooltip.emi.unset_default": "Quitar como receta por defecto", + "tooltip.emi.set_default_stack": "Presiona %s en un resultado para establecer la receta por defecto para esa pila", + "tooltip.emi.view_tree": "Ver Árbol de Recetas", + "tooltip.emi.recipe_screenshot": "Tomar Captura de Receta", + "tooltip.emi.resolution": "Resolviendo árbol de recetas para ingrediente", + "tooltip.emi.select_resolution": "Haz clic en el §6resultado de una receta§r para asignarlo a §deste§r árbol de recetas", + "tooltip.emi.default_resolution": "Haz clic en el §6botón de receta predeterminada§r para asignar a §atodos§r los árboles de recetas", + "tooltip.emi.clear_resolution": "Haz clic §6aquí§r para §climpiar§r la resolución", + + "tooltip.emi.config": "Configuración de %s", + "tooltip.emi.recipe_tree": "Árbol de Recetas", + + "tooltip.emi.config.global": "Alterna entre usar una configuración global de EMI para todas las instancias del juego o una configuración separada por instancia", + + "tooltip.emi.synfav.uncraftable": "No es posible fabricar §cningún§r lote", + "tooltip.emi.synfav.partially_craftable": "Es posible fabricar §dalgunos§r lotes", + "tooltip.emi.synfav.fully_craftable": "Es posible fabricar §atodos los %s§r lotes", + "tooltip.emi.synfav.craft_some": "Presiona %s para fabricar tantos como sea posible", + "tooltip.emi.synfav.craft_all": "Presiona %s para fabricar todos los §9%s§r lotes", + + "tooltip.emi.bom.batch_size": "Tamaño del lote: %s\nDesplázate para ajustar\nMantén §6[Mayús]§r para ajustar de 16 en 16", + "tooltip.emi.bom.batch_size.ideal": "Presiona %s para minimizar los sobrantes", + "tooltip.emi.bom.mode.view": "§6Viendo§r árbol de recetas", + "tooltip.emi.bom.mode.craft": "§6Fabricando§r árbol de recetas\nEl progreso se mostrará en el árbol de recetas\n§bFavoritos sintéticos§r añadidos a la barra lateral", + "tooltip.emi.bom.help": "El árbol de recetas muestra el proceso y costo base de una receta\nLa visualización puede desplazarse y ampliarse\n\nHaz clic izquierdo en un nodo para elegir una receta a asignar\nMantén §6[Mayús]§r para seleccionar automáticamente según tu inventario\n\nHaz clic derecho en un nodo de receta para plegarlo temporalmente\nMantén §6[Mayús]§r para limpiar la receta\n\nEl estado inicial del árbol es controlado por las recetas predeterminadas\nUn botón junto a las recetas puede establecer preferencias de receta predeterminadas\n\nEl interruptor por costo total puede usarse para ayudar a fabricar un árbol de recetas\nMientras fabricas, se mostrarán los materiales que necesitas recolectar\nSe añadirán §bFavoritos sintéticos§r a la barra lateral de favoritos que\nmostrarán pasos incompletos y pueden usarse para fabricar", + + "tooltip.emi.fluid_interaction.basalt.soul_soil": "Debajo de lava", + "tooltip.emi.fluid_interaction.basalt.blue_ice": "Adyacente a lava", + + "screen.emi.recipe": "Receta", + "screen.emi.config": "Configuración", + "screen.emi.presets": "Configuraciones Predefinidas", + + "screen.emi.config.reset": "Revertir %s cambio(s)", + + "emi.error.recipe.initialize": "Error al Inicializar", + "emi.error.recipe.render": "Error al Renderizar", + + "emi.dev.severity.error": "Error", + "emi.dev.severity.warning": "Advertencia", + "emi.dev.null_recipe_id": "ID de receta es §7nulo§r\nLas recetas necesitan tener IDs únicos para ser serializadas\nEsto solo afectará a esta receta", + "emi.dev.duplicate_recipe_id": "ID de receta es un duplicado de otra receta\n§7%s§r\nLas recetas necesitan tener IDs únicos para ser serializadas\nEsto romperá otras recetas con este ID", + "emi.dev.duplicate_vanilla_recipe_id": "ID de receta es un duplicado de una receta vanilla\n§7%s§r\nLas recetas necesitan tener IDs únicos para ser serializadas\nEsto romperá la receta vanilla con el mismo ID", + "emi.dev.synthetic_id": "Usa un ID sintético §7[espacio de nombres]§b:/§7[ruta]§r", + "emi.dev.suggest_id": "Usa un ID sintético §7[espacio de nombres]§b:/§7[ruta]§r como\n§7%s§b:/§7%s§r", + "emi.dev.null_input_or_output": "Las entradas o salidas de la receta son §7nulas§r\nUsa una lista vacía para no tener entradas o salidas\nUsa §7EmiStack.EMPTY§r para representar una pila vacía", + "emi.dev.no_output_slots": "Las ranuras de la receta no incluyen ninguna salida\nLlama a §7SlotWidget.recipeContext(this)§r en las salidas§r", + "emi.dev.synthetic_nag_explanation": "ID de receta no se encontró en el administrador de recetas, pero no es sintético\n§7%s§r\nSi una receta no corresponde a una receta JSON impulsada por datos, debería usar un ID sintético", + + "emi.chess.piece.white_pawn": "Peón Blanco", + "emi.chess.piece.white_rook": "Torre Blanca", + "emi.chess.piece.white_knight": "Caballo Blanco", + "emi.chess.piece.white_bishop": "Alfil Blanco", + "emi.chess.piece.white_queen": "Reina Blanca", + "emi.chess.piece.white_king": "Rey Blanco", + "emi.chess.piece.black_pawn": "Peón Negro", + "emi.chess.piece.black_rook": "Torre Negra", + "emi.chess.piece.black_knight": "Caballo Negro", + "emi.chess.piece.black_bishop": "Alfil Negro", + "emi.chess.piece.black_queen": "Reina Negra", + "emi.chess.piece.black_king": "Rey Negro", + "emi.chess.tooltip.invite": "Invita al jugador en tu barra de búsqueda a jugar ajedrez", + "emi.chess.tooltip.accept": "Aceptar la invitación de ajedrez de %s", + "emi.chess.tooltip.decline": "Clic derecho para rechazar la invitación de ajedrez de %s", + "emi.chess.tooltip.restart": "Clic derecho para reiniciar", + "emi.chess.multiplayer.invited": "%s te invitó a jugar ajedrez", + "emi.chess.multiplayer.accepted": "%s aceptó tu invitación de ajedrez", + "emi.chess.multiplayer.cancelled": "%s canceló la partida de ajedrez", + "emi.chess.multiplayer.unavailable": "%s no puede jugar ajedrez", + + "emi.cooking.experience": "%s XP", + "emi.cooking.time": "%s Segundos", + "emi.grinding.experience": "%s - %s XP", + "emi.fuel_time.items": "Funde %s objeto(s)", + + "emi.category.minecraft.crafting": "Fabricación", + "emi.category.minecraft.smelting": "Fundición", + "emi.category.minecraft.blasting": "Alto Horno", + "emi.category.minecraft.smoking": "Ahumado", + "emi.category.minecraft.campfire_cooking": "Cocción en Fogata", + "emi.category.minecraft.stonecutting": "Cortapiedras", + "emi.category.minecraft.smithing": "Forja", + "emi.category.emi.anvil_repairing": "Reparación con Yunque", + "emi.category.minecraft.brewing": "Elaboración de Pociones", + "emi.category.emi.grinding": "Molienda", + "emi.category.emi.world_interaction": "Interacción con el Mundo", + "emi.category.emi.fuel": "Combustible", + "emi.category.emi.composting": "Compostaje", + "emi.category.emi.info": "Información", + + "emi.category.emi.tag": "Etiquetas", + "emi.category.emi.ingredient": "Ingredientes", + + "alias.emi.workbench": "Mesa de Trabajo", + + "tag.item.minecraft.logs": "Troncos", + "tag.item.minecraft.oak_logs": "Troncos de Roble", + "tag.item.minecraft.birch_logs": "Troncos de Abedul", + "tag.item.minecraft.spruce_logs": "Troncos de Abeto", + "tag.item.minecraft.jungle_logs": "Troncos de Jungla", + "tag.item.minecraft.dark_oak_logs": "Troncos de Roble Oscuro", + "tag.item.minecraft.crimson_stems": "Tallos Carmesí", + "tag.item.minecraft.warped_stems": "Tallos Distorsionados", + "tag.item.minecraft.acacia_logs": "Troncos de Acacia", + "tag.item.minecraft.logs_that_burn": "Troncos Inflamables", + "tag.item.minecraft.planks": "Tablones", + "tag.item.minecraft.non_flammable_wood": "Madera No Inflamable", + "tag.item.minecraft.coal_ores": "Mineral de Carbón", + "tag.item.minecraft.copper_ores": "Mineral de Cobre", + "tag.item.minecraft.diamond_ores": "Mineral de Diamante", + "tag.item.minecraft.emerald_ores": "Mineral de Esmeralda", + "tag.item.minecraft.gold_ores": "Mineral de Oro", + "tag.item.minecraft.iron_ores": "Mineral de Hierro", + "tag.item.minecraft.lapis_ores": "Mineral de Lapislázuli", + "tag.item.minecraft.redstone_ores": "Mineral de Redstone", + "tag.item.minecraft.anvil": "Yunques", + "tag.item.minecraft.arrows": "Flechas", + "tag.item.minecraft.axolotl_tempt_items": "Objetos que Atraen Ajolotes", + "tag.item.minecraft.banners": "Estandartes", + "tag.item.minecraft.beacon_payment_items": "Pagos para Baliza", + "tag.item.minecraft.beds": "Camas", + "tag.item.minecraft.boats": "Botes", + "tag.item.minecraft.buttons": "Botones", + "tag.item.minecraft.candles": "Velas", + "tag.item.minecraft.carpets": "Alfombras", + "tag.item.minecraft.coals": "Carbones", + "tag.item.minecraft.creeper_drop_music_discs": "Discos de Música que Sueltan los Creepers", + "tag.item.minecraft.creeper_igniters": "Encendedores de Creepers", + "tag.item.minecraft.dirt": "Tierra", + "tag.item.minecraft.doors": "Puertas", + "tag.item.minecraft.fences": "Vallas", + "tag.item.minecraft.fence_gates": "Puertas de Valla", + "tag.item.minecraft.fishes": "Peces", + "tag.item.minecraft.flowers": "Flores", + "tag.item.minecraft.fox_food": "Comida de Zorro", + "tag.item.minecraft.freeze_immune_wearables": "Equipo Inmune a la Congelación", + "tag.item.minecraft.ignored_by_piglin_babies": "Ignorado por Bebés Piglin", + "tag.item.minecraft.leaves": "Hojas", + "tag.item.minecraft.lectern_books": "Libros de Atril", + "tag.item.minecraft.music_discs": "Discos de Música", + "tag.item.minecraft.occludes_vibration_signals": "Ocluye Señales de Vibración", + "tag.item.minecraft.piglin_food": "Comida de Piglin", + "tag.item.minecraft.piglin_loved": "Amado por los Piglins", + "tag.item.minecraft.piglin_repellents": "Repelentes de Piglins", + "tag.item.minecraft.rails": "Rieles", + "tag.item.minecraft.sand": "Arena", + "tag.item.minecraft.saplings": "Brotes", + "tag.item.minecraft.signs": "Carteles", + "tag.item.minecraft.slabs": "Losas", + "tag.item.minecraft.small_flowers": "Flores Pequeñas", + "tag.item.minecraft.soul_fire_base_blocks": "Bases de Fuego de Alma", + "tag.item.minecraft.stairs": "Escaleras", + "tag.item.minecraft.stone_bricks": "Ladrillos de Piedra", + "tag.item.minecraft.stone_crafting_materials": "Materiales de Fabricación de Piedra", + "tag.item.minecraft.stone_tool_materials": "Materiales de Herramientas de Piedra", + "tag.item.minecraft.tall_flowers": "Flores Altas", + "tag.item.minecraft.terracotta": "Terracota", + "tag.item.minecraft.trapdoors": "Trampillas", + "tag.item.minecraft.walls": "Muros", + "tag.item.minecraft.wooden_buttons": "Botones de Madera", + "tag.item.minecraft.wooden_doors": "Puertas de Madera", + "tag.item.minecraft.wooden_fences": "Vallas de Madera", + "tag.item.minecraft.wooden_pressure_plates": "Placas de Presión de Madera", + "tag.item.minecraft.wooden_slabs": "Losas de Madera", + "tag.item.minecraft.wooden_stairs": "Escaleras de Madera", + "tag.item.minecraft.wooden_trapdoors": "Trampillas de Madera", + "tag.item.minecraft.wool": "Lana", + "tag.item.minecraft.wart_blocks": "Bloques de Verruga", + "tag.item.minecraft.wool_carpets": "Alfombras de Lana", + "tag.item.minecraft.mangrove_logs": "Troncos de Mangle", + "tag.item.minecraft.compasses": "Brújulas", + "tag.item.minecraft.chest_boats": "Botes con Cofre", + "tag.item.minecraft.overworld_natural_logs": "Troncos Naturales del Mundo", + "tag.item.minecraft.axes": "Hachas", + "tag.item.minecraft.hoes": "Azadas", + "tag.item.minecraft.pickaxes": "Picos", + "tag.item.minecraft.shovels": "Palas", + "tag.item.minecraft.smelts_to_glass": "Se Funde en Vidrio", + "tag.item.minecraft.swords": "Espadas", + "tag.item.minecraft.tools": "Herramientas", + "tag.item.minecraft.bamboo_blocks": "Bloques de Bambú", + "tag.item.minecraft.bookshelf_books": "Libros de Estantería", + "tag.item.minecraft.breaks_decorated_pots": "Rompe Macetas Decoradas", + "tag.item.minecraft.cherry_logs": "Troncos de Cerezo", + "tag.item.minecraft.decorated_pot_ingredients": "Ingredientes de Macetas Decoradas", + "tag.item.minecraft.decorated_pot_sherds": "Fragmentos de Macetas Decoradas", + "tag.item.minecraft.hanging_signs": "Carteles Colgantes", + "tag.item.minecraft.noteblock_top_instruments": "Instrumentos de Bloque de Notas Superior", + "tag.item.minecraft.sniffer_food": "Comida de Husmeador", + "tag.item.minecraft.stone_buttons": "Botones de Piedra", + "tag.item.minecraft.trim_materials": "Materiales de Adorno", + "tag.item.minecraft.trim_templates": "Plantillas de Adorno", + "tag.item.minecraft.trimmable_armor": "Armadura Adornables", + "tag.item.minecraft.villager_plantable_seeds": "Semillas Plantables por Aldeanos", + + "tag.minecraft.armadillo_food": "Comida de Armadillo", + "tag.minecraft.axolotl_food": "Comida de Ajolote", + "tag.minecraft.bee_food": "Comida de Abeja", + "tag.minecraft.camel_food": "Comida de Camello", + "tag.minecraft.cat_food": "Comida de Gato", + "tag.minecraft.chest_armor": "Pecheras", + "tag.minecraft.chicken_food": "Comida de Pollo", + "tag.minecraft.cow_food": "Comida de Vaca", + "tag.minecraft.dyeable": "Teñible", + "tag.minecraft.enchantable.armor": "Armadura Encantable", + "tag.minecraft.enchantable.bow": "Arcos Encantables", + "tag.minecraft.enchantable.chest_armor": "Pecheras Encantables", + "tag.minecraft.enchantable.crossbow": "Ballestas Encantables", + "tag.minecraft.enchantable.durability": "Durabilidad Encantable", + "tag.minecraft.enchantable.equippable": "Equipo Encantable", + "tag.minecraft.enchantable.fire_aspect": "Aspecto Ígneo Encantable", + "tag.minecraft.enchantable.fishing": "Pesca Encantable", + "tag.minecraft.enchantable.foot_armor": "Botas Encantables", + "tag.minecraft.enchantable.head_armor": "Yelmos Encantables", + "tag.minecraft.enchantable.leg_armor": "Grebas Encantables", + "tag.minecraft.enchantable.mining": "Minería Encantable", + "tag.minecraft.enchantable.mining_loot": "Botín de Minería Encantable", + "tag.minecraft.enchantable.sharp_weapon": "Armas Afiladas Encantables", + "tag.minecraft.enchantable.sword": "Espadas Encantables", + "tag.minecraft.enchantable.trident": "Tridentes Encantables", + "tag.minecraft.enchantable.vanishing": "Desaparición Encantable", + "tag.minecraft.enchantable.weapon": "Armas Encantables", + "tag.minecraft.foot_armor": "Botas", + "tag.minecraft.frog_food": "Comida de Rana", + "tag.minecraft.goat_food": "Comida de Cabra", + "tag.minecraft.head_armor": "Yelmos", + "tag.minecraft.hoglin_food": "Comida de Hoglin", + "tag.minecraft.horse_food": "Comida de Caballo", + "tag.minecraft.horse_tempt_items": "Objetos que Atraen a Caballos", + "tag.minecraft.leg_armor": "Grebas", + "tag.minecraft.llama_food": "Comida de Llama", + "tag.minecraft.llama_tempt_items": "Objetos que Atraen a Llamas", + "tag.minecraft.meat": "Carne", + "tag.minecraft.ocelot_food": "Comida de Ocelote", + "tag.minecraft.panda_food": "Comida de Panda", + "tag.minecraft.parrot_food": "Comida de Loro", + "tag.minecraft.parrot_poisonous_food": "Comida Venenosa para Loros", + "tag.minecraft.pig_food": "Comida de Cerdo", + "tag.minecraft.rabbit_food": "Comida de Conejo", + "tag.minecraft.sheep_food": "Comida de Oveja", + "tag.minecraft.skulls": "Calaveras", + "tag.minecraft.strider_food": "Comida de Lavagante", + "tag.minecraft.strider_tempt_items": "Objetos que Atraen a Lavagantes", + "tag.minecraft.turtle_food": "Comida de Tortuga", + "tag.minecraft.wolf_food": "Comida de Lobo", + + "tag.fluid.minecraft.water": "Agua", + "tag.fluid.minecraft.lava": "Lava", + "tag.fluid.c.water": "Agua", + "tag.fluid.c.lava": "Lava", + "tag.fluid.c.milk": "Leche", + + "tag.item.c.stone": "Piedra", + "tag.item.c.cobblestone": "Roca", + "tag.item.c.cobblestone.deepslate": "Roca de Pizarra Profunda", + "tag.item.c.cobblestone.infested": "Roca Infestada", + "tag.item.c.cobblestone.mossy": "Roca Musgosa", + "tag.item.c.cobblestone.normal": "Roca", + "tag.item.c.sandstone": "Arenisca", + "tag.item.c.glass_blocks": "Bloques de Vidrio", + "tag.item.c.stained_glass": "Vidrio Tintado", + "tag.item.c.stained_glass_panes": "Paneles de Vidrio Tintado", + "tag.item.c.glass": "Vidrio", + "tag.item.c.glass.colorless": "Vidrio Incoloro", + "tag.item.c.glass.silica": "Vidrio de Sílice", + "tag.item.c.quartz_blocks": "Bloques de Cuarzo", + "tag.item.c.glass_panes": "Paneles de Vidrio", + "tag.item.c.glass.tinted": "Vidrio Tintado", + "tag.item.c.glass_panes.colorless": "Paneles de Vidrio Incoloro", + "tag.item.c.raw_materials": "Materiales Crudos", + "tag.item.c.rods": "Barras", + "tag.item.c.ores": "Minerales", + "tag.item.c.nuggets": "Pepitas", + "tag.item.c.ingots": "Lingotes", + "tag.item.c.gems": "Gemas", + "tag.item.c.plates": "Placas", + "tag.item.c.dusts": "Polvos", + "tag.item.c.storage_blocks": "Bloques de Almacenamiento", + "tag.item.c.seeds": "Semillas", + "tag.item.c.crops": "Cultivos", + "tag.item.c.heads": "Cabezas", + "tag.item.c.dyes": "Tintes", + "tag.item.c.mushrooms": "Hongos", + "tag.item.c.fence_gates": "Puertas de Valla", + "tag.item.c.fence_gates.wooden": "Puertas de Valla de Madera", + "tag.item.c.chests": "Cofres", + "tag.item.c.wooden_chests": "Cofres de Madera", + "tag.item.c.ores_in_ground.stone": "Minerales en Piedra", + "tag.item.c.ores_in_ground.deepslate": "Minerales en Pizarra Profunda", + "tag.item.c.ores_in_ground.netherrack": "Minerales en Netherrack", + + "tag.item.c.chest": "Cofres", + "tag.item.c.coal": "Carbones", + "tag.item.c.sand": "Arenas", + "tag.item.c.glass_pane": "Paneles de Vidrio", + "tag.item.c.beacon_payment": "Pagos de Baliza", + "tag.item.c.fences": "Vallas", + "tag.item.c.fences.wooden": "Vallas de Madera", + "tag.item.c.ores.coal": "Mineral de Carbón", + "tag.item.c.ores.copper": "Mineral de Cobre", + "tag.item.c.ores.iron": "Mineral de Hierro", + "tag.item.c.ores.gold": "Mineral de Oro", + "tag.item.c.ores.redstone": "Mineral de Redstone", + "tag.item.c.ores.lapis": "Mineral de Lapislázuli", + "tag.item.c.ores.emerald": "Mineral de Esmeralda", + "tag.item.c.ores.diamond": "Mineral de Diamante", + + "tag.item.c.storage_blocks.coal": "Bloques de Almacenamiento de Carbón", + + "tag.item.c.raw_materials.copper": "Cobre Crudo", + "tag.item.c.copper_dusts": "Polvos de Cobre", + "tag.item.c.dusts.copper": "Polvos de Cobre", + "tag.item.c.copper_ingots": "Lingotes de Cobre", + "tag.item.c.ingots.copper": "Lingotes de Cobre", + "tag.item.c.copper_nuggets": "Pepitas de Cobre", + "tag.item.c.nuggets.copper": "Pepitas de Cobre", + "tag.item.c.plates.copper": "Placas de Cobre", + "tag.item.c.raw_copper_ores": "Mineral de Cobre Crudo", + "tag.item.c.raw_copper_blocks": "Bloques de Cobre Crudo", + "tag.item.c.copper_blocks": "Bloques de Cobre", + "tag.item.c.storage_blocks.raw_copper": "Bloques de Almacenamiento de Cobre Crudo", + "tag.item.c.storage_blocks.copper": "Bloques de Almacenamiento de Cobre", + + "tag.item.c.raw_materials.iron": "Hierro Crudo", + "tag.item.c.iron_dusts": "Polvos de Hierro", + "tag.item.c.dusts.iron": "Polvos de Hierro", + "tag.item.c.iron_ingots": "Lingotes de Hierro", + "tag.item.c.ingots.iron": "Lingotes de Hierro", + "tag.item.c.iron_nuggets": "Pepitas de Hierro", + "tag.item.c.nuggets.iron": "Pepitas de Hierro", + "tag.item.c.plates.iron": "Placas de Hierro", + "tag.item.c.raw_iron_ores": "Mineral de Hierro Crudo", + "tag.item.c.raw_iron_blocks": "Bloques de Hierro Crudo", + "tag.item.c.iron_blocks": "Bloques de Hierro", + "tag.item.c.storage_blocks.raw_iron": "Bloques de Almacenamiento de Hierro Crudo", + "tag.item.c.storage_blocks.iron": "Bloques de Almacenamiento de Hierro", + + "tag.item.c.raw_materials.gold": "Oro Crudo", + "tag.item.c.gold_dusts": "Polvos de Oro", + "tag.item.c.dusts.gold": "Polvos de Oro", + "tag.item.c.gold_ingots": "Lingotes de Oro", + "tag.item.c.ingots.gold": "Lingotes de Oro", + "tag.item.c.gold_nuggets": "Pepitas de Oro", + "tag.item.c.nuggets.gold": "Pepitas de Oro", + "tag.item.c.plates.gold": "Placas de Oro", + "tag.item.c.raw_gold_ores": "Mineral de Oro Crudo", + "tag.item.c.raw_gold_blocks": "Bloques de Oro Crudo", + "tag.item.c.gold_blocks": "Bloques de Oro", + "tag.item.c.storage_blocks.gold": "Bloques de Almacenamiento de Oro", + "tag.item.c.storage_blocks.raw_gold": "Bloques de Almacenamiento de Oro Crudo", + + "tag.item.c.gems.amethyst": "Amatistas", + "tag.item.c.amethyst_dusts": "Polvos de Amatista", + "tag.item.c.storage_blocks.amethyst": "Bloques de Almacenamiento de Amatista", + + "tag.item.c.storage_blocks.diamond": "Bloques de Almacenamiento de Diamante", + "tag.item.c.storage_blocks.emerald": "Bloques de Almacenamiento de Esmeralda", + "tag.item.c.storage_blocks.lapis": "Bloques de Almacenamiento de Lapislázuli", + "tag.item.c.storage_blocks.netherite": "Bloques de Almacenamiento de Netherita", + "tag.item.c.storage_blocks.quartz": "Bloques de Almacenamiento de Cuarzo", + "tag.item.c.storage_blocks.redstone": "Bloques de Almacenamiento de Redstone", + "tag.item.c.redstone_dusts": "Polvos de Redstone", + "tag.item.c.redstone_ores": "Mineral de Redstone", + "tag.item.c.quartz": "Cuarzo", + "tag.item.c.quartz_ores": "Mineral de Cuarzo", + "tag.item.c.diamond_dusts": "Polvos de Diamante", + "tag.item.c.diamonds": "Diamantes", + "tag.item.c.dusts.glowstone": "Polvos de Piedra Luminosa", + "tag.item.c.dusts.prismarine": "Polvos de Prismarina", + "tag.item.c.dusts.redstone": "Polvos de Redstone", + "tag.item.c.emeralds": "Esmeraldas", + "tag.item.c.ender_pearl_dusts": "Polvos de Perla de Ender", + "tag.item.c.ender_pearls": "Perlas de Ender", + "tag.item.c.gems.diamond": "Diamantes", + "tag.item.c.gems.emerald": "Esmeraldas", + "tag.item.c.gems.lapis": "Lapislázuli", + "tag.item.c.gems.prismarine": "Prismarina", + "tag.item.c.gems.quartz": "Cuarzo", + "tag.item.c.ingots.brick": "Ladrillos", + "tag.item.c.ingots.nether_brick": "Ladrillos del Nether", + "tag.item.c.ingots.netherite": "Lingotes de Netherita", + "tag.item.c.lapis": "Lapislázuli", + "tag.item.c.nether_quartz_dusts": "Polvos de Cuarzo del Nether", + "tag.item.c.netherite_ingots": "Lingotes de Netherita", + "tag.item.c.netherite_scrap_dusts": "Polvos de Desechos de Netherita", + "tag.item.c.ores.netherite_scrap": "Mineral de Desechos de Netherita", + "tag.item.c.ores.quartz": "Mineral de Cuarzo", + + "tag.item.c.spears": "Lanzas", + "tag.item.c.axes": "Hachas", + "tag.item.c.barrels": "Barriles", + "tag.item.c.barrels.wooden": "Barriles de Madera", + "tag.item.c.white_dyes": "Tintes Blancos", + "tag.item.c.orange_dyes": "Tintes Naranjas", + "tag.item.c.magenta_dyes": "Tintes Magentas", + "tag.item.c.light_blue_dyes": "Tintes Azul Claro", + "tag.item.c.yellow_dyes": "Tintes Amarillos", + "tag.item.c.lime_dyes": "Tintes Lima", + "tag.item.c.pink_dyes": "Tintes Rosados", + "tag.item.c.gray_dyes": "Tintes Grises", + "tag.item.c.light_gray_dyes": "Tintes Gris Claro", + "tag.item.c.cyan_dyes": "Tintes Cian", + "tag.item.c.purple_dyes": "Tintes Morados", + "tag.item.c.blue_dyes": "Tintes Azules", + "tag.item.c.brown_dyes": "Tintes Marrones", + "tag.item.c.green_dyes": "Tintes Verdes", + "tag.item.c.red_dyes": "Tintes Rojos", + "tag.item.c.black_dyes": "Tintes Negros", + "tag.item.c.dyes.white": "Tintes Blancos", + "tag.item.c.dyes.orange": "Tintes Naranjas", + "tag.item.c.dyes.magenta": "Tintes Magentas", + "tag.item.c.dyes.light_blue": "Tintes Azul Claro", + "tag.item.c.dyes.yellow": "Tintes Amarillos", + "tag.item.c.dyes.lime": "Tintes Lima", + "tag.item.c.dyes.pink": "Tintes Rosados", + "tag.item.c.dyes.gray": "Tintes Grises", + "tag.item.c.dyes.light_gray": "Tintes Gris Claro", + "tag.item.c.dyes.cyan": "Tintes Cian", + "tag.item.c.dyes.purple": "Tintes Morados", + "tag.item.c.dyes.blue": "Tintes Azules", + "tag.item.c.dyes.brown": "Tintes Marrones", + "tag.item.c.dyes.green": "Tintes Verdes", + "tag.item.c.dyes.red": "Tintes Rojos", + "tag.item.c.dyes.black": "Tintes Negros", + "tag.item.c.glass.white": "Vidrio Blanco", + "tag.item.c.glass.orange": "Vidrio Naranja", + "tag.item.c.glass.magenta": "Vidrio Magenta", + "tag.item.c.glass.light_blue": "Vidrio Azul Claro", + "tag.item.c.glass.yellow": "Vidrio Amarillo", + "tag.item.c.glass.lime": "Vidrio Lima", + "tag.item.c.glass.pink": "Vidrio Rosado", + "tag.item.c.glass.gray": "Vidrio Gris", + "tag.item.c.glass.light_gray": "Vidrio Gris Claro", + "tag.item.c.glass.cyan": "Vidrio Cian", + "tag.item.c.glass.purple": "Vidrio Morado", + "tag.item.c.glass.blue": "Vidrio Azul", + "tag.item.c.glass.brown": "Vidrio Marrón", + "tag.item.c.glass.green": "Vidrio Verde", + "tag.item.c.glass.red": "Vidrio Rojo", + "tag.item.c.glass.black": "Vidrio Negro", + "tag.item.c.glass_panes.white": "Paneles de Vidrio Blanco", + "tag.item.c.glass_panes.orange": "Paneles de Vidrio Naranja", + "tag.item.c.glass_panes.magenta": "Paneles de Vidrio Magenta", + "tag.item.c.glass_panes.light_blue": "Paneles de Vidrio Azul Claro", + "tag.item.c.glass_panes.yellow": "Paneles de Vidrio Amarillo", + "tag.item.c.glass_panes.lime": "Paneles de Vidrio Lima", + "tag.item.c.glass_panes.pink": "Paneles de Vidrio Rosado", + "tag.item.c.glass_panes.gray": "Paneles de Vidrio Gris", + "tag.item.c.glass_panes.light_gray": "Paneles de Vidrio Gris Claro", + "tag.item.c.glass_panes.cyan": "Paneles de Vidrio Cian", + "tag.item.c.glass_panes.purple": "Paneles de Vidrio Morado", + "tag.item.c.glass_panes.blue": "Paneles de Vidrio Azul", + "tag.item.c.glass_panes.brown": "Paneles de Vidrio Marrón", + "tag.item.c.glass_panes.green": "Paneles de Vidrio Verde", + "tag.item.c.glass_panes.red": "Paneles de Vidrio Rojo", + "tag.item.c.glass_panes.black": "Paneles de Vidrio Negro", + "tag.item.c.bones": "Huesos", + "tag.item.c.bookshelves": "Estanterías", + "tag.item.c.bows": "Arcos", + "tag.item.c.buckets.honey": "Baldes de Miel", + "tag.item.c.chests.ender": "Cofres de Ender", + "tag.item.c.chests.trapped": "Cofres Trampa", + "tag.item.c.chests.wooden": "Cofres de Madera", + "tag.item.c.circuits": "Circuitos", + "tag.item.c.crops.beetroot": "Remolachas", + "tag.item.c.crops.carrot": "Zanahorias", + "tag.item.c.crops.nether_wart": "Verrugas del Nether", + "tag.item.c.crops.potato": "Papas", + "tag.item.c.crops.wheat": "Trigo", + "tag.item.c.eggs": "Huevos", + "tag.item.c.empty_buckets": "Baldes Vacíos", + "tag.item.c.enchanting_fuels": "Combustibles para Encantamientos", + "tag.item.c.end_stones": "Piedras del End", + "tag.item.c.feathers": "Plumas", + "tag.item.c.fences.nether_brick": "Vallas de Ladrillos del Nether", + "tag.item.c.foods": "Comida", + "tag.item.c.gravel": "Grava", + "tag.item.c.gunpowder": "Pólvora", + "tag.item.c.hoes": "Azadas", + "tag.item.c.lava_buckets": "Baldes de Lava", + "tag.item.c.leather": "Cuero", + "tag.item.c.milk_bottles": "Botellas de Leche", + "tag.item.c.milk_buckets": "Baldes de Leche", + "tag.item.c.nether_stars": "Estrellas del Nether", + "tag.item.c.netherrack": "Netherrack", + "tag.item.c.obsidian": "Obsidiana", + "tag.item.c.pickaxes": "Picos", + "tag.item.c.potions": "Pociones", + "tag.item.c.red_sandstone": "Arenisca Roja", + "tag.item.c.red_sandstone_slabs": "Losas de Arenisca Roja", + "tag.item.c.red_sandstone_stairs": "Escaleras de Arenisca Roja", + "tag.item.c.rods.blaze": "Barras de Blaze", + "tag.item.c.rods.wooden": "Barras de Madera", + "tag.item.c.sand.colorless": "Arena Incolora", + "tag.item.c.sand.red": "Arena Roja", + "tag.item.c.sandstone_slabs": "Losas de Arenisca", + "tag.item.c.sandstone_stairs": "Escaleras de Arenisca", + "tag.item.c.seeds.beetroot": "Semillas de Remolacha", + "tag.item.c.seeds.melon": "Semillas de Melón", + "tag.item.c.seeds.pumpkin": "Semillas de Calabaza", + "tag.item.c.seeds.wheat": "Semillas de Trigo", + "tag.item.c.shears": "Tijeras", + "tag.item.c.shields": "Escudos", + "tag.item.c.shovels": "Palas", + "tag.item.c.shulker_boxes": "Cajas de Shulker", + "tag.item.c.skulls": "Calaveras", + "tag.item.c.slime_balls": "Bolas de Slime", + "tag.item.c.slimeballs": "Bolas de Slime", + "tag.item.c.stone_dusts": "Polvos de Piedra", + "tag.item.c.stones": "Piedras", + "tag.item.c.string": "Hilo", + "tag.item.c.strings": "Hilos", + "tag.item.c.swords": "Espadas", + "tag.item.c.water_buckets": "Baldes de Agua", + "tag.item.c.wrenches": "Llaves Inglesas", + + "tag.item.c.budding_blocks": "Bloques en Ciernes", + "tag.item.c.buds": "Brotes", + "tag.item.c.clusters": "Cúmulos", + "tag.item.c.entity_water_buckets": "Baldes de Agua con Entidades", + "tag.item.c.raw_ores": "Minerales Crudos", + "tag.item.c.red_sandstone_blocks": "Bloques de Arenisca Roja", + "tag.item.c.sandstone_blocks": "Bloques de Arenisca", + "tag.item.c.uncolored_sandstone_blocks": "Bloques de Arenisca Incolora", + "tag.item.c.uncolored_sandstone_slabs": "Losas de Arenisca Incolora", + "tag.item.c.uncolored_sandstone_stairs": "Escaleras de Arenisca Incolora", + "tag.item.c.villager_job_sites": "Sitios de Trabajo de Aldeanos", + "tag.item.c.wooden_barrels": "Barriles de Madera", + + "tag.item.c.armors": "Armaduras", + "tag.item.c.armors.boots": "Botas", + "tag.item.c.armors.chestplates": "Pecheras", + "tag.item.c.armors.helmets": "Yelmos", + "tag.item.c.armors.leggings": "Grebas", + "tag.item.c.tools": "Herramientas", + "tag.item.c.tools.axes": "Hachas", + "tag.item.c.tools.bows": "Arcos", + "tag.item.c.tools.crossbows": "Ballestas", + "tag.item.c.tools.fishing_rods": "Cañas de Pescar", + "tag.item.c.tools.hoes": "Azadas", + "tag.item.c.tools.pickaxes": "Picos", + "tag.item.c.tools.shields": "Escudos", + "tag.item.c.tools.shovels": "Palas", + "tag.item.c.tools.swords": "Espadas", + "tag.item.c.tools.tridents": "Tridentes", + + "tag.item.fabric.pickaxes": "Picos", + "tag.item.fabric.axes": "Hachas", + "tag.item.fabric.shovels": "Palas", + "tag.item.fabric.hoes": "Azadas", + "tag.item.fabric.swords": "Espadas", + "tag.item.fabric.shears": "Tijeras" +} From ecff40354d0f20db4d2cc5b1c5bc076666dff02b Mon Sep 17 00:00:00 2001 From: emilyploszaj Date: Sun, 13 Apr 2025 22:17:50 -0500 Subject: [PATCH 67/67] Fix 1.20.6 crash --- .../src/main/java/dev/emi/emi/network/EmiNetwork.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/xplat/src/main/java/dev/emi/emi/network/EmiNetwork.java b/xplat/src/main/java/dev/emi/emi/network/EmiNetwork.java index 0b3c35cd..604e0c79 100644 --- a/xplat/src/main/java/dev/emi/emi/network/EmiNetwork.java +++ b/xplat/src/main/java/dev/emi/emi/network/EmiNetwork.java @@ -9,11 +9,11 @@ public class EmiNetwork { // TODO - public static final CustomPayload.Id FILL_RECIPE = CustomPayload.id("emi/fill_recipe"); - public static final CustomPayload.Id CREATE_ITEM = CustomPayload.id("emi/create_item"); - public static final CustomPayload.Id COMMAND = CustomPayload.id("emi/command"); - public static final CustomPayload.Id CHESS = CustomPayload.id("emi/chess"); - public static final CustomPayload.Id PING = CustomPayload.id("emi/ping"); + public static final CustomPayload.Id FILL_RECIPE = new CustomPayload.Id<>(Identifier.of("emi", "fill_recipe")); + public static final CustomPayload.Id CREATE_ITEM = new CustomPayload.Id<>(Identifier.of("emi", "create_item")); + public static final CustomPayload.Id COMMAND = new CustomPayload.Id<>(Identifier.of("emi", "command")); + public static final CustomPayload.Id CHESS = new CustomPayload.Id<>(Identifier.of("emi", "chess")); + public static final CustomPayload.Id PING = new CustomPayload.Id<>(Identifier.of("emi", "ping")); private static BiConsumer clientSender; private static Consumer serverSender;