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