Ex Deorum 1.13
This commit is contained in:
parent
1c5c08c557
commit
0c7913cd12
11
build.gradle
11
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'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
80
src/main/java/thedarkcolour/exdeorum/client/RenderFace.java
Normal file
80
src/main/java/thedarkcolour/exdeorum/client/RenderFace.java
Normal file
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<Pair<RenderType, TextureAtlasSprite>> layers, boolean isMissingTexture) implements RenderFace {
|
||||
public Composite(List<Pair<RenderType, TextureAtlasSprite>> 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<Pair<RenderType, TextureAtlasSprite>> layers) {
|
||||
for (var layer : layers) {
|
||||
if (RenderUtil.isMissingTexture(layer.second())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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<Block, RenderType> TOP_RENDER_TYPES;
|
||||
public static final LoadingCache<Block, TextureAtlasSprite> TOP_TEXTURES;
|
||||
private static final VarHandle COMPOSITE_MODEL_CHILDREN;
|
||||
private static final IdentityHashMap<Block, RenderFace> 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<BlockState, BakedModel> 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<String, BakedModel> children = (ImmutableMap<String, BakedModel>) COMPOSITE_MODEL_CHILDREN.get(composite);
|
||||
var builder = new ImmutableList.Builder<Pair<RenderType, TextureAtlasSprite>>();
|
||||
|
||||
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) {
|
||||
|
|
|
|||
|
|
@ -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<AbstractCrucibleBlo
|
|||
RenderUtil.renderFlatFluidSprite(buffers, stack, level, pos, y, 2.0f, light, (color >> 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);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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<SieveBlockEntity> {
|
||||
public static final LoadingCache<Item, TextureAtlasSprite> 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<Item, TextureAtlasSprite> MESH_TEXTURES = new IdentityHashMap<>();
|
||||
|
||||
public SieveRenderer(BlockEntityRendererProvider.Context ctx) {}
|
||||
|
||||
|
|
@ -53,17 +46,26 @@ public class SieveRenderer implements BlockEntityRenderer<SieveBlockEntity> {
|
|||
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()) {
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<BarrelCompostRecipe> {
|
||||
public static final int WIDTH = 120;
|
||||
|
|
@ -46,8 +55,7 @@ class BarrelCompostCategory implements IRecipeCategory<BarrelCompostRecipe> {
|
|||
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<BarrelCompostRecipe> {
|
|||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<T> implements IRecipeCategory<T> {
|
||||
public static final int WIDTH = 120;
|
||||
|
|
@ -48,12 +46,12 @@ public abstract class BarrelMixingCategory<T> implements IRecipeCategory<T> {
|
|||
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<T> implements IRecipeCategory<T> {
|
|||
|
||||
public static class Items extends BarrelMixingCategory<BarrelMixingRecipe> {
|
||||
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<T> implements IRecipeCategory<T> {
|
|||
|
||||
public static class Fluids extends BarrelMixingCategory<BarrelFluidMixingRecipe> {
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<OutputItem> 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<OutputItem> key, OutputItem value) {
|
||||
if (value.isEmpty()) {
|
||||
return "ItemStack '" + key.name + "' can't be empty";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
RecipeKey<OutputItem> RESULT = OUTPUT_ITEM_ONLY.key("result");
|
||||
RecipeKey<InputItem> INGREDIENT = ItemComponents.INPUT.key("ingredient");
|
||||
|
||||
RecipeSchema SCHEMA = new RecipeSchema(RESULT, INGREDIENT).uniqueOutputId(RESULT);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Item> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"parent": "exdeorum:block/oak_barrel_composting"
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user