From 0c7913cd12a642f264ab30dafc651d47c1641a03 Mon Sep 17 00:00:00 2001 From: thedarkcolour <30441001+thedarkcolour@users.noreply.github.com> Date: Sun, 7 Jan 2024 15:09:16 -0800 Subject: [PATCH] Ex Deorum 1.13 --- build.gradle | 11 +- changelog.md | 9 ++ .../AbstractCrucibleBlockEntity.java | 17 +-- .../blockentity/BarrelBlockEntity.java | 5 +- .../blockentity/SieveBlockEntity.java | 3 +- .../exdeorum/client/ClientHandler.java | 26 +++- .../exdeorum/client/RenderFace.java | 80 +++++++++++ .../exdeorum/client/RenderUtil.java | 133 +++++++++++------- .../exdeorum/client/ter/CrucibleRenderer.java | 8 +- .../exdeorum/client/ter/SieveRenderer.java | 34 ++--- .../thedarkcolour/exdeorum/compat/ModIds.java | 1 + .../compat/jei/BarrelCompostCategory.java | 71 +++++++++- .../compat/jei/BarrelMixingCategory.java | 14 +- .../compat/kubejs/ExDeorumKubeJsBindings.java | 11 ++ .../compat/kubejs/ExDeorumKubeJsPlugin.java | 7 + .../compat/kubejs/SieveMeshFilter.java | 33 +++++ .../compat/kubejs/SieveRecipeSchema.java | 92 ++++++++++++ .../exdeorum/recipe/ProbabilityRecipe.java | 7 + .../exdeorum/recipe/RecipeUtil.java | 34 ++--- .../recipe/barrel/BarrelMixingRecipe.java | 6 + .../exdeorum/recipe/sieve/SieveRecipe.java | 4 - .../models/block/oak_barrel_composting.json | 68 +++++++++ .../models/item/oak_barrel_composting.json | 3 + 23 files changed, 554 insertions(+), 123 deletions(-) create mode 100644 src/main/java/thedarkcolour/exdeorum/client/RenderFace.java create mode 100644 src/main/java/thedarkcolour/exdeorum/compat/kubejs/SieveMeshFilter.java create mode 100644 src/main/java/thedarkcolour/exdeorum/compat/kubejs/SieveRecipeSchema.java create mode 100644 src/main/resources/assets/exdeorum/models/block/oak_barrel_composting.json create mode 100644 src/main/resources/assets/exdeorum/models/item/oak_barrel_composting.json diff --git a/build.gradle b/build.gradle index b88a9630..b1d2d71b 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ plugins { id 'org.spongepowered.mixin' version '0.7.+' } -version = '1.12' +version = '1.13' group = 'thedarkcolour.exdeorum' base { archivesName = 'exdeorum' @@ -135,6 +135,12 @@ repositories { includeModule("maven.modrinth", "embeddium") } } + /*maven { + url "https://cursemaven.com" + content { + includeGroup "curse.maven" + } + }*/ } dependencies { @@ -160,6 +166,9 @@ dependencies { implementation fg.deobf('maven.modrinth:oculus:1.20.1-1.6.9') implementation fg.deobf('maven.modrinth:embeddium:0.2.12+mc1.20.1') + // testing + //implementation fg.deobf("curse.maven:allthecompressed-514045:4938351") + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.2' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.2' } diff --git a/changelog.md b/changelog.md index df3658e7..b1a56868 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,12 @@ +## Ex Deorum 1.13 +- Added new icon for JEI compost recipes to help differentiate from the other categories. +- Added `sieve_mesh` property to KubeJS's RecipeFilter, for usage in `RecipesEventJS.remove` to remove sieve recipes using a specific mesh. View the [updated documentation](https://exdeorum.readthedocs.io/en/latest). +- Fixed bug with Ex Deorum recipes not being removable by KubeJS with the OutputFilter and InputFilter. +- Fixed water crucible not displaying leaves properly. +- Fixed crimson nylium spores displaying as warped nylium in the water crucible. +- Fixed sieves not rendering AllTheCompressed blocks properly. +- Optimized crucible/sieve rendering of solid contents. No more Guava cache! + ## Ex Deorum 1.12 - Added Wood Chippings, obtained by hammering logs. Usable as compost or as a crafting material for Sponges. - Added some more KubeJS functions. Check out the [new documentation](https://exdeorum.readthedocs.io/en/latest) for Ex Deorum. diff --git a/src/main/java/thedarkcolour/exdeorum/blockentity/AbstractCrucibleBlockEntity.java b/src/main/java/thedarkcolour/exdeorum/blockentity/AbstractCrucibleBlockEntity.java index cf7f3e68..9bce0941 100644 --- a/src/main/java/thedarkcolour/exdeorum/blockentity/AbstractCrucibleBlockEntity.java +++ b/src/main/java/thedarkcolour/exdeorum/blockentity/AbstractCrucibleBlockEntity.java @@ -242,17 +242,18 @@ public abstract class AbstractCrucibleBlockEntity extends EBlockEntity { overrides.put(EItems.GRASS_SEEDS.get(), Blocks.GRASS_BLOCK); overrides.put(EItems.MYCELIUM_SPORES.get(), Blocks.MYCELIUM); overrides.put(EItems.WARPED_NYLIUM_SPORES.get(), Blocks.WARPED_NYLIUM); - overrides.put(EItems.CRIMSON_NYLIUM_SPORES.get(), Blocks.WARPED_NYLIUM); + overrides.put(EItems.CRIMSON_NYLIUM_SPORES.get(), Blocks.CRIMSON_NYLIUM); for (var sapling : ForgeRegistries.BLOCKS.getEntries()) { - var key = sapling.getKey().location(); + var item = sapling.getValue().asItem(); + if (!overrides.containsKey(item)) { + var key = sapling.getKey().location(); - if (key.getPath().endsWith("sapling")) { - try { - var item = sapling.getValue().asItem(); - ForgeRegistries.BLOCKS.getValue(new ResourceLocation(key.getNamespace(), key.getPath().replace("sapling", "leaves"))); - overrides.put(item, Blocks.OAK_LEAVES); - } catch (Exception ignored) { + if (key.getPath().endsWith("sapling")) { + try { + overrides.put(item, ForgeRegistries.BLOCKS.getValue(new ResourceLocation(key.getNamespace(), key.getPath().replace("sapling", "leaves")))); + } catch (Exception ignored) { + } } } } diff --git a/src/main/java/thedarkcolour/exdeorum/blockentity/BarrelBlockEntity.java b/src/main/java/thedarkcolour/exdeorum/blockentity/BarrelBlockEntity.java index 167780e5..d8080766 100644 --- a/src/main/java/thedarkcolour/exdeorum/blockentity/BarrelBlockEntity.java +++ b/src/main/java/thedarkcolour/exdeorum/blockentity/BarrelBlockEntity.java @@ -150,7 +150,7 @@ public class BarrelBlockEntity extends EBlockEntity { return fluidType.getTemperature() > 575; } - private void spawnBurningParticles() { + private void spawnParticlesIfBurning() { if (isBurning()) { BlockPos pos = getBlockPos(); int burnTicks = (int) (progress * 300); @@ -430,6 +430,7 @@ public class BarrelBlockEntity extends EBlockEntity { } } + // Try to perform a fluid transformation recipe if (barrel.tank.getFluid().getFluid().getFluidType() == ForgeMod.WATER_TYPE.get()) { if (mycelium == 0 && state.ignitedByLava() && rand.nextInt(500) == 0) { var randomPos = pos.offset(rand.nextIntBetweenInclusive(-MOSS_SPREAD_RANGE, MOSS_SPREAD_RANGE), -1, rand.nextIntBetweenInclusive(-MOSS_SPREAD_RANGE, MOSS_SPREAD_RANGE)); @@ -475,7 +476,7 @@ public class BarrelBlockEntity extends EBlockEntity { } } } else { - barrel.spawnBurningParticles(); + barrel.spawnParticlesIfBurning(); } } } diff --git a/src/main/java/thedarkcolour/exdeorum/blockentity/SieveBlockEntity.java b/src/main/java/thedarkcolour/exdeorum/blockentity/SieveBlockEntity.java index 1ab9205a..fbbdfa7f 100644 --- a/src/main/java/thedarkcolour/exdeorum/blockentity/SieveBlockEntity.java +++ b/src/main/java/thedarkcolour/exdeorum/blockentity/SieveBlockEntity.java @@ -115,7 +115,8 @@ public class SieveBlockEntity extends EBlockEntity { if (contents.isEmpty()) { // Insert an item if (!isClientSide) { - if (RecipeUtil.hasSieveResult(level.getRecipeManager(), mesh.getItem(), playerItem)) { + // If the input has any sieve drops, insert it into the mesh + if (!RecipeUtil.getSieveRecipes(mesh.getItem(), playerItem).isEmpty()) { playerItem = this.insertContents(player, hand); markUpdated(); diff --git a/src/main/java/thedarkcolour/exdeorum/client/ClientHandler.java b/src/main/java/thedarkcolour/exdeorum/client/ClientHandler.java index 6708d0a5..e3351cca 100644 --- a/src/main/java/thedarkcolour/exdeorum/client/ClientHandler.java +++ b/src/main/java/thedarkcolour/exdeorum/client/ClientHandler.java @@ -21,7 +21,6 @@ package thedarkcolour.exdeorum.client; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.DefaultVertexFormat; import net.minecraft.client.Minecraft; -import net.minecraft.client.Timer; import net.minecraft.client.gui.screens.worldselection.CreateWorldScreen; import net.minecraft.client.gui.screens.worldselection.WorldCreationUiState; import net.minecraft.client.renderer.ItemBlockRenderTypes; @@ -32,12 +31,13 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.util.Unit; import net.minecraftforge.client.event.ClientPlayerNetworkEvent; import net.minecraftforge.client.event.EntityRenderersEvent; +import net.minecraftforge.client.event.ModelEvent; import net.minecraftforge.client.event.RegisterClientReloadListenersEvent; import net.minecraftforge.client.event.RegisterShadersEvent; import net.minecraftforge.client.event.ScreenEvent; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.TagsUpdatedEvent; -import net.minecraftforge.eventbus.api.Event; +import net.minecraftforge.fml.ModList; import net.minecraftforge.fml.event.config.ModConfigEvent; import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; @@ -46,6 +46,7 @@ import thedarkcolour.exdeorum.client.ter.BarrelRenderer; import thedarkcolour.exdeorum.client.ter.CrucibleRenderer; import thedarkcolour.exdeorum.client.ter.InfestedLeavesRenderer; import thedarkcolour.exdeorum.client.ter.SieveRenderer; +import thedarkcolour.exdeorum.compat.ModIds; import thedarkcolour.exdeorum.config.EConfig; import thedarkcolour.exdeorum.network.ClientMessageHandler; import thedarkcolour.exdeorum.recipe.RecipeUtil; @@ -56,6 +57,9 @@ import thedarkcolour.exdeorum.registry.EWorldPresets; import java.io.IOException; public class ClientHandler { + // Used for the composting recipe category in JEI + public static final ResourceLocation OAK_BARREL_COMPOSTING = new ResourceLocation(ExDeorum.ID, "item/oak_barrel_composting"); + // This is set to true whenever the server tells a client to do so, then set back to false after cache is refreshed. public static boolean needsRecipeCacheRefresh; public static void register() { @@ -71,6 +75,10 @@ public class ClientHandler { fmlBus.addListener(ClientHandler::onPlayerLogout); fmlBus.addListener(ClientHandler::onScreenOpen); fmlBus.addListener(ClientHandler::onTagsUpdated); + + if (ModList.get().isLoaded(ModIds.JEI)) { + modBus.addListener(ClientHandler::registerAdditionalModels); + } } private static void onTagsUpdated(TagsUpdatedEvent event) { @@ -90,6 +98,12 @@ public class ClientHandler { event.enqueueWork(ClientHandler::setRenderLayers); } + private static void setRenderLayers() { + // Fluids + ItemBlockRenderTypes.setRenderLayer(EFluids.WITCH_WATER.get(), RenderType.translucent()); + ItemBlockRenderTypes.setRenderLayer(EFluids.WITCH_WATER_FLOWING.get(), RenderType.translucent()); + } + private static void onPlayerRespawn(ClientPlayerNetworkEvent.Clone event) { if (ClientMessageHandler.isInVoidWorld) { ClientMessageHandler.disableVoidFogRendering(); @@ -138,9 +152,9 @@ public class ClientHandler { } } - private static void setRenderLayers() { - // Fluids - ItemBlockRenderTypes.setRenderLayer(EFluids.WITCH_WATER.get(), RenderType.translucent()); - ItemBlockRenderTypes.setRenderLayer(EFluids.WITCH_WATER_FLOWING.get(), RenderType.translucent()); + // Only called when JEI is loaded, because this registers the recipe category icon models. + private static void registerAdditionalModels(ModelEvent.RegisterAdditional event) { + event.register(new ResourceLocation(ExDeorum.ID, "block/oak_barrel_composting")); + event.register(OAK_BARREL_COMPOSTING); } } diff --git a/src/main/java/thedarkcolour/exdeorum/client/RenderFace.java b/src/main/java/thedarkcolour/exdeorum/client/RenderFace.java new file mode 100644 index 00000000..bfcc1466 --- /dev/null +++ b/src/main/java/thedarkcolour/exdeorum/client/RenderFace.java @@ -0,0 +1,80 @@ +/* + * Ex Deorum + * Copyright (c) 2024 thedarkcolour + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package thedarkcolour.exdeorum.client; + +import com.mojang.blaze3d.vertex.PoseStack; +import it.unimi.dsi.fastutil.Pair; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; + +import java.util.List; + +public interface RenderFace { + void renderFlatSprite(MultiBufferSource buffers, PoseStack stack, float y, int r, int g, int b, int light, float edge); + + void renderFlatSpriteLerp(MultiBufferSource buffers, PoseStack stack, float percentage, int r, int g, int b, int light, float edge, float minY, float maxY); + + boolean isMissingTexture(); + + record Single(RenderType renderType, TextureAtlasSprite sprite, boolean isMissingTexture) implements RenderFace { + public Single(RenderType renderType, TextureAtlasSprite sprite) { + this(renderType, sprite, RenderUtil.isMissingTexture(sprite)); + } + @Override + public void renderFlatSprite(MultiBufferSource buffers, PoseStack stack, float y, int r, int g, int b, int light, float edge) { + RenderUtil.renderFlatSprite(buffers.getBuffer(this.renderType), stack, y, r, g, b, this.sprite, light, edge); + } + + @Override + public void renderFlatSpriteLerp(MultiBufferSource buffers, PoseStack stack, float percentage, int r, int g, int b, int light, float edge, float minY, float maxY) { + RenderUtil.renderFlatSpriteLerp(buffers.getBuffer(this.renderType), stack, percentage, r, g, b, this.sprite, light, edge, minY, maxY); + } + } + + record Composite(List> layers, boolean isMissingTexture) implements RenderFace { + public Composite(List> layers) { + this(layers, areAnyMissing(layers)); + } + + @Override + public void renderFlatSprite(MultiBufferSource buffers, PoseStack stack, float y, int r, int g, int b, int light, float edge) { + for (var layer : this.layers) { + RenderUtil.renderFlatSprite(buffers.getBuffer(layer.first()), stack, y, r, g, b, layer.second(), light, edge); + } + } + + @Override + public void renderFlatSpriteLerp(MultiBufferSource buffers, PoseStack stack, float percentage, int r, int g, int b, int light, float edge, float minY, float maxY) { + for (var layer : this.layers) { + RenderUtil.renderFlatSpriteLerp(buffers.getBuffer(layer.first()), stack, percentage, r, g, b, layer.second(), light, edge, minY, maxY); + } + } + + private static boolean areAnyMissing(List> layers) { + for (var layer : layers) { + if (RenderUtil.isMissingTexture(layer.second())) { + return true; + } + } + + return false; + } + } +} diff --git a/src/main/java/thedarkcolour/exdeorum/client/RenderUtil.java b/src/main/java/thedarkcolour/exdeorum/client/RenderUtil.java index db38981b..71f85341 100644 --- a/src/main/java/thedarkcolour/exdeorum/client/RenderUtil.java +++ b/src/main/java/thedarkcolour/exdeorum/client/RenderUtil.java @@ -18,14 +18,13 @@ package thedarkcolour.exdeorum.client; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import com.mojang.blaze3d.vertex.VertexFormat; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.Pair; import net.irisshaders.iris.api.v0.IrisApi; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.MultiBufferSource; @@ -40,14 +39,14 @@ import net.minecraft.client.resources.model.BakedModel; import net.minecraft.core.BlockPos; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.Mth; +import net.minecraft.util.RandomSource; import net.minecraft.world.inventory.InventoryMenu; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.levelgen.LegacyRandomSource; import net.minecraft.world.level.material.Fluid; import net.minecraftforge.client.extensions.common.IClientFluidTypeExtensions; +import net.minecraftforge.client.model.CompositeModel; import net.minecraftforge.client.model.data.ModelData; import net.minecraftforge.registries.ForgeRegistries; import org.joml.Vector3f; @@ -55,64 +54,34 @@ import thedarkcolour.exdeorum.ExDeorum; import thedarkcolour.exdeorum.client.ter.SieveRenderer; import java.awt.Color; -import java.util.Map; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; +import java.util.IdentityHashMap; public class RenderUtil { - public static final LoadingCache TOP_RENDER_TYPES; - public static final LoadingCache TOP_TEXTURES; + private static final VarHandle COMPOSITE_MODEL_CHILDREN; + private static final IdentityHashMap TOP_FACES = new IdentityHashMap<>(); public static final RenderStateShard.ShaderStateShard RENDER_TYPE_TINTED_CUTOUT_MIPPED_SHADER = new RenderStateShard.ShaderStateShard(RenderUtil::getRenderTypeTintedCutoutMippedShader); public static final RenderType TINTED_CUTOUT_MIPPED = RenderType.create(ExDeorum.ID + ":tinted_cutout_mipped", DefaultVertexFormat.NEW_ENTITY, VertexFormat.Mode.QUADS, RenderType.SMALL_BUFFER_SIZE, false, false, RenderType.CompositeState.builder().setLightmapState(RenderStateShard.LIGHTMAP).setShaderState(RENDER_TYPE_TINTED_CUTOUT_MIPPED_SHADER).setTextureState(RenderStateShard.BLOCK_SHEET_MIPPED).createCompositeState(true)); public static TextureAtlas blockAtlas; public static ShaderInstance renderTypeTintedCutoutMippedShader; - private static final Map LEAF_BAKED_MODELS = new Object2ObjectOpenHashMap<>(); public static final IrisAccess IRIS_ACCESS; static { - // todo remove these caches, google cache is slow - TOP_RENDER_TYPES = CacheBuilder.newBuilder().maximumSize(10).build(new CacheLoader<>() { - @Override - public RenderType load(Block key) { - var rand = new LegacyRandomSource(key.hashCode()); - var blockTypes = Minecraft.getInstance().getBlockRenderer().getBlockModel(key.defaultBlockState()).getRenderTypes(key.defaultBlockState(), rand, ModelData.EMPTY); - return RenderType.chunkBufferLayers().stream().filter(blockTypes::contains).findFirst().get(); - } - }); - TOP_TEXTURES = CacheBuilder.newBuilder().weakValues().build(new CacheLoader<>() { - @Override - public TextureAtlasSprite load(Block key) { - var registryName = ForgeRegistries.BLOCKS.getKey(key); - var blockLoc = registryName.withPrefix("block/"); - var sprite = blockAtlas.getSprite(blockLoc); - // for stuff like azalea bush, retry to get the top texture - if (isMissingTexture(sprite)) { - blockLoc = new ResourceLocation(registryName.getNamespace(), "block/" + registryName.getPath() + "_top"); - sprite = blockAtlas.getSprite(blockLoc); - } - return sprite; - } - }); - IrisAccess irisAccess; try { Class.forName("net.irisshaders.iris.api.v0.IrisApi"); - irisAccess = () -> IrisApi.getInstance().isShaderPackInUse(); + irisAccess = IrisApi.getInstance()::isShaderPackInUse; } catch (ClassNotFoundException e) { irisAccess = () -> false; } IRIS_ACCESS = irisAccess; - } - public static boolean isMissingTexture(TextureAtlasSprite sprite) { - return sprite.contents().name() == MissingTextureAtlasSprite.getLocation(); - } - - public static TextureAtlasSprite getTopTexture(Block block, Block defaultBlock) { - var sprite = TOP_TEXTURES.getUnchecked(block); - - if (isMissingTexture(sprite)) { - return TOP_TEXTURES.getUnchecked(defaultBlock); - } else { - return sprite; + var lookup = MethodHandles.lookup(); + try { + COMPOSITE_MODEL_CHILDREN = MethodHandles.privateLookupIn(CompositeModel.Baked.class, lookup).findVarHandle(CompositeModel.Baked.class, "children", ImmutableMap.class); + } catch (NoSuchFieldException | IllegalAccessException e) { + throw new RuntimeException(e); } } @@ -122,9 +91,75 @@ public class RenderUtil { } public static void invalidateCaches() { - SieveRenderer.MESH_TEXTURES.invalidateAll(); + SieveRenderer.MESH_TEXTURES.clear(); + TOP_FACES.clear(); blockAtlas = null; - LEAF_BAKED_MODELS.clear(); + } + + public static RenderFace getTopFaceOrDefault(Block block, Block defaultBlock) { + var face = getTopFace(block); + if (face.isMissingTexture()) { + return getTopFace(defaultBlock); + } else { + return face; + } + } + + public static RenderFace getTopFace(Block block) { + if (TOP_FACES.containsKey(block)) { + return TOP_FACES.get(block); + } else { + var rand = new LegacyRandomSource(block.hashCode()); + BakedModel model = Minecraft.getInstance().getBlockRenderer().getBlockModel(block.defaultBlockState()); + RenderFace face; + + if (model instanceof CompositeModel.Baked composite) { + @SuppressWarnings("unchecked") + ImmutableMap children = (ImmutableMap) COMPOSITE_MODEL_CHILDREN.get(composite); + var builder = new ImmutableList.Builder>(); + + for (var childModel : children.values()) { + var singleFace = getFaceFromModel(block, rand, childModel); + builder.add(Pair.of(singleFace.renderType(), singleFace.sprite())); + } + + face = new RenderFace.Composite(builder.build()); + } else { + face = getFaceFromModel(block, rand, model); + } + + TOP_FACES.put(block, face); + + return face; + } + } + + private static RenderFace.Single getFaceFromModel(Block block, RandomSource rand, BakedModel model) { + var texture = getTopTexture(block, model); + var blockTypes = model.getRenderTypes(block.defaultBlockState(), rand, ModelData.EMPTY); + for (var bufferLayer : RenderType.chunkBufferLayers()) { + if (blockTypes.contains(bufferLayer)) { + return new RenderFace.Single(bufferLayer, texture); + } + } + throw new IllegalStateException("No render type found for block " + block); + } + + private static TextureAtlasSprite getTopTexture(Block block, BakedModel model) { + var registryName = ForgeRegistries.BLOCKS.getKey(block); + var sprite = blockAtlas.getSprite(registryName.withPrefix("block/")); + // for stuff like azalea bush, retry to get the top texture + if (isMissingTexture(sprite)) { + sprite = blockAtlas.getSprite(new ResourceLocation(registryName.getNamespace(), "block/" + registryName.getPath() + "_top")); + } + if (isMissingTexture(sprite)) { + sprite = model.getParticleIcon(ModelData.EMPTY); + } + return sprite; + } + + public static boolean isMissingTexture(TextureAtlasSprite sprite) { + return sprite.contents().name() == MissingTextureAtlasSprite.getLocation(); } public static void renderFlatFluidSprite(MultiBufferSource buffers, PoseStack stack, Level level, BlockPos pos, float y, float edge, int light, int r, int g, int b, Fluid fluid) { diff --git a/src/main/java/thedarkcolour/exdeorum/client/ter/CrucibleRenderer.java b/src/main/java/thedarkcolour/exdeorum/client/ter/CrucibleRenderer.java index 0c7e7746..67426080 100644 --- a/src/main/java/thedarkcolour/exdeorum/client/ter/CrucibleRenderer.java +++ b/src/main/java/thedarkcolour/exdeorum/client/ter/CrucibleRenderer.java @@ -23,7 +23,6 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; import net.minecraft.util.Mth; -import net.minecraftforge.client.extensions.common.IClientFluidTypeExtensions; import net.minecraftforge.common.capabilities.ForgeCapabilities; import thedarkcolour.exdeorum.blockentity.AbstractCrucibleBlockEntity; import thedarkcolour.exdeorum.client.RenderUtil; @@ -52,14 +51,15 @@ public class CrucibleRenderer implements BlockEntityRenderer> 16) & 0xff, (color >> 8) & 0xff, color & 0xff, fluid); } if (solids != 0) { - var builder = buffers.getBuffer(RenderUtil.TOP_RENDER_TYPES.getUnchecked(crucible.getLastMelted())); - var sprite = RenderUtil.getTopTexture(crucible.getLastMelted(), crucible.getDefaultMeltBlock()); + // LastMelted is not null if solids is nonzero + @SuppressWarnings("DataFlowIssue") + var face = RenderUtil.getTopFaceOrDefault(crucible.getLastMelted(), crucible.getDefaultMeltBlock()); var color = Minecraft.getInstance().getBlockColors().getColor(crucible.getLastMelted().defaultBlockState(), level, pos, 0); if (color == -1) color = 0xffffff; - RenderUtil.renderFlatSpriteLerp(builder, stack, solids, (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff, sprite, light, 2.0f, 4.0f, 14.0f); + face.renderFlatSpriteLerp(buffers, stack, solids, (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff, light, 2.0f, 4.0f, 14.0f); } } }); diff --git a/src/main/java/thedarkcolour/exdeorum/client/ter/SieveRenderer.java b/src/main/java/thedarkcolour/exdeorum/client/ter/SieveRenderer.java index aec0a6be..cdb74d5b 100644 --- a/src/main/java/thedarkcolour/exdeorum/client/ter/SieveRenderer.java +++ b/src/main/java/thedarkcolour/exdeorum/client/ter/SieveRenderer.java @@ -18,9 +18,6 @@ package thedarkcolour.exdeorum.client.ter; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; @@ -34,15 +31,11 @@ import net.minecraftforge.registries.ForgeRegistries; import thedarkcolour.exdeorum.blockentity.SieveBlockEntity; import thedarkcolour.exdeorum.client.RenderUtil; +import java.util.IdentityHashMap; +import java.util.Map; + public class SieveRenderer implements BlockEntityRenderer { - public static final LoadingCache MESH_TEXTURES = CacheBuilder.newBuilder().build(new CacheLoader<>() { - @Override - public TextureAtlasSprite load(Item key) { - ResourceLocation registryName = ForgeRegistries.ITEMS.getKey(key); - var textureLoc = registryName.withPrefix("item/mesh/"); - return RenderUtil.blockAtlas.getSprite(textureLoc); - } - }); + public static final Map MESH_TEXTURES = new IdentityHashMap<>(); public SieveRenderer(BlockEntityRendererProvider.Context ctx) {} @@ -53,17 +46,26 @@ public class SieveRenderer implements BlockEntityRenderer { if (!contents.isEmpty() && contents.getItem() instanceof BlockItem blockItem) { var block = blockItem.getBlock(); var percentage = (float) sieve.getProgress() / 100.0f; - var builder = buffers.getBuffer(RenderUtil.TOP_RENDER_TYPES.getUnchecked(block)); - var sprite = RenderUtil.TOP_TEXTURES.getUnchecked(block); - - RenderUtil.renderFlatSpriteLerp(builder, stack, percentage, 0xff, 0xff, 0xff, sprite, light, 1.0f, 13f, 15f); + var face = RenderUtil.getTopFace(block); + face.renderFlatSpriteLerp(buffers, stack, percentage, 0xff, 0xff, 0xff, light, 1.0f, 13f, 15f); } var mesh = sieve.getMesh(); if (!mesh.isEmpty()) { var builder = buffers.getBuffer(RenderType.cutoutMipped()); - var sprite = MESH_TEXTURES.getUnchecked(mesh.getItem()); + var meshItem = mesh.getItem(); + + TextureAtlasSprite sprite; + if (MESH_TEXTURES.containsKey(meshItem)) { + sprite = MESH_TEXTURES.get(meshItem); + } else { + ResourceLocation registryName = ForgeRegistries.ITEMS.getKey(meshItem); + ResourceLocation textureLoc = registryName.withPrefix("item/mesh/"); + sprite = RenderUtil.blockAtlas.getSprite(textureLoc); + MESH_TEXTURES.put(meshItem, sprite); + } + RenderUtil.renderFlatSprite(builder, stack, 0.75f, 0xff, 0xff, 0xff, sprite, light, 1f); if (mesh.hasFoil()) { diff --git a/src/main/java/thedarkcolour/exdeorum/compat/ModIds.java b/src/main/java/thedarkcolour/exdeorum/compat/ModIds.java index 52df9997..d35c1701 100644 --- a/src/main/java/thedarkcolour/exdeorum/compat/ModIds.java +++ b/src/main/java/thedarkcolour/exdeorum/compat/ModIds.java @@ -42,4 +42,5 @@ public class ModIds { public static final String BLUE_SKIES = "blue_skies"; public static final String PAMS_HARVESTCRAFT_CROPS = "pamhc2crops"; public static final String NUCLEARCRAFT_NEOTERIC = "nuclearcraft"; + public static final String JEI = "jei"; } diff --git a/src/main/java/thedarkcolour/exdeorum/compat/jei/BarrelCompostCategory.java b/src/main/java/thedarkcolour/exdeorum/compat/jei/BarrelCompostCategory.java index 5d1ad834..9f7977ce 100644 --- a/src/main/java/thedarkcolour/exdeorum/compat/jei/BarrelCompostCategory.java +++ b/src/main/java/thedarkcolour/exdeorum/compat/jei/BarrelCompostCategory.java @@ -18,6 +18,8 @@ package thedarkcolour.exdeorum.compat.jei; +import com.mojang.blaze3d.platform.Lighting; +import com.mojang.blaze3d.systems.RenderSystem; import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; import mezz.jei.api.gui.drawable.IDrawable; import mezz.jei.api.gui.ingredient.IRecipeSlotsView; @@ -26,13 +28,20 @@ import mezz.jei.api.recipe.IFocusGroup; import mezz.jei.api.recipe.RecipeIngredientRole; import mezz.jei.api.recipe.RecipeType; import mezz.jei.api.recipe.category.IRecipeCategory; +import net.minecraft.CrashReport; +import net.minecraft.CrashReportCategory; +import net.minecraft.ReportedException; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.network.chat.Component; +import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.item.ItemStack; +import org.joml.Matrix4f; +import thedarkcolour.exdeorum.client.ClientHandler; import thedarkcolour.exdeorum.data.TranslationKeys; import thedarkcolour.exdeorum.recipe.barrel.BarrelCompostRecipe; -import thedarkcolour.exdeorum.registry.EBlocks; +import thedarkcolour.exdeorum.registry.EItems; class BarrelCompostCategory implements IRecipeCategory { public static final int WIDTH = 120; @@ -46,8 +55,7 @@ class BarrelCompostCategory implements IRecipeCategory { public BarrelCompostCategory(IGuiHelper helper) { this.background = helper.createBlankDrawable(WIDTH, HEIGHT); this.slot = helper.getSlotDrawable(); - // todo add a little dirt icon in the bottom corner to differentiate between compost and mixing - this.icon = helper.createDrawableItemStack(new ItemStack(EBlocks.OAK_BARREL.get())); + this.icon = new DrawableIcon(); this.title = Component.translatable(TranslationKeys.BARREL_COMPOST_CATEGORY_TITLE); } @@ -85,4 +93,61 @@ class BarrelCompostCategory implements IRecipeCategory { graphics.drawString(Minecraft.getInstance().font, volumeLabel, 24, 5, 0xff808080, false); } + + private static class DrawableIcon implements IDrawable { + private final ItemStack oakBarrel = new ItemStack(EItems.OAK_BARREL.get()); + + @Override + public int getWidth() { + return 16; + } + + @Override + public int getHeight() { + return 16; + } + + @Override + public void draw(GuiGraphics guiGraphics, int xOffset, int yOffset) { + // From mezz.jei.library.render.ItemStackRenderer + RenderSystem.enableDepthTest(); + + // From GuiGraphics.renderFakeItem + Minecraft mc = Minecraft.getInstance(); + var model = mc.getModelManager().getModel(ClientHandler.OAK_BARREL_COMPOSTING); + var pose = guiGraphics.pose(); + pose.pushPose(); + pose.translate(8 + xOffset, 8 + yOffset, 150); + + try { + pose.mulPoseMatrix((new Matrix4f()).scaling(1.0F, -1.0F, 1.0F)); + pose.scale(16f, 16f, 16f); + boolean flag = !model.usesBlockLight(); + if (flag) { + Lighting.setupForFlatItems(); + } + + mc.getItemRenderer().render(oakBarrel, ItemDisplayContext.GUI, false, pose, guiGraphics.bufferSource(), 0xf000f0, OverlayTexture.NO_OVERLAY, model); + guiGraphics.flush(); + if (flag) { + Lighting.setupFor3DItems(); + } + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Rendering item"); + CrashReportCategory crashreportcategory = crashreport.addCategory("Item being rendered"); + crashreportcategory.setDetail("Item Type", () -> { + return String.valueOf(oakBarrel.getItem()); + }); + crashreportcategory.setDetail("Registry Name", () -> "exdeorum:oak_barrel"); + throw new ReportedException(crashreport); + } + + pose.popPose(); + + // From end of ItemStackRenderer + RenderSystem.disableBlend(); + // From end of DrawableIngredient + RenderSystem.disableDepthTest(); + } + } } diff --git a/src/main/java/thedarkcolour/exdeorum/compat/jei/BarrelMixingCategory.java b/src/main/java/thedarkcolour/exdeorum/compat/jei/BarrelMixingCategory.java index 64bab9cb..51f80ef7 100644 --- a/src/main/java/thedarkcolour/exdeorum/compat/jei/BarrelMixingCategory.java +++ b/src/main/java/thedarkcolour/exdeorum/compat/jei/BarrelMixingCategory.java @@ -27,15 +27,13 @@ import mezz.jei.api.recipe.RecipeIngredientRole; import mezz.jei.api.recipe.RecipeType; import mezz.jei.api.recipe.category.IRecipeCategory; import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.core.NonNullList; import net.minecraft.network.chat.Component; -import net.minecraft.world.Container; +import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; -import thedarkcolour.exdeorum.ExDeorum; import thedarkcolour.exdeorum.data.TranslationKeys; import thedarkcolour.exdeorum.recipe.barrel.BarrelFluidMixingRecipe; import thedarkcolour.exdeorum.recipe.barrel.BarrelMixingRecipe; -import thedarkcolour.exdeorum.registry.EBlocks; +import thedarkcolour.exdeorum.registry.EItems; public abstract class BarrelMixingCategory implements IRecipeCategory { public static final int WIDTH = 120; @@ -48,12 +46,12 @@ public abstract class BarrelMixingCategory implements IRecipeCategory { private final IDrawable icon; private final Component title; - public BarrelMixingCategory(IGuiHelper helper, IDrawable plus, IDrawable arrow, String titleKey) { + public BarrelMixingCategory(IGuiHelper helper, IDrawable plus, IDrawable arrow, String titleKey, Item iconItem) { this.background = helper.createBlankDrawable(WIDTH, HEIGHT); this.slot = helper.getSlotDrawable(); this.plus = plus; this.arrow = arrow; - this.icon = helper.createDrawableItemStack(new ItemStack(EBlocks.STONE_BARREL.get())); + this.icon = helper.createDrawableItemStack(new ItemStack(iconItem)); this.title = Component.translatable(titleKey); } @@ -83,7 +81,7 @@ public abstract class BarrelMixingCategory implements IRecipeCategory { public static class Items extends BarrelMixingCategory { public Items(IGuiHelper helper, IDrawable plus, IDrawable arrow) { - super(helper, plus, arrow, TranslationKeys.BARREL_MIXING_CATEGORY_TITLE); + super(helper, plus, arrow, TranslationKeys.BARREL_MIXING_CATEGORY_TITLE, EItems.OAK_BARREL.get()); } @Override @@ -101,7 +99,7 @@ public abstract class BarrelMixingCategory implements IRecipeCategory { public static class Fluids extends BarrelMixingCategory { public Fluids(IGuiHelper helper, IDrawable plus, IDrawable arrow) { - super(helper, plus, arrow, TranslationKeys.BARREL_FLUID_MIXING_CATEGORY_TITLE); + super(helper, plus, arrow, TranslationKeys.BARREL_FLUID_MIXING_CATEGORY_TITLE, EItems.STONE_BARREL.get()); } @Override diff --git a/src/main/java/thedarkcolour/exdeorum/compat/kubejs/ExDeorumKubeJsBindings.java b/src/main/java/thedarkcolour/exdeorum/compat/kubejs/ExDeorumKubeJsBindings.java index f92aa7c6..fc575ad7 100644 --- a/src/main/java/thedarkcolour/exdeorum/compat/kubejs/ExDeorumKubeJsBindings.java +++ b/src/main/java/thedarkcolour/exdeorum/compat/kubejs/ExDeorumKubeJsBindings.java @@ -20,6 +20,8 @@ package thedarkcolour.exdeorum.compat.kubejs; import com.mojang.brigadier.exceptions.CommandSyntaxException; import dev.latvian.mods.kubejs.recipe.RecipesEventJS; +import dev.latvian.mods.kubejs.recipe.ReplacementMatch; +import dev.latvian.mods.kubejs.recipe.filter.RecipeFilter; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import net.minecraft.commands.arguments.blocks.BlockStateParser; import net.minecraft.core.registries.BuiltInRegistries; @@ -31,6 +33,15 @@ import thedarkcolour.exdeorum.registry.ERecipeTypes; @SuppressWarnings("unused") class ExDeorumKubeJsBindings { + static { + RecipeFilter.PARSE.register((ctx, filters, map) -> { + var sieveMesh = map.get("sieve_mesh"); + if (sieveMesh != null) { + filters.add(new SieveMeshFilter(ReplacementMatch.of(sieveMesh))); + } + }); + } + public void setCrucibleHeatValue(Block block, int value) { setCrucibleHeatValueForBlock(block, value); } diff --git a/src/main/java/thedarkcolour/exdeorum/compat/kubejs/ExDeorumKubeJsPlugin.java b/src/main/java/thedarkcolour/exdeorum/compat/kubejs/ExDeorumKubeJsPlugin.java index 96375f39..4b630cb5 100644 --- a/src/main/java/thedarkcolour/exdeorum/compat/kubejs/ExDeorumKubeJsPlugin.java +++ b/src/main/java/thedarkcolour/exdeorum/compat/kubejs/ExDeorumKubeJsPlugin.java @@ -19,6 +19,7 @@ package thedarkcolour.exdeorum.compat.kubejs; import dev.latvian.mods.kubejs.KubeJSPlugin; +import dev.latvian.mods.kubejs.recipe.schema.RegisterRecipeSchemasEvent; import dev.latvian.mods.kubejs.script.BindingsEvent; import dev.latvian.mods.kubejs.script.ScriptType; import dev.latvian.mods.kubejs.util.ClassFilter; @@ -30,6 +31,12 @@ public class ExDeorumKubeJsPlugin extends KubeJSPlugin { event.add(ExDeorum.ID, new ExDeorumKubeJsBindings()); } + @Override + public void registerRecipeSchemas(RegisterRecipeSchemasEvent event) { + event.namespace("exdeorum") + .register("sieve", SieveRecipeSchema.SCHEMA); + } + @Override public void registerClasses(ScriptType type, ClassFilter filter) { super.registerClasses(type, filter); diff --git a/src/main/java/thedarkcolour/exdeorum/compat/kubejs/SieveMeshFilter.java b/src/main/java/thedarkcolour/exdeorum/compat/kubejs/SieveMeshFilter.java new file mode 100644 index 00000000..3c676e94 --- /dev/null +++ b/src/main/java/thedarkcolour/exdeorum/compat/kubejs/SieveMeshFilter.java @@ -0,0 +1,33 @@ +/* + * Ex Deorum + * Copyright (c) 2024 thedarkcolour + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package thedarkcolour.exdeorum.compat.kubejs; + +import dev.latvian.mods.kubejs.core.RecipeKJS; +import dev.latvian.mods.kubejs.recipe.ItemMatch; +import dev.latvian.mods.kubejs.recipe.RecipeJS; +import dev.latvian.mods.kubejs.recipe.ReplacementMatch; +import dev.latvian.mods.kubejs.recipe.filter.RecipeFilter; +import thedarkcolour.exdeorum.recipe.sieve.SieveRecipe; + +public record SieveMeshFilter(ReplacementMatch match) implements RecipeFilter { + @Override + public boolean test(RecipeKJS recipe) { + return match instanceof ItemMatch match && recipe instanceof RecipeJS recipeJs && recipeJs.getOriginalRecipe() instanceof SieveRecipe sieveRecipe && match.contains(sieveRecipe.mesh); + } +} diff --git a/src/main/java/thedarkcolour/exdeorum/compat/kubejs/SieveRecipeSchema.java b/src/main/java/thedarkcolour/exdeorum/compat/kubejs/SieveRecipeSchema.java new file mode 100644 index 00000000..1147396e --- /dev/null +++ b/src/main/java/thedarkcolour/exdeorum/compat/kubejs/SieveRecipeSchema.java @@ -0,0 +1,92 @@ +/* + * Ex Deorum + * Copyright (c) 2024 thedarkcolour + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package thedarkcolour.exdeorum.compat.kubejs; + +import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; +import dev.latvian.mods.kubejs.item.InputItem; +import dev.latvian.mods.kubejs.item.OutputItem; +import dev.latvian.mods.kubejs.recipe.ItemMatch; +import dev.latvian.mods.kubejs.recipe.RecipeJS; +import dev.latvian.mods.kubejs.recipe.RecipeKey; +import dev.latvian.mods.kubejs.recipe.ReplacementMatch; +import dev.latvian.mods.kubejs.recipe.component.ComponentRole; +import dev.latvian.mods.kubejs.recipe.component.ItemComponents; +import dev.latvian.mods.kubejs.recipe.component.RecipeComponent; +import dev.latvian.mods.kubejs.recipe.schema.RecipeSchema; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.registries.ForgeRegistries; + +public interface SieveRecipeSchema { + RecipeComponent OUTPUT_ITEM_ONLY = new RecipeComponent<>() { + @Override + public String componentType() { + return "output_item_only"; + } + + @Override + public ComponentRole role() { + return ComponentRole.OUTPUT; + } + + @Override + public Class componentClass() { + return OutputItem.class; + } + + @Override + public boolean hasPriority(RecipeJS recipe, Object from) { + return recipe.outputItemHasPriority(from); + } + + @Override + public JsonElement write(RecipeJS recipe, OutputItem value) { + return new JsonPrimitive(ForgeRegistries.ITEMS.getKey(value.item.getItem()).toString()); + } + + @Override + public OutputItem read(RecipeJS recipe, Object from) { + if (from instanceof JsonPrimitive primitive && primitive.isString()) { + return OutputItem.of(new ItemStack(ForgeRegistries.ITEMS.getValue(new ResourceLocation(primitive.getAsString())))); + } else { + return OutputItem.of(from); + } + } + + @Override + public boolean isOutput(RecipeJS recipe, OutputItem value, ReplacementMatch match) { + return match instanceof ItemMatch m && !value.isEmpty() && m.contains(value.item); + } + + @Override + public String checkEmpty(RecipeKey key, OutputItem value) { + if (value.isEmpty()) { + return "ItemStack '" + key.name + "' can't be empty"; + } + + return ""; + } + }; + + RecipeKey RESULT = OUTPUT_ITEM_ONLY.key("result"); + RecipeKey INGREDIENT = ItemComponents.INPUT.key("ingredient"); + + RecipeSchema SCHEMA = new RecipeSchema(RESULT, INGREDIENT).uniqueOutputId(RESULT); +} diff --git a/src/main/java/thedarkcolour/exdeorum/recipe/ProbabilityRecipe.java b/src/main/java/thedarkcolour/exdeorum/recipe/ProbabilityRecipe.java index 0a6a951c..5691e063 100644 --- a/src/main/java/thedarkcolour/exdeorum/recipe/ProbabilityRecipe.java +++ b/src/main/java/thedarkcolour/exdeorum/recipe/ProbabilityRecipe.java @@ -18,8 +18,10 @@ package thedarkcolour.exdeorum.recipe; +import net.minecraft.core.RegistryAccess; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.level.storage.loot.providers.number.NumberProvider; @@ -32,4 +34,9 @@ public abstract class ProbabilityRecipe extends SingleIngredientRecipe { this.result = result; this.resultAmount = resultAmount; } + + @Override + public ItemStack getResultItem(RegistryAccess access) { + return new ItemStack(this.result); + } } diff --git a/src/main/java/thedarkcolour/exdeorum/recipe/RecipeUtil.java b/src/main/java/thedarkcolour/exdeorum/recipe/RecipeUtil.java index 4e1edd4b..94091a2d 100644 --- a/src/main/java/thedarkcolour/exdeorum/recipe/RecipeUtil.java +++ b/src/main/java/thedarkcolour/exdeorum/recipe/RecipeUtil.java @@ -259,21 +259,13 @@ public final class RecipeUtil { } } - public static boolean hasSieveResult(RecipeManager recipes, Item mesh, ItemStack stack) { - for (var recipe : byType(recipes, ERecipeTypes.SIEVE.get())) { - if (recipe.test(mesh, stack)) { - return true; - } - } - - return false; - } - public static boolean isCompostable(ItemStack stack) { return barrelCompostRecipeCache != null && barrelCompostRecipeCache.getRecipe(stack) != null; } - public static @Nullable BarrelMixingRecipe getBarrelMixingRecipe(RecipeManager recipes, ItemStack stack, FluidStack fluid) { + // todo stop using the RecipeManager + @Nullable + public static BarrelMixingRecipe getBarrelMixingRecipe(RecipeManager recipes, ItemStack stack, FluidStack fluid) { for (var recipe : byType(recipes, ERecipeTypes.BARREL_MIXING.get())) { if (recipe.matches(stack, fluid)) { return recipe; @@ -283,6 +275,16 @@ public final class RecipeUtil { return null; } + @Nullable + public static BarrelFluidMixingRecipe getFluidMixingRecipe(FluidStack base, Fluid additive) { + var recipe = barrelFluidMixingRecipeCache.getRecipe(base.getFluid(), additive); + if (recipe != null && base.getAmount() >= recipe.baseFluidAmount) { + return recipe; + } else { + return null; + } + } + public static double getExpectedValue(NumberProvider provider) { if (provider instanceof ConstantValue constant) { return constant.value; @@ -299,14 +301,4 @@ public final class RecipeUtil { public static boolean isTagEmpty(TagKey tag) { return BuiltInRegistries.ITEM.getTag(tag).map(set -> !set.iterator().hasNext()).orElse(PreferredOres.getPreferredOre(tag) == Items.AIR); } - - @Nullable - public static BarrelFluidMixingRecipe getFluidMixingRecipe(FluidStack base, Fluid additive) { - var recipe = barrelFluidMixingRecipeCache.getRecipe(base.getFluid(), additive); - if (recipe != null && base.getAmount() >= recipe.baseFluidAmount) { - return recipe; - } else { - return null; - } - } } diff --git a/src/main/java/thedarkcolour/exdeorum/recipe/barrel/BarrelMixingRecipe.java b/src/main/java/thedarkcolour/exdeorum/recipe/barrel/BarrelMixingRecipe.java index 0801ec26..9d45f6b6 100644 --- a/src/main/java/thedarkcolour/exdeorum/recipe/barrel/BarrelMixingRecipe.java +++ b/src/main/java/thedarkcolour/exdeorum/recipe/barrel/BarrelMixingRecipe.java @@ -19,6 +19,7 @@ package thedarkcolour.exdeorum.recipe.barrel; import com.google.gson.JsonObject; +import net.minecraft.core.RegistryAccess; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.GsonHelper; @@ -61,6 +62,11 @@ public class BarrelMixingRecipe extends SingleIngredientRecipe { return ingredient.test(item) && fluid.getFluid() == this.fluid && fluid.getAmount() >= fluidAmount; } + @Override + public ItemStack getResultItem(RegistryAccess access) { + return new ItemStack(this.result); + } + @Override public RecipeSerializer getSerializer() { return ERecipeSerializers.BARREL_MIXING.get(); diff --git a/src/main/java/thedarkcolour/exdeorum/recipe/sieve/SieveRecipe.java b/src/main/java/thedarkcolour/exdeorum/recipe/sieve/SieveRecipe.java index 75d70426..4b72986e 100644 --- a/src/main/java/thedarkcolour/exdeorum/recipe/sieve/SieveRecipe.java +++ b/src/main/java/thedarkcolour/exdeorum/recipe/sieve/SieveRecipe.java @@ -50,10 +50,6 @@ public class SieveRecipe extends ProbabilityRecipe { this.mesh = mesh; } - public boolean test(Item mesh, ItemStack item) { - return this.mesh == mesh && getIngredient().test(item); - } - @Override public RecipeSerializer getSerializer() { return ERecipeSerializers.SIEVE.get(); diff --git a/src/main/resources/assets/exdeorum/models/block/oak_barrel_composting.json b/src/main/resources/assets/exdeorum/models/block/oak_barrel_composting.json new file mode 100644 index 00000000..0bdb9017 --- /dev/null +++ b/src/main/resources/assets/exdeorum/models/block/oak_barrel_composting.json @@ -0,0 +1,68 @@ +{ + "parent": "block/block", + "textures": { + "barrel": "minecraft:block/oak_planks", + "dirt": "minecraft:block/dirt" + }, + "elements": [ + { + "from": [1, 0, 1], + "to": [2, 16, 15], + "faces": { + "north": {"uv": [14, 0, 15, 16], "texture": "#barrel"}, + "east": {"uv": [1, 0, 15, 16], "texture": "#barrel"}, + "south": {"uv": [1, 0, 2, 16], "texture": "#barrel"}, + "west": {"uv": [1, 0, 15, 16], "texture": "#barrel"}, + "up": {"uv": [14, 1, 15, 15], "texture": "#barrel", "cullface": "up"}, + "down": {"uv": [1, 1, 2, 15], "texture": "#barrel", "cullface": "down"} + } + }, + { + "from": [2, 0, 2], + "to": [14, 1, 14], + "faces": { + "up": {"uv": [2, 2, 14, 14], "texture": "#barrel"}, + "down": {"uv": [14, 2, 2, 14], "texture": "#barrel", "cullface": "down"} + } + }, + { + "from": [2, 0, 14], + "to": [14, 16, 15], + "faces": { + "north": {"uv": [2, 0, 14, 16], "texture": "#barrel"}, + "south": {"uv": [2, 0, 14, 16], "texture": "#barrel"}, + "up": {"uv": [2, 1, 14, 2], "texture": "#barrel", "cullface": "up"}, + "down": {"uv": [2, 1, 14, 2], "texture": "#barrel", "cullface": "down"} + } + }, + { + "from": [2, 0, 1], + "to": [14, 16, 2], + "faces": { + "north": {"uv": [2, 0, 14, 16], "texture": "#barrel"}, + "south": {"uv": [2, 0, 14, 16], "texture": "#barrel"}, + "up": {"uv": [2, 14, 14, 15], "texture": "#barrel", "cullface": "up"}, + "down": {"uv": [2, 14, 14, 15], "texture": "#barrel", "cullface": "down"} + } + }, + { + "from": [14, 0, 1], + "to": [15, 16, 15], + "faces": { + "north": {"uv": [1, 0, 2, 16], "texture": "#barrel"}, + "east": {"uv": [1, 0, 15, 16], "texture": "#barrel"}, + "south": {"uv": [14, 0, 15, 16], "texture": "#barrel"}, + "west": {"uv": [1, 0, 15, 16], "texture": "#barrel"}, + "up": {"uv": [1, 1, 2, 15], "texture": "#barrel", "cullface": "up"}, + "down": {"uv": [14, 1, 15, 15], "texture": "#barrel", "cullface": "down"} + } + }, + { + "from": [2, 1, 2], + "to": [14, 14, 14], + "faces": { + "up": {"uv": [2, 2, 14, 14], "texture": "#dirt"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/exdeorum/models/item/oak_barrel_composting.json b/src/main/resources/assets/exdeorum/models/item/oak_barrel_composting.json new file mode 100644 index 00000000..2aa7e318 --- /dev/null +++ b/src/main/resources/assets/exdeorum/models/item/oak_barrel_composting.json @@ -0,0 +1,3 @@ +{ + "parent": "exdeorum:block/oak_barrel_composting" +} \ No newline at end of file