Add compressed sieves, hammers, and blocks

This commit is contained in:
thedarkcolour 2024-04-08 18:37:36 -07:00
parent f22c004bda
commit 282a774d31
No known key found for this signature in database
GPG Key ID: 86B37B3575FD5976
51 changed files with 1476 additions and 356 deletions

View File

@ -84,5 +84,6 @@ public class ExDeorum {
ERecipeTypes.RECIPE_TYPES.register(modBus);
ENumberProviders.NUMBER_PROVIDERS.register(modBus);
DefaultMaterials.registerMaterials();
ECompressedBlocks.register();
}
}

View File

@ -0,0 +1,89 @@
package thedarkcolour.exdeorum.block;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.ItemLike;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.neoforged.neoforge.registries.DeferredBlock;
import net.neoforged.neoforge.registries.DeferredItem;
import thedarkcolour.exdeorum.compat.ModIds;
import thedarkcolour.exdeorum.registry.EBlocks;
import thedarkcolour.exdeorum.registry.EItems;
import thedarkcolour.exdeorum.tag.EItemTags;
import java.util.function.Supplier;
public class CompressedBlockType implements ItemLike {
private final DeferredBlock<Block> block;
private final DeferredItem<BlockItem> item;
private final TagKey<Item> itemTag;
private final Supplier<Block> base;
private boolean hasAtc, hasCompressium;
public CompressedBlockType(String name, Supplier<Block> base) {
this.block = EBlocks.BLOCKS.register("compressed_" + name, this::createBlock);
this.item = EItems.registerItemBlock(this.block);
this.itemTag = EItemTags.tag("compressed/" + name);
this.base = base;
}
private Block createBlock() {
return new Block(BlockBehaviour.Properties.ofFullCopy(this.base.get()));
}
public Block getBlock() {
return this.block.get();
}
public BlockItem getItem() {
return this.item.get();
}
@Override
public Item asItem() {
return this.item.get();
}
public TagKey<Item> getTag() {
return this.itemTag;
}
public CompressedBlockType withAtc() {
this.hasAtc = true;
return this;
}
public CompressedBlockType withCompressium() {
this.hasCompressium = true;
return this;
}
public boolean hasAtc() {
return this.hasAtc;
}
public boolean hasCompressium() {
return this.hasCompressium;
}
public ResourceLocation getAtc() {
return new ResourceLocation(ModIds.ALL_THE_COMPRESSED, BuiltInRegistries.BLOCK.getKey(this.base.get()).getPath() + "_1x");
}
public ResourceLocation getCompressium() {
return new ResourceLocation(ModIds.COMPRESSIUM, BuiltInRegistries.BLOCK.getKey(this.base.get()).getPath() + "_1");
}
public Block getBase() {
return this.base.get();
}
public ResourceLocation getId() {
return this.block.getId();
}
}

View File

@ -0,0 +1,28 @@
package thedarkcolour.exdeorum.block;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import thedarkcolour.exdeorum.registry.EBlockEntities;
public class CompressedSieveBlock extends SieveBlock {
public static final VoxelShape SHAPE = Shapes.or(
box(0, 8, 0, 16, 14, 16),
box(1, 0, 1, 3, 8, 3),
box(13, 0, 1, 15, 8, 3),
box(1, 0, 13, 3, 8, 15),
box(13, 0, 13, 15, 8, 15)
);
public CompressedSieveBlock(Properties properties) {
super(properties, EBlockEntities.COMPRESSED_SIEVE);
}
@Override
public VoxelShape getShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, CollisionContext pContext) {
return SHAPE;
}
}

View File

@ -22,6 +22,7 @@ import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
@ -29,6 +30,8 @@ import net.minecraft.world.phys.shapes.VoxelShape;
import thedarkcolour.exdeorum.blockentity.SieveBlockEntity;
import thedarkcolour.exdeorum.registry.EBlockEntities;
import java.util.function.Supplier;
public class SieveBlock extends EBlock {
public static final VoxelShape SHAPE = Shapes.or(
box(0, 11, 0, 16, 16, 16),
@ -42,14 +45,13 @@ public class SieveBlock extends EBlock {
super(properties, EBlockEntities.SIEVE);
}
@Override
public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
return SHAPE;
protected SieveBlock(Properties properties, Supplier<? extends BlockEntityType<?>> blockEntityType) {
super(properties, blockEntityType);
}
@Override
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
return new SieveBlockEntity(pos, state);
public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
return SHAPE;
}
@Override

View File

@ -22,20 +22,30 @@ import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.RandomSource;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.neoforged.neoforge.common.util.FakePlayer;
import thedarkcolour.exdeorum.blockentity.logic.SieveLogic;
import thedarkcolour.exdeorum.config.EConfig;
import java.util.function.Function;
public abstract class AbstractSieveBlockEntity extends EBlockEntity implements SieveLogic.Owner {
protected final SieveLogic logic;
private final float sieveInterval;
public AbstractSieveBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state, Function<SieveLogic.Owner, SieveLogic> logic) {
public AbstractSieveBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state, float sieveInterval, Function<SieveLogic.Owner, SieveLogic> logic) {
super(type, pos, state);
this.sieveInterval = sieveInterval;
this.logic = logic.apply(this);
}
@ -45,6 +55,16 @@ public abstract class AbstractSieveBlockEntity extends EBlockEntity implements S
return copy;
}
@Override
public boolean handleResultItem(ItemStack result, ServerLevel level, RandomSource rand) {
var pos = this.worldPosition;
var itemEntity = new ItemEntity(level, pos.getX() + 0.5, pos.getY() + 1.5, pos.getZ() + 0.5, result);
itemEntity.setDeltaMovement(rand.nextGaussian() * 0.05, 0.2, rand.nextGaussian() * 0.05);
level.addFreshEntity(itemEntity);
return true;
}
@SuppressWarnings("DataFlowIssue")
@Override
public ServerLevel getServerLevel() {
return (ServerLevel) this.level;
@ -83,4 +103,138 @@ public abstract class AbstractSieveBlockEntity extends EBlockEntity implements S
public void copyVisualData(BlockEntity fromIntegratedServer) {
this.logic.copyVisualData(fromIntegratedServer);
}
@Override
public InteractionResult use(Level level, Player player, InteractionHand hand) {
ItemStack playerItem = player.getItemInHand(hand);
boolean isClientSide = level.isClientSide;
// Try insert mesh
if (this.logic.getMesh().isEmpty()) {
if (this.logic.isValidMesh(playerItem)) {
if (!isClientSide) {
this.logic.setMesh(singleCopy(playerItem));
if (!player.getAbilities().instabuild) {
playerItem.shrink(1);
}
return InteractionResult.CONSUME;
} else {
return InteractionResult.SUCCESS;
}
}
} else if (this.logic.getContents().isEmpty()) {
// remove mesh with sneak right click
if (player.isShiftKeyDown() && player.getMainHandItem().isEmpty()) {
popOutMesh(level, this.worldPosition, this.logic);
}
}
if (!isClientSide) {
// Insert an item
if (this.logic.getContents().isEmpty()) {
// If the input has any sieve drops, insert it into the mesh
if (this.logic.isValidInput(playerItem)) {
playerItem = insertContents(player, hand, this.logic);
if (canUseSimultaneously()) {
int range = EConfig.SERVER.simultaneousSieveUsageRange.get();
var cursor = this.worldPosition.mutable().move(-range, 0, -range);
// Fill adjacent sieves
otherSieves:
for (int x = -range; x <= range; x++) {
for (int z = -range; z <= range; z++) {
if (playerItem.isEmpty()) {
break otherSieves;
}
if ((x | z) != 0) {
if (level.getBlockEntity(cursor) instanceof SieveBlockEntity other) {
if (other.logic.getContents().isEmpty()) {
if (this.logic.getMesh().getItem() == other.logic.getMesh().getItem()) {
playerItem = insertContents(player, hand, other.logic);
}
}
}
}
cursor.move(0, 0, 1);
}
cursor.move(1, 0, (-2 * range) - 1);
}
}
}
} else {
var time = level.getGameTime();
var realPlayer = !(player instanceof FakePlayer);
if ((realPlayer || !EConfig.SERVER.nerfAutomatedSieves.get()) && canUseSimultaneously()) {
int range = EConfig.SERVER.simultaneousSieveUsageRange.get();
var cursor = this.worldPosition.mutable().move(-range, 0, -range);
var selfType = getType();
// Sieve with adjacent sieves
for (int x = -range; x <= range; x++) {
for (int z = -range; z <= range; z++) {
if (level.getBlockEntity(cursor) instanceof AbstractSieveBlockEntity other && other.getType() == selfType) {
var otherLogic = other.logic;
if (!otherLogic.getContents().isEmpty()) {
if (this.logic.getMesh().getItem() == otherLogic.getMesh().getItem()) {
otherLogic.sift(this.sieveInterval, time);
}
}
}
cursor.move(0, 0, 1);
}
cursor.move(1, 0, (-2 * range) - 1);
}
} else if (realPlayer || EConfig.SERVER.automatedSieves.get()) {
this.logic.sift(this.sieveInterval, time);
}
}
}
return InteractionResult.sidedSuccess(isClientSide);
}
// Fills the sieve (assumes contents is EMPTY) and returns the remaining item, putting it in the player's hand
public static ItemStack insertContents(Player player, InteractionHand hand, SieveLogic logic) {
var consume = !player.getAbilities().instabuild;
var playerItem = player.getItemInHand(hand);
if (consume) {
if (playerItem.getCount() == 1) {
logic.startSifting(playerItem);
player.setItemInHand(hand, ItemStack.EMPTY);
playerItem = ItemStack.EMPTY;
} else {
logic.startSifting(singleCopy(playerItem));
playerItem.shrink(1);
}
} else {
logic.startSifting(singleCopy(playerItem));
}
return playerItem;
}
// Do not call on client side
public static void popOutMesh(Level level, BlockPos sievePos, SieveLogic logic) {
if (!level.isClientSide) {
// Pop out item
var itemEntity = new ItemEntity(level, sievePos.getX() + 0.5, sievePos.getY() + 1.5, sievePos.getZ() + 0.5, logic.getMesh());
var rand = level.random;
itemEntity.setDeltaMovement(rand.nextGaussian() * 0.05, 0.2, rand.nextGaussian() * 0.05);
level.addFreshEntity(itemEntity);
// Empty contents
logic.setMesh(ItemStack.EMPTY);
}
}
protected boolean canUseSimultaneously() {
return false;
}
}

View File

@ -0,0 +1,14 @@
package thedarkcolour.exdeorum.blockentity;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.state.BlockState;
import thedarkcolour.exdeorum.blockentity.logic.CompressedSieveLogic;
import thedarkcolour.exdeorum.registry.EBlockEntities;
public class CompressedSieveBlockEntity extends AbstractSieveBlockEntity {
private static final float COMPRESSED_SIEVE_INTERVAl = 0.075f;
public CompressedSieveBlockEntity(BlockPos pos, BlockState state) {
super(EBlockEntities.COMPRESSED_SIEVE.get(), pos, state, COMPRESSED_SIEVE_INTERVAl, owner -> new CompressedSieveLogic(owner, false));
}
}

View File

@ -50,7 +50,7 @@ public class MechanicalSieveBlockEntity extends AbstractMachineBlockEntity<Mecha
public MechanicalSieveBlockEntity(BlockPos pos, BlockState state) {
super(EBlockEntities.MECHANICAL_SIEVE.get(), pos, state, ItemHandler::new, EConfig.SERVER.mechanicalSieveEnergyStorage.get());
this.logic = new SieveLogic(this, false, true);
this.logic = new SieveLogic(this, true);
}
@Override

View File

@ -19,16 +19,7 @@
package thedarkcolour.exdeorum.blockentity;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.RandomSource;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import net.neoforged.neoforge.common.util.FakePlayer;
import thedarkcolour.exdeorum.blockentity.logic.SieveLogic;
import thedarkcolour.exdeorum.config.EConfig;
import thedarkcolour.exdeorum.registry.EBlockEntities;
@ -37,140 +28,11 @@ public class SieveBlockEntity extends AbstractSieveBlockEntity {
public static final float SIEVE_INTERVAL = 0.1f;
public SieveBlockEntity(BlockPos pos, BlockState state) {
super(EBlockEntities.SIEVE.get(), pos, state, (owner) -> new SieveLogic(owner, true, false));
super(EBlockEntities.SIEVE.get(), pos, state, SIEVE_INTERVAL, (owner) -> new SieveLogic(owner, false));
}
@Override
public boolean handleResultItem(ItemStack result, ServerLevel level, RandomSource rand) {
var pos = this.worldPosition;
var itemEntity = new ItemEntity(level, pos.getX() + 0.5, pos.getY() + 1.5, pos.getZ() + 0.5, result);
itemEntity.setDeltaMovement(rand.nextGaussian() * 0.05, 0.2, rand.nextGaussian() * 0.05);
level.addFreshEntity(itemEntity);
return true;
}
public InteractionResult use(Level level, Player player, InteractionHand hand) {
ItemStack playerItem = player.getItemInHand(hand);
boolean isClientSide = level.isClientSide;
// Try insert mesh
if (this.logic.getMesh().isEmpty()) {
if (this.logic.isValidMesh(playerItem)) {
if (!isClientSide) {
this.logic.setMesh(singleCopy(playerItem));
if (!player.getAbilities().instabuild) {
playerItem.shrink(1);
}
return InteractionResult.CONSUME;
} else {
return InteractionResult.SUCCESS;
}
}
} else if (this.logic.getContents().isEmpty()) {
// remove mesh with sneak right click
if (player.isShiftKeyDown() && player.getMainHandItem().isEmpty()) {
popOutMesh(level, this.worldPosition, this.logic);
}
}
if (!isClientSide) {
// Insert an item
if (this.logic.getContents().isEmpty()) {
// If the input has any sieve drops, insert it into the mesh
if (this.logic.isValidInput(playerItem)) {
playerItem = insertContents(player, hand, this.logic);
if (EConfig.SERVER.simultaneousSieveUsage.get()) {
int range = EConfig.SERVER.simultaneousSieveUsageRange.get();
var cursor = this.worldPosition.mutable().move(-range, 0, -range);
// Fill adjacent sieves
otherSieves:
for (int x = -range; x <= range; x++) {
for (int z = -range; z <= range; z++) {
if (playerItem.isEmpty()) {
break otherSieves;
}
if ((x | z) != 0) {
if (level.getBlockEntity(cursor) instanceof SieveBlockEntity other) {
if (other.logic.getContents().isEmpty()) {
if (this.logic.getMesh().getItem() == other.logic.getMesh().getItem()) {
playerItem = insertContents(player, hand, other.logic);
}
}
}
}
cursor.move(0, 0, 1);
}
cursor.move(1, 0, (-2 * range) - 1);
}
}
}
} else {
var time = level.getGameTime();
var realPlayer = !(player instanceof FakePlayer);
if ((realPlayer || !EConfig.SERVER.nerfAutomatedSieves.get()) && EConfig.SERVER.simultaneousSieveUsage.get()) {
int range = EConfig.SERVER.simultaneousSieveUsageRange.get();
var cursor = this.worldPosition.mutable().move(-range, 0, -range);
// Sieve with adjacent sieves
for (int x = -range; x <= range; x++) {
for (int z = -range; z <= range; z++) {
if (level.getBlockEntity(cursor) instanceof SieveBlockEntity other) {
if (!other.logic.getContents().isEmpty()) {
if (this.logic.getMesh().getItem() == other.logic.getMesh().getItem()) {
other.logic.sift(SIEVE_INTERVAL, time);
}
}
}
cursor.move(0, 0, 1);
}
cursor.move(1, 0, (-2 * range) - 1);
}
} else if (realPlayer || EConfig.SERVER.automatedSieves.get()) {
this.logic.sift(SIEVE_INTERVAL, time);
}
}
}
return InteractionResult.sidedSuccess(isClientSide);
}
// Fills the sieve (assumes contents is EMPTY) and returns the remaining item, putting it in the player's hand
public static ItemStack insertContents(Player player, InteractionHand hand, SieveLogic logic) {
var consume = !player.getAbilities().instabuild;
var playerItem = player.getItemInHand(hand);
if (consume) {
if (playerItem.getCount() == 1) {
logic.startSifting(playerItem);
player.setItemInHand(hand, ItemStack.EMPTY);
playerItem = ItemStack.EMPTY;
} else {
logic.startSifting(singleCopy(playerItem));
playerItem.shrink(1);
}
} else {
logic.startSifting(singleCopy(playerItem));
}
return playerItem;
}
// Do not call on client side
public static void popOutMesh(Level level, BlockPos sievePos, SieveLogic logic) {
if (!level.isClientSide) {
// Pop out item
var itemEntity = new ItemEntity(level, sievePos.getX() + 0.5, sievePos.getY() + 1.5, sievePos.getZ() + 0.5, logic.getMesh());
var rand = level.random;
itemEntity.setDeltaMovement(rand.nextGaussian() * 0.05, 0.2, rand.nextGaussian() * 0.05);
level.addFreshEntity(itemEntity);
// Empty contents
logic.setMesh(ItemStack.EMPTY);
}
protected boolean canUseSimultaneously() {
return EConfig.SERVER.simultaneousSieveUsage.get();
}
}

View File

@ -0,0 +1,18 @@
package thedarkcolour.exdeorum.blockentity.logic;
import net.minecraft.world.item.ItemStack;
import thedarkcolour.exdeorum.recipe.RecipeUtil;
import thedarkcolour.exdeorum.recipe.sieve.SieveRecipe;
import java.util.List;
public class CompressedSieveLogic extends SieveLogic {
public CompressedSieveLogic(Owner owner, boolean mechanical) {
super(owner, mechanical);
}
@Override
protected List<? extends SieveRecipe> getDropsFor(ItemStack contents) {
return RecipeUtil.getCompressedSieveRecipes(this.mesh.getItem(), contents);
}
}

View File

@ -34,15 +34,16 @@ import thedarkcolour.exdeorum.recipe.RecipeUtil;
import thedarkcolour.exdeorum.recipe.sieve.SieveRecipe;
import thedarkcolour.exdeorum.tag.EItemTags;
import java.util.List;
public class SieveLogic {
private final Owner owner;
private final boolean saveMesh;
private final boolean mechanical;
// block currently being sifted
private ItemStack contents = ItemStack.EMPTY;
// mesh
private ItemStack mesh = ItemStack.EMPTY;
protected ItemStack mesh = ItemStack.EMPTY;
// from 0.0 to 1.0
private float progress;
private float efficiency;
@ -50,9 +51,8 @@ public class SieveLogic {
private long lastTime = 0;
private final long minInterval;
public SieveLogic(Owner owner, boolean saveMesh, boolean mechanical) {
public SieveLogic(Owner owner, boolean mechanical) {
this.owner = owner;
this.saveMesh = saveMesh;
this.mechanical = mechanical;
this.minInterval = EConfig.SERVER.sieveIntervalTicks.get();
}
@ -62,7 +62,7 @@ public class SieveLogic {
}
public boolean isValidInput(ItemStack stack) {
return !RecipeUtil.getSieveRecipes(this.mesh.getItem(), stack).isEmpty();
return !getDropsFor(stack).isEmpty();
}
public boolean isValidMesh(ItemStack stack) {
@ -93,7 +93,7 @@ public class SieveLogic {
var handledAnyDrops = false;
var hasDrops = false;
for (SieveRecipe recipe : RecipeUtil.getSieveRecipes(this.mesh.getItem(), this.contents)) {
for (SieveRecipe recipe : getDropsFor(this.contents)) {
var amount = getResultAmount(recipe, context, rand);
// Split overflowing stacks (64+) into multiple stacks
@ -126,6 +126,10 @@ public class SieveLogic {
this.owner.markUpdated();
}
protected List<? extends SieveRecipe> getDropsFor(ItemStack contents) {
return RecipeUtil.getSieveRecipes(this.mesh.getItem(), contents);
}
protected int getResultAmount(SieveRecipe recipe, LootContext context, RandomSource rand) {
if (recipe.byHandOnly && this.mechanical) return 0;
@ -162,7 +166,7 @@ public class SieveLogic {
if (!this.contents.isEmpty()) {
nbt.put("contents", this.contents.save(new CompoundTag()));
}
if (this.saveMesh && !this.mesh.isEmpty()) {
if (!this.mechanical && !this.mesh.isEmpty()) {
nbt.put("mesh", this.mesh.save(new CompoundTag()));
}
nbt.putFloat("progress", this.progress);
@ -179,7 +183,7 @@ public class SieveLogic {
} else {
this.progress = nbt.getFloat("progress");
}
if (this.saveMesh) {
if (!this.mechanical) {
if (nbt.contains("mesh")) {
setMesh(ItemStack.of(nbt.getCompound("mesh")), false);
} else {

View File

@ -38,13 +38,9 @@ import net.neoforged.neoforge.common.NeoForge;
import thedarkcolour.exdeorum.ExDeorum;
import thedarkcolour.exdeorum.client.screen.MechanicalHammerScreen;
import thedarkcolour.exdeorum.client.screen.MechanicalSieveScreen;
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.client.ter.*;
import thedarkcolour.exdeorum.compat.ModIds;
import thedarkcolour.exdeorum.config.EConfig;
import thedarkcolour.exdeorum.network.ClientMessageHandler;
import thedarkcolour.exdeorum.recipe.RecipeUtil;
import thedarkcolour.exdeorum.registry.EBlockEntities;
import thedarkcolour.exdeorum.registry.EFluids;
@ -121,8 +117,9 @@ public class ClientHandler {
event.registerBlockEntityRenderer(EBlockEntities.BARREL.get(), BarrelRenderer::new);
event.registerBlockEntityRenderer(EBlockEntities.LAVA_CRUCIBLE.get(), ctx -> new CrucibleRenderer());
event.registerBlockEntityRenderer(EBlockEntities.WATER_CRUCIBLE.get(), ctx -> new CrucibleRenderer());
event.registerBlockEntityRenderer(EBlockEntities.SIEVE.get(), ctx -> new SieveRenderer<>());
event.registerBlockEntityRenderer(EBlockEntities.MECHANICAL_SIEVE.get(), ctx -> new SieveRenderer<>());
event.registerBlockEntityRenderer(EBlockEntities.SIEVE.get(), ctx -> new SieveRenderer<>(0.75f, 15f));
event.registerBlockEntityRenderer(EBlockEntities.MECHANICAL_SIEVE.get(), ctx -> new SieveRenderer<>(0.75f, 15f));
event.registerBlockEntityRenderer(EBlockEntities.COMPRESSED_SIEVE.get(), ctx -> new CompressedSieveRenderer<>(0.5625f, 16f));
}
private static void registerShaders(RegisterShadersEvent event) {

View File

@ -32,6 +32,8 @@ public interface RenderFace {
boolean isMissingTexture();
void renderCuboid(MultiBufferSource buffers, PoseStack stack, float minY, float maxY, int r, int g, int b, int light, float edge);
record Single(RenderType renderType, TextureAtlasSprite sprite, boolean isMissingTexture) implements RenderFace {
public Single(RenderType renderType, TextureAtlasSprite sprite) {
this(renderType, sprite, RenderUtil.isMissingTexture(sprite));
@ -41,23 +43,35 @@ public interface RenderFace {
public void renderFlatSpriteLerp(MultiBufferSource buffers, PoseStack stack, float percentage, int r, int g, int b, int light, float edge, float yStart, float yEnd) {
RenderUtil.renderFlatSpriteLerp(buffers.getBuffer(this.renderType), stack, percentage, r, g, b, this.sprite, light, edge, yStart, yEnd);
}
@Override
public void renderCuboid(MultiBufferSource buffers, PoseStack stack, float minY, float maxY, int r, int g, int b, int light, float edge) {
RenderUtil.renderCuboid(buffers.getBuffer(this.renderType), stack, minY, maxY, r, g, b, this.sprite, light, edge);
}
}
record Composite(List<Pair<RenderType, TextureAtlasSprite>> layers, boolean isMissingTexture) implements RenderFace {
public Composite(List<Pair<RenderType, TextureAtlasSprite>> layers) {
record Composite(CompositeLayer[] layers, boolean isMissingTexture) implements RenderFace {
public Composite(CompositeLayer[] layers) {
this(layers, areAnyMissing(layers));
}
@Override
public void renderFlatSpriteLerp(MultiBufferSource buffers, PoseStack stack, float percentage, int r, int g, int b, int light, float edge, float yStart, float yEnd) {
for (var layer : this.layers) {
RenderUtil.renderFlatSpriteLerp(buffers.getBuffer(layer.first()), stack, percentage, r, g, b, layer.second(), light, edge, yStart, yEnd);
RenderUtil.renderFlatSpriteLerp(buffers.getBuffer(layer.renderType), stack, percentage, r, g, b, layer.sprite, light, edge, yStart, yEnd);
}
}
private static boolean areAnyMissing(List<Pair<RenderType, TextureAtlasSprite>> layers) {
@Override
public void renderCuboid(MultiBufferSource buffers, PoseStack stack, float minY, float maxY, int r, int g, int b, int light, float edge) {
for (var layer : this.layers) {
RenderUtil.renderCuboid(buffers.getBuffer(layer.renderType), stack, minY, maxY, r, g, b, layer.sprite, light, edge);
}
}
private static boolean areAnyMissing(CompositeLayer[] layers) {
for (var layer : layers) {
if (RenderUtil.isMissingTexture(layer.second())) {
if (RenderUtil.isMissingTexture(layer.sprite)) {
return true;
}
}
@ -65,4 +79,5 @@ public interface RenderFace {
return false;
}
}
record CompositeLayer(RenderType renderType, TextureAtlasSprite sprite) {}
}

View File

@ -18,13 +18,11 @@
package thedarkcolour.exdeorum.client;
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.Pair;
import net.irisshaders.iris.api.v0.IrisApi;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.MultiBufferSource;
@ -117,14 +115,15 @@ public class RenderUtil {
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>>();
RenderFace.CompositeLayer[] layers = new RenderFace.CompositeLayer[children.size()];
int i = 0;
for (var childModel : children.values()) {
var singleFace = getFaceFromModel(block, rand, childModel);
builder.add(Pair.of(singleFace.renderType(), singleFace.sprite()));
layers[i++] = new RenderFace.CompositeLayer(singleFace.renderType(), singleFace.sprite());
}
face = new RenderFace.Composite(builder.build());
face = new RenderFace.Composite(layers);
} else {
face = getFaceFromModel(block, rand, model);
}
@ -277,6 +276,67 @@ public class RenderUtil {
return IClientFluidTypeExtensions.of(fluid).getTintColor(fluid.defaultFluidState(), level, pos);
}
// todo use ambient occlusion
// Renders a cuboid using the same side sprite on all six sides
public static void renderCuboid(VertexConsumer builder, PoseStack stack, float minY, float maxY, int r, int g, int b, TextureAtlasSprite sprite, int light, float edge) {
var pose = stack.last().pose();
var poseNormal = stack.last().normal();
Vector3f normal;
float uMin = sprite.getU0();
float uMax = sprite.getU1();
float vMin = sprite.getV0();
float vMax = sprite.getV1();
float edgeMin = edge / 16f;
float edgeMax = 1f - edge / 16f;
int lightU = light & '\uffff';
int lightV = light >> 16 & '\uffff';
// Top face
normal = poseNormal.transform(new Vector3f(0, 1, 0));
builder.vertex(pose, edgeMin, maxY, edgeMin).color(r, g, b, 255).uv(uMin, vMin).overlayCoords(0, 10).uv2(lightU, lightV).normal(normal.x, normal.y, normal.z).endVertex();
builder.vertex(pose, edgeMin, maxY, edgeMax).color(r, g, b, 255).uv(uMin, vMax).overlayCoords(0, 10).uv2(lightU, lightV).normal(normal.x, normal.y, normal.z).endVertex();
builder.vertex(pose, edgeMax, maxY, edgeMax).color(r, g, b, 255).uv(uMax, vMax).overlayCoords(0, 10).uv2(lightU, lightV).normal(normal.x, normal.y, normal.z).endVertex();
builder.vertex(pose, edgeMax, maxY, edgeMin).color(r, g, b, 255).uv(uMax, vMin).overlayCoords(0, 10).uv2(lightU, lightV).normal(normal.x, normal.y, normal.z).endVertex();
// Bottom face
normal = poseNormal.transform(new Vector3f(0, -1, 0));
builder.vertex(pose, edgeMin, minY, edgeMin).color(r, g, b, 255).uv(uMin, vMin).overlayCoords(0, 10).uv2(lightU, lightV).normal(normal.x, normal.y, normal.z).endVertex();
builder.vertex(pose, edgeMax, minY, edgeMin).color(r, g, b, 255).uv(uMax, vMin).overlayCoords(0, 10).uv2(lightU, lightV).normal(normal.x, normal.y, normal.z).endVertex();
builder.vertex(pose, edgeMax, minY, edgeMax).color(r, g, b, 255).uv(uMax, vMax).overlayCoords(0, 10).uv2(lightU, lightV).normal(normal.x, normal.y, normal.z).endVertex();
builder.vertex(pose, edgeMin, minY, edgeMax).color(r, g, b, 255).uv(uMin, vMax).overlayCoords(0, 10).uv2(lightU, lightV).normal(normal.x, normal.y, normal.z).endVertex();
// Adjust UV based on height of cuboid, rendering from the top down to the bottom of the texture
float f = sprite.getV1() - sprite.getV0();
vMax = sprite.getV0() + f * (maxY - minY);
// South face
normal = poseNormal.transform(new Vector3f(0, 0, -1));
builder.vertex(pose, edgeMax, maxY, edgeMax).color(r, g, b, 255).uv(uMax, vMin).overlayCoords(0, 10).uv2(lightU, lightV).normal(normal.x, normal.y, normal.z).endVertex();
builder.vertex(pose, edgeMin, maxY, edgeMax).color(r, g, b, 255).uv(uMin, vMin).overlayCoords(0, 10).uv2(lightU, lightV).normal(normal.x, normal.y, normal.z).endVertex();
builder.vertex(pose, edgeMin, minY, edgeMax).color(r, g, b, 255).uv(uMin, vMax).overlayCoords(0, 10).uv2(lightU, lightV).normal(normal.x, normal.y, normal.z).endVertex();
builder.vertex(pose, edgeMax, minY, edgeMax).color(r, g, b, 255).uv(uMax, vMax).overlayCoords(0, 10).uv2(lightU, lightV).normal(normal.x, normal.y, normal.z).endVertex();
// North face
normal = poseNormal.transform(new Vector3f(0, 0, -1));
builder.vertex(pose, edgeMin, maxY, edgeMin).color(r, g, b, 255).uv(uMin, vMin).overlayCoords(0, 10).uv2(lightU, lightV).normal(normal.x, normal.y, normal.z).endVertex();
builder.vertex(pose, edgeMax, maxY, edgeMin).color(r, g, b, 255).uv(uMax, vMin).overlayCoords(0, 10).uv2(lightU, lightV).normal(normal.x, normal.y, normal.z).endVertex();
builder.vertex(pose, edgeMax, minY, edgeMin).color(r, g, b, 255).uv(uMax, vMax).overlayCoords(0, 10).uv2(lightU, lightV).normal(normal.x, normal.y, normal.z).endVertex();
builder.vertex(pose, edgeMin, minY, edgeMin).color(r, g, b, 255).uv(uMin, vMax).overlayCoords(0, 10).uv2(lightU, lightV).normal(normal.x, normal.y, normal.z).endVertex();
// East face
normal = poseNormal.transform(new Vector3f(1, 0, 0));
builder.vertex(pose, edgeMax, maxY, edgeMin).color(r, g, b, 255).uv(uMin, vMin).overlayCoords(0, 10).uv2(lightU, lightV).normal(normal.x, normal.y, normal.z).endVertex();
builder.vertex(pose, edgeMax, maxY, edgeMax).color(r, g, b, 255).uv(uMax, vMin).overlayCoords(0, 10).uv2(lightU, lightV).normal(normal.x, normal.y, normal.z).endVertex();
builder.vertex(pose, edgeMax, minY, edgeMax).color(r, g, b, 255).uv(uMax, vMax).overlayCoords(0, 10).uv2(lightU, lightV).normal(normal.x, normal.y, normal.z).endVertex();
builder.vertex(pose, edgeMax, minY, edgeMin).color(r, g, b, 255).uv(uMin, vMax).overlayCoords(0, 10).uv2(lightU, lightV).normal(normal.x, normal.y, normal.z).endVertex();
// West face
normal = poseNormal.transform(new Vector3f(-1, 0, 0));
builder.vertex(pose, edgeMin, maxY, edgeMax).color(r, g, b, 255).uv(uMax, vMin).overlayCoords(0, 10).uv2(lightU, lightV).normal(normal.x, normal.y, normal.z).endVertex();
builder.vertex(pose, edgeMin, maxY, edgeMin).color(r, g, b, 255).uv(uMin, vMin).overlayCoords(0, 10).uv2(lightU, lightV).normal(normal.x, normal.y, normal.z).endVertex();
builder.vertex(pose, edgeMin, minY, edgeMin).color(r, g, b, 255).uv(uMin, vMax).overlayCoords(0, 10).uv2(lightU, lightV).normal(normal.x, normal.y, normal.z).endVertex();
builder.vertex(pose, edgeMin, minY, edgeMax).color(r, g, b, 255).uv(uMax, vMax).overlayCoords(0, 10).uv2(lightU, lightV).normal(normal.x, normal.y, normal.z).endVertex();
}
public interface IrisAccess {
boolean areShadersEnabled();
}

View File

@ -0,0 +1,16 @@
package thedarkcolour.exdeorum.client.ter;
import thedarkcolour.exdeorum.blockentity.EBlockEntity;
import thedarkcolour.exdeorum.blockentity.logic.SieveLogic;
// mesh y = 10 / 16
public class CompressedSieveRenderer<T extends EBlockEntity & SieveLogic.Owner> extends SieveRenderer<T> {
public CompressedSieveRenderer(float meshHeight, float contentsMaxY) {
super(meshHeight, contentsMaxY);
}
@Override
protected boolean shouldContentsRender3d(T sieve) {
return true;
}
}

View File

@ -25,6 +25,7 @@ import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.Item;
import thedarkcolour.exdeorum.blockentity.EBlockEntity;
@ -37,6 +38,16 @@ import java.util.Map;
public class SieveRenderer<T extends EBlockEntity & SieveLogic.Owner> implements BlockEntityRenderer<T> {
public static final Map<Item, TextureAtlasSprite> MESH_TEXTURES = new HashMap<>();
private final float meshHeight;
private final float contentsMinY;
private final float contentsMaxY;
public SieveRenderer(float meshHeight, float contentsMaxY) {
this.meshHeight = meshHeight;
this.contentsMinY = meshHeight * 16f + 1f;
this.contentsMaxY = contentsMaxY;
}
@Override
public void render(T sieve, float partialTicks, PoseStack stack, MultiBufferSource buffers, int light, int overlay) {
var logic = sieve.getLogic();
@ -46,7 +57,12 @@ public class SieveRenderer<T extends EBlockEntity & SieveLogic.Owner> implements
var block = blockItem.getBlock();
var percentage = logic.getProgress();
var face = RenderUtil.getTopFace(block);
face.renderFlatSpriteLerp(buffers, stack, percentage, 0xff, 0xff, 0xff, light, 1.0f, 15f, 13f);
if (shouldContentsRender3d(sieve)) {
face.renderCuboid(buffers, stack, this.contentsMinY / 16f, Mth.lerp(percentage, this.contentsMaxY, this.contentsMinY) / 16f, 0xff, 0xff, 0xff, light, 1.0f);
} else {
face.renderFlatSpriteLerp(buffers, stack, percentage, 0xff, 0xff, 0xff, light, 1.0f, this.contentsMaxY, this.contentsMinY);
}
}
var mesh = logic.getMesh();
@ -65,11 +81,16 @@ public class SieveRenderer<T extends EBlockEntity & SieveLogic.Owner> implements
MESH_TEXTURES.put(meshItem, meshSprite);
}
RenderUtil.renderFlatSprite(builder, stack, 0.75f, 0xff, 0xff, 0xff, meshSprite, light, 1f);
RenderUtil.renderFlatSprite(builder, stack, this.meshHeight, 0xff, 0xff, 0xff, meshSprite, light, 1f);
if (mesh.hasFoil()) {
RenderUtil.renderFlatSprite(buffers.getBuffer(RenderType.glint()), stack, 0.75f, 0xff, 0xff, 0xff, meshSprite, light, 1f);
RenderUtil.renderFlatSprite(buffers.getBuffer(RenderType.glint()), stack, this.meshHeight, 0xff, 0xff, 0xff, meshSprite, light, 1f);
}
}
}
// todo return true for transparent sieves
protected boolean shouldContentsRender3d(T sieve) {
return false;
}
}

View File

@ -56,6 +56,10 @@ public class CompatUtil {
return getAvailableMaterials(DefaultMaterials.WATER_CRUCIBLES, registered);
}
public static List<ItemLike> getAvailableCompressedSieves(boolean registered) {
return getAvailableMaterials(DefaultMaterials.COMPRESSED_SIEVES, registered);
}
private static List<ItemLike> getAvailableMaterials(MaterialRegistry<?> registry, boolean registered) {
List<ItemLike> materials = new ArrayList<>();

View File

@ -21,36 +21,31 @@ package thedarkcolour.exdeorum.compat;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Multimap;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.minecraft.client.Minecraft;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.util.Mth;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.RecipeHolder;
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.level.storage.loot.providers.number.ConstantValue;
import net.minecraft.world.level.storage.loot.providers.number.NumberProvider;
import thedarkcolour.exdeorum.recipe.RecipeUtil;
import thedarkcolour.exdeorum.recipe.sieve.SieveRecipe;
import thedarkcolour.exdeorum.registry.EItems;
import thedarkcolour.exdeorum.registry.ERecipeSerializers;
import thedarkcolour.exdeorum.registry.ERecipeTypes;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
// Since no JEI code is used here, this can be reused for REI
public record GroupedSieveRecipe(Ingredient ingredient, ItemStack mesh, List<Result> results) {
public static int maxSieveRows;
public static ImmutableList<GroupedSieveRecipe> getAllRecipesGrouped() {
public static ImmutableList<GroupedSieveRecipe> getAllRecipesGrouped(RecipeType<? extends SieveRecipe> recipeType) {
maxSieveRows = 1;
var recipes = CompatUtil.collectAllRecipes(ERecipeTypes.SIEVE.value(), Function.identity());
var recipes = CompatUtil.collectAllRecipes(recipeType, Function.identity());
Multimap<Ingredient, SieveRecipe> ingredientGrouper = ArrayListMultimap.create();
for (int i = 0; i < recipes.size(); i++) {

View File

@ -24,6 +24,8 @@ public class ModIds {
public static final String THE_ONE_PROBE = "theoneprobe";
public static final String TINKERS_CONSTRUCT = "tconstruct";
public static final String ALL_THE_ORES = "alltheores";
public static final String ALL_THE_COMPRESSED = "allthecompressed";
public static final String COMPRESSIUM = "compressium";
public static final String THERMAL = "thermal";
public static final String OCCULTISM = "occultism";
public static final String RAILCRAFT = "railcraft";
@ -45,4 +47,5 @@ public class ModIds {
public static final String EMI = "emi";
public static final String INVENTORY_SORTER = "inventorysorter";
public static final String REI_PC = "rei_plugin_compatibilities";
public static final String CYCLIC = "cyclic";
}

View File

@ -0,0 +1,19 @@
package thedarkcolour.exdeorum.compat.jei;
import mezz.jei.api.helpers.IGuiHelper;
import mezz.jei.api.recipe.RecipeType;
import net.minecraft.network.chat.Component;
import thedarkcolour.exdeorum.compat.GroupedSieveRecipe;
import thedarkcolour.exdeorum.data.TranslationKeys;
import thedarkcolour.exdeorum.material.DefaultMaterials;
class CompressedSieveCategory extends SieveCategory {
CompressedSieveCategory(IGuiHelper helper) {
super(helper, DefaultMaterials.OAK_COMPRESSED_SIEVE, Component.translatable(TranslationKeys.COMPRESSED_SIEVE_CATEGORY_TITLE));
}
@Override
public RecipeType<GroupedSieveRecipe> getRecipeType() {
return ExDeorumJeiPlugin.COMPRESSED_SIEVE;
}
}

View File

@ -43,6 +43,7 @@ import net.minecraft.world.level.block.LiquidBlock;
import net.minecraft.world.level.block.WallTorchBlock;
import net.neoforged.fml.ModList;
import net.neoforged.neoforge.fluids.FluidStack;
import net.neoforged.neoforge.registries.DeferredHolder;
import thedarkcolour.exdeorum.ExDeorum;
import thedarkcolour.exdeorum.client.screen.MechanicalHammerScreen;
import thedarkcolour.exdeorum.client.screen.MechanicalSieveScreen;
@ -56,6 +57,7 @@ import thedarkcolour.exdeorum.recipe.barrel.BarrelCompostRecipe;
import thedarkcolour.exdeorum.recipe.barrel.BarrelFluidMixingRecipe;
import thedarkcolour.exdeorum.recipe.barrel.BarrelMixingRecipe;
import thedarkcolour.exdeorum.recipe.crucible.CrucibleRecipe;
import thedarkcolour.exdeorum.recipe.hammer.CompressedHammerRecipe;
import thedarkcolour.exdeorum.recipe.hammer.HammerRecipe;
import thedarkcolour.exdeorum.registry.EFluids;
import thedarkcolour.exdeorum.registry.EItems;
@ -79,7 +81,9 @@ public class ExDeorumJeiPlugin implements IModPlugin {
static final RecipeType<CrucibleRecipe> WATER_CRUCIBLE = recipeType("water_crucible", CrucibleRecipe.class);
static final RecipeType<CrucibleHeatSourceRecipe> CRUCIBLE_HEAT_SOURCES = recipeType("crucible_heat_sources", CrucibleHeatSourceRecipe.class);
static final RecipeType<GroupedSieveRecipe> SIEVE = recipeType("sieve", GroupedSieveRecipe.class);
static final RecipeType<GroupedSieveRecipe> COMPRESSED_SIEVE = recipeType("compressed_sieve", GroupedSieveRecipe.class);
static final RecipeType<HammerRecipe> HAMMER = recipeType("hammer", HammerRecipe.class);
static final RecipeType<HammerRecipe> COMPRESSED_HAMMER = recipeType("compressed_hammer", CompressedHammerRecipe.class);
static final RecipeType<CrookJeiRecipe> CROOK = recipeType("crook", CrookJeiRecipe.class);
private static <T> RecipeType<T> recipeType(String path, Class<? extends T> type) {
@ -106,7 +110,9 @@ public class ExDeorumJeiPlugin implements IModPlugin {
registration.addRecipeCategories(new CrucibleCategory.WaterCrucible(helper, arrow));
registration.addRecipeCategories(new CrucibleHeatSourcesCategory(registration.getJeiHelpers()));
registration.addRecipeCategories(new SieveCategory(helper));
registration.addRecipeCategories(new HammerCategory(helper, arrow));
registration.addRecipeCategories(new CompressedSieveCategory(helper));
registration.addRecipeCategories(new HammerCategory(helper, arrow, EItems.DIAMOND_HAMMER, Component.translatable(TranslationKeys.HAMMER_CATEGORY_TITLE), HAMMER));
registration.addRecipeCategories(new HammerCategory(helper, arrow, EItems.COMPRESSED_DIAMOND_HAMMER, Component.translatable(TranslationKeys.COMPRESSED_HAMMER_CATEGORY_TITLE), COMPRESSED_HAMMER));
registration.addRecipeCategories(new CrookCategory(registration.getJeiHelpers(), arrow));
}
@ -116,6 +122,7 @@ public class ExDeorumJeiPlugin implements IModPlugin {
var sieves = CompatUtil.getAvailableSieves(true, true);
var lavaCrucibles = CompatUtil.getAvailableLavaCrucibles(true);
var waterCrucibles = CompatUtil.getAvailableWaterCrucibles(true);
var compressedSieves = CompatUtil.getAvailableCompressedSieves(true);
for (var barrel : barrels) {
var stack = new ItemStack(barrel);
@ -134,6 +141,9 @@ public class ExDeorumJeiPlugin implements IModPlugin {
for (var sieve : sieves) {
registration.addRecipeCatalyst(new ItemStack(sieve), SIEVE);
}
for (var compressedSieve : compressedSieves) {
registration.addRecipeCatalyst(new ItemStack(compressedSieve), COMPRESSED_SIEVE);
}
registration.addRecipeCatalyst(new ItemStack(EItems.WOODEN_HAMMER.get()), HAMMER);
registration.addRecipeCatalyst(new ItemStack(EItems.STONE_HAMMER.get()), HAMMER);
@ -143,6 +153,13 @@ public class ExDeorumJeiPlugin implements IModPlugin {
registration.addRecipeCatalyst(new ItemStack(EItems.NETHERITE_HAMMER.get()), HAMMER);
registration.addRecipeCatalyst(new ItemStack(EItems.MECHANICAL_HAMMER.get()), HAMMER);
registration.addRecipeCatalyst(new ItemStack(EItems.COMPRESSED_WOODEN_HAMMER.get()), COMPRESSED_HAMMER);
registration.addRecipeCatalyst(new ItemStack(EItems.COMPRESSED_STONE_HAMMER.get()), COMPRESSED_HAMMER);
registration.addRecipeCatalyst(new ItemStack(EItems.COMPRESSED_GOLDEN_HAMMER.get()), COMPRESSED_HAMMER);
registration.addRecipeCatalyst(new ItemStack(EItems.COMPRESSED_IRON_HAMMER.get()), COMPRESSED_HAMMER);
registration.addRecipeCatalyst(new ItemStack(EItems.COMPRESSED_DIAMOND_HAMMER.get()), COMPRESSED_HAMMER);
registration.addRecipeCatalyst(new ItemStack(EItems.COMPRESSED_NETHERITE_HAMMER.get()), COMPRESSED_HAMMER);
registration.addRecipeCatalyst(new ItemStack(EItems.CROOK.get()), CROOK);
registration.addRecipeCatalyst(new ItemStack(EItems.BONE_CROOK.get()), CROOK);
}
@ -194,8 +211,11 @@ public class ExDeorumJeiPlugin implements IModPlugin {
addRecipes(registration, LAVA_CRUCIBLE, ERecipeTypes.LAVA_CRUCIBLE);
addRecipes(registration, WATER_CRUCIBLE, ERecipeTypes.WATER_CRUCIBLE);
addRecipes(registration, HAMMER, ERecipeTypes.HAMMER);
//noinspection rawtypes,unchecked
addRecipes(registration, COMPRESSED_HAMMER, ((DeferredHolder) ERecipeTypes.COMPRESSED_HAMMER));
registration.addRecipes(CROOK, CompatUtil.collectAllRecipes(ERecipeTypes.CROOK.get(), CrookJeiRecipe::create));
registration.addRecipes(SIEVE, GroupedSieveRecipe.getAllRecipesGrouped());
registration.addRecipes(SIEVE, GroupedSieveRecipe.getAllRecipesGrouped(ERecipeTypes.SIEVE.get()));
registration.addRecipes(COMPRESSED_SIEVE, GroupedSieveRecipe.getAllRecipesGrouped(ERecipeTypes.COMPRESSED_SIEVE.get()));
addCrucibleHeatSources(registration);
}

View File

@ -23,19 +23,25 @@ import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.helpers.IGuiHelper;
import mezz.jei.api.recipe.RecipeType;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import thedarkcolour.exdeorum.data.TranslationKeys;
import net.minecraft.world.level.storage.loot.providers.number.ConstantValue;
import thedarkcolour.exdeorum.recipe.hammer.HammerRecipe;
import thedarkcolour.exdeorum.registry.EItems;
import java.util.function.Supplier;
class HammerCategory extends OneToOneCategory<HammerRecipe> {
public HammerCategory(IGuiHelper helper, IDrawable arrow) {
super(helper, arrow, helper.createDrawableItemStack(new ItemStack(EItems.DIAMOND_HAMMER.get())), Component.translatable(TranslationKeys.HAMMER_CATEGORY_TITLE));
private final RecipeType<HammerRecipe> recipeType;
public HammerCategory(IGuiHelper helper, IDrawable arrow, Supplier<? extends Item> icon, Component title, RecipeType<HammerRecipe> recipeType) {
super(helper, arrow, helper.createDrawableItemStack(new ItemStack(icon.get())), title);
this.recipeType = recipeType;
}
@Override
public RecipeType<HammerRecipe> getRecipeType() {
return ExDeorumJeiPlugin.HAMMER;
return this.recipeType;
}
@Override
@ -45,7 +51,11 @@ class HammerCategory extends OneToOneCategory<HammerRecipe> {
@Override
protected void addOutput(IRecipeSlotBuilder slot, HammerRecipe recipe) {
slot.addItemStack(new ItemStack(recipe.result));
SieveCategory.addTooltips(slot, false, recipe.resultAmount);
if (recipe.resultAmount instanceof ConstantValue constant) {
slot.addItemStack(new ItemStack(recipe.result, (int) constant.value()));
} else {
slot.addItemStack(new ItemStack(recipe.result));
SieveCategory.addTooltips(slot, false, recipe.resultAmount);
}
}
}

View File

@ -33,6 +33,7 @@ import net.minecraft.ChatFormatting;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.ItemLike;
import net.minecraft.world.level.storage.loot.providers.number.BinomialDistributionGenerator;
import net.minecraft.world.level.storage.loot.providers.number.ConstantValue;
import net.minecraft.world.level.storage.loot.providers.number.NumberProvider;
@ -61,12 +62,16 @@ class SieveCategory implements IRecipeCategory<GroupedSieveRecipe> {
private final IDrawable icon;
private final Component title;
public SieveCategory(IGuiHelper helper) {
SieveCategory(IGuiHelper helper, ItemLike icon, Component title) {
this.background = Lazy.of(() -> helper.createBlankDrawable(WIDTH, ROW_START + 18 * GroupedSieveRecipe.maxSieveRows));
this.slot = helper.getSlotDrawable();
this.row = helper.createDrawable(ExDeorumJeiPlugin.EX_DEORUM_JEI_TEXTURE, 0, 0, 162, 18);
this.icon = helper.createDrawableItemStack(new ItemStack(DefaultMaterials.OAK_SIEVE.getItem()));
this.title = Component.translatable(TranslationKeys.SIEVE_CATEGORY_TITLE);
this.icon = helper.createDrawableItemStack(new ItemStack(icon));
this.title = title;
}
SieveCategory(IGuiHelper helper) {
this(helper, DefaultMaterials.OAK_SIEVE, Component.translatable(TranslationKeys.SIEVE_CATEGORY_TITLE));
}
@Override

View File

@ -24,8 +24,10 @@ import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.neoforged.neoforge.client.model.generators.BlockModelBuilder;
import net.neoforged.neoforge.client.model.generators.ConfiguredModel;
import net.neoforged.neoforge.client.model.generators.loaders.CompositeModelBuilder;
import thedarkcolour.exdeorum.material.DefaultMaterials;
import thedarkcolour.exdeorum.registry.EBlocks;
import thedarkcolour.exdeorum.registry.ECompressedBlocks;
import thedarkcolour.modkit.data.MKBlockModelProvider;
import java.util.Objects;
@ -38,6 +40,10 @@ class BlockModels {
models.simpleBlock(EBlocks.CRUSHED_DEEPSLATE.get());
models.simpleBlock(EBlocks.CRUSHED_BLACKSTONE.get());
for (var variant : ECompressedBlocks.ALL_VARIANTS) {
compressedBlock(models, variant.getBlock(), variant.getBase());
}
// Barrels
barrel(models, DefaultMaterials.OAK_BARREL.getBlock(), Blocks.OAK_PLANKS);
barrel(models, DefaultMaterials.SPRUCE_BARREL.getBlock(), Blocks.SPRUCE_PLANKS);
@ -64,6 +70,19 @@ class BlockModels {
sieve(models, DefaultMaterials.CRIMSON_SIEVE.getBlock(), Blocks.CRIMSON_PLANKS);
sieve(models, DefaultMaterials.WARPED_SIEVE.getBlock(), Blocks.WARPED_PLANKS);
// Compressed Sieves
compressedSieve(models, DefaultMaterials.OAK_COMPRESSED_SIEVE.getBlock(), Blocks.OAK_LOG);
compressedSieve(models, DefaultMaterials.SPRUCE_COMPRESSED_SIEVE.getBlock(), Blocks.SPRUCE_LOG);
compressedSieve(models, DefaultMaterials.BIRCH_COMPRESSED_SIEVE.getBlock(), Blocks.BIRCH_LOG);
compressedSieve(models, DefaultMaterials.JUNGLE_COMPRESSED_SIEVE.getBlock(), Blocks.JUNGLE_LOG);
compressedSieve(models, DefaultMaterials.ACACIA_COMPRESSED_SIEVE.getBlock(), Blocks.ACACIA_LOG);
compressedSieve(models, DefaultMaterials.DARK_OAK_COMPRESSED_SIEVE.getBlock(), Blocks.DARK_OAK_LOG);
compressedSieve(models, DefaultMaterials.MANGROVE_COMPRESSED_SIEVE.getBlock(), Blocks.MANGROVE_LOG);
compressedSieve(models, DefaultMaterials.CHERRY_COMPRESSED_SIEVE.getBlock(), Blocks.CHERRY_LOG);
compressedSieve(models, DefaultMaterials.BAMBOO_COMPRESSED_SIEVE.getBlock(), Blocks.BAMBOO_BLOCK);
compressedSieve(models, DefaultMaterials.WARPED_COMPRESSED_SIEVE.getBlock(), Blocks.WARPED_STEM);
compressedSieve(models, DefaultMaterials.CRIMSON_COMPRESSED_SIEVE.getBlock(), Blocks.CRIMSON_STEM);
// Lava Crucible
crucible(models, EBlocks.UNFIRED_PORCELAIN_CRUCIBLE.get());
crucible(models, DefaultMaterials.PORCELAIN_CRUCIBLE.getBlock());
@ -93,6 +112,11 @@ class BlockModels {
sieve(models, DefaultMaterials.ARCHWOOD_SIEVE.getBlock(), ModCompatData.ARCHWOOD_PLANKS.get());
compressedSieve(models, DefaultMaterials.CASCADING_ARCHWOOD_COMPRESSED_SIEVE.getBlock(), ModCompatData.CASCADING_ARCHWOOD_LOG.get());
compressedSieve(models, DefaultMaterials.BLAZING_ARCHWOOD_COMPRESSED_SIEVE.getBlock(), ModCompatData.BLAZING_ARCHWOOD_LOG.get());
compressedSieve(models, DefaultMaterials.VEXING_ARCHWOOD_COMPRESSED_SIEVE.getBlock(), ModCompatData.VEXING_ARCHWOOD_LOG.get());
compressedSieve(models, DefaultMaterials.FLOURISHING_ARCHWOOD_COMPRESSED_SIEVE.getBlock(), ModCompatData.FLOURISHING_ARCHWOOD_LOG.get());
crucible(models, DefaultMaterials.CASCADING_ARCHWOOD_CRUCIBLE.getBlock(), ModCompatData.CASCADING_ARCHWOOD_LOG.get());
crucible(models, DefaultMaterials.BLAZING_ARCHWOOD_CRUCIBLE.getBlock(), ModCompatData.BLAZING_ARCHWOOD_LOG.get());
crucible(models, DefaultMaterials.VEXING_ARCHWOOD_CRUCIBLE.getBlock(), ModCompatData.VEXING_ARCHWOOD_LOG.get());
@ -104,6 +128,9 @@ class BlockModels {
sieve(models, DefaultMaterials.SKYROOT_SIEVE.getBlock(), ModCompatData.SKYROOT_PLANKS.get(), "construction/");
compressedSieve(models, DefaultMaterials.SKYROOT_COMPRESSED_SIEVE.getBlock(), ModCompatData.SKYROOT_LOG.get(), "natural/", "");
compressedSieve(models, DefaultMaterials.GOLDEN_OAK_COMPRESSED_SIEVE.getBlock(), ModCompatData.GOLDEN_OAK_LOG.get(), "natural/", "");
crucible(models, DefaultMaterials.SKYROOT_CRUCIBLE.getBlock(), ModCompatData.SKYROOT_LOG.get(), "natural/", "");
crucible(models, DefaultMaterials.GOLDEN_OAK_CRUCIBLE.getBlock(), ModCompatData.GOLDEN_OAK_LOG.get(), "natural/", "");
}
@ -130,6 +157,15 @@ class BlockModels {
sieve(models, DefaultMaterials.MAPLE_SIEVE.getBlock(), ModCompatData.MAPLE_PLANKS.get(), woodPrefix);
sieve(models, DefaultMaterials.CRYSTALLIZED_SIEVE.getBlock(), ModCompatData.CRYSTALLIZED_PLANKS.get(), woodPrefix).renderType("translucent");
compressedSieve(models, DefaultMaterials.BLUEBRIGHT_COMPRESSED_SIEVE.getBlock(), ModCompatData.BLUEBRIGHT_LOG.get(), woodPrefix, logSuffix);
compressedSieve(models, DefaultMaterials.STARLIT_COMPRESSED_SIEVE.getBlock(), ModCompatData.STARLIT_LOG.get(), woodPrefix, logSuffix);
compressedSieve(models, DefaultMaterials.FROSTBRIGHT_COMPRESSED_SIEVE.getBlock(), ModCompatData.FROSTBRIGHT_LOG.get(), woodPrefix, logSuffix);
compressedSieve(models, DefaultMaterials.COMET_COMPRESSED_SIEVE.getBlock(), ModCompatData.COMET_LOG.get(), woodPrefix, logSuffix);
compressedSieve(models, DefaultMaterials.LUNAR_COMPRESSED_SIEVE.getBlock(), ModCompatData.LUNAR_LOG.get(), woodPrefix, logSuffix);
compressedSieve(models, DefaultMaterials.DUSK_COMPRESSED_SIEVE.getBlock(), ModCompatData.DUSK_LOG.get(), woodPrefix, logSuffix);
compressedSieve(models, DefaultMaterials.MAPLE_COMPRESSED_SIEVE.getBlock(), ModCompatData.MAPLE_LOG.get(), woodPrefix, logSuffix);
compressedSieve(models, DefaultMaterials.CRYSTALLIZED_COMPRESSED_SIEVE.getBlock(), ModCompatData.CRYSTALLIZED_LOG.get(), woodPrefix, logSuffix).renderType("translucent");
crucible(models, DefaultMaterials.BLUEBRIGHT_CRUCIBLE.getBlock(), ModCompatData.BLUEBRIGHT_LOG.get(), woodPrefix, logSuffix);
crucible(models, DefaultMaterials.STARLIT_CRUCIBLE.getBlock(), ModCompatData.STARLIT_LOG.get(), woodPrefix, logSuffix);
crucible(models, DefaultMaterials.FROSTBRIGHT_CRUCIBLE.getBlock(), ModCompatData.FROSTBRIGHT_LOG.get(), woodPrefix, logSuffix);
@ -163,6 +199,17 @@ class BlockModels {
sieve(models, DefaultMaterials.UMBRAN_SIEVE.getBlock(), ModCompatData.UMBRAN_PLANKS.get());
sieve(models, DefaultMaterials.HELLBARK_SIEVE.getBlock(), ModCompatData.HELLBARK_PLANKS.get());
compressedSieve(models, DefaultMaterials.FIR_COMPRESSED_SIEVE.getBlock(), ModCompatData.FIR_LOG.get());
compressedSieve(models, DefaultMaterials.REDWOOD_COMPRESSED_SIEVE.getBlock(), ModCompatData.REDWOOD_LOG.get());
compressedSieve(models, DefaultMaterials.MAHOGANY_COMPRESSED_SIEVE.getBlock(), ModCompatData.MAHOGANY_LOG.get());
compressedSieve(models, DefaultMaterials.JACARANDA_COMPRESSED_SIEVE.getBlock(), ModCompatData.JACARANDA_LOG.get());
compressedSieve(models, DefaultMaterials.PALM_COMPRESSED_SIEVE.getBlock(), ModCompatData.PALM_LOG.get());
compressedSieve(models, DefaultMaterials.WILLOW_COMPRESSED_SIEVE.getBlock(), ModCompatData.WILLOW_LOG.get());
compressedSieve(models, DefaultMaterials.DEAD_COMPRESSED_SIEVE.getBlock(), ModCompatData.DEAD_LOG.get());
compressedSieve(models, DefaultMaterials.MAGIC_COMPRESSED_SIEVE.getBlock(), ModCompatData.MAGIC_LOG.get());
compressedSieve(models, DefaultMaterials.UMBRAN_COMPRESSED_SIEVE.getBlock(), ModCompatData.UMBRAN_LOG.get());
compressedSieve(models, DefaultMaterials.HELLBARK_COMPRESSED_SIEVE.getBlock(), ModCompatData.HELLBARK_LOG.get());
crucible(models, DefaultMaterials.FIR_CRUCIBLE.getBlock(), ModCompatData.FIR_LOG.get());
crucible(models, DefaultMaterials.REDWOOD_CRUCIBLE.getBlock(), ModCompatData.REDWOOD_LOG.get());
crucible(models, DefaultMaterials.MAHOGANY_CRUCIBLE.getBlock(), ModCompatData.MAHOGANY_LOG.get());
@ -180,6 +227,27 @@ class BlockModels {
crucible(models, block, block);
}
public static void compressedBlock(MKBlockModelProvider models, Block block, Block appearance) {
var original = models.file(models.blockTexture(appearance));
models.getVariantBuilder(block).partialState().addModels(new ConfiguredModel(
models.models().getBuilder(models.name(block)).customLoader(CompositeModelBuilder::begin)
.child("base", models.models().nested()
.parent(original)
.renderType("solid")
)
.child("overlay", models.models().nested()
.parent(models.mcFile("cube_all"))
.texture("all", models.modLoc("block/compressed_overlay"))
.renderType("translucent")
)
.itemRenderOrder("base", "overlay")
.end()
.parent(models.mcFile("block"))
.texture("particle", models.blockTexture(appearance))
));
}
public static void crucible(MKBlockModelProvider models, Block block, Block appearance) {
crucible(models, block, appearance, "", "");
}
@ -220,6 +288,16 @@ class BlockModels {
.texture("texture", texture(appearance, pathPrefix, ""));
}
public static void compressedSieve(MKBlockModelProvider models, Block block, Block appearance) {
compressedSieve(models, block, appearance, "", "");
}
public static BlockModelBuilder compressedSieve(MKBlockModelProvider models, Block block, Block appearance, String pathPrefix, String pathSuffix) {
return singleModel(models, block)
.parent(models.modFile("template_compressed_sieve"))
.texture("texture", texture(appearance, pathPrefix, pathSuffix));
}
public static BlockModelBuilder singleModel(MKBlockModelProvider models, Block block) {
BlockModelBuilder builder = blockModel(models, block);

View File

@ -19,10 +19,12 @@
package thedarkcolour.exdeorum.data;
import net.minecraft.tags.TagKey;
import org.apache.commons.lang3.text.WordUtils;
import thedarkcolour.exdeorum.ExDeorum;
import thedarkcolour.exdeorum.client.screen.RedstoneControlWidget;
import thedarkcolour.exdeorum.material.DefaultMaterials;
import thedarkcolour.exdeorum.registry.EBlocks;
import thedarkcolour.exdeorum.registry.ECompressedBlocks;
import thedarkcolour.exdeorum.registry.EFluids;
import thedarkcolour.exdeorum.tag.EItemTags;
import thedarkcolour.modkit.data.MKEnglishProvider;
@ -33,6 +35,7 @@ class English {
english.add(EItemTags.CROOKS, "Crooks");
english.add(EItemTags.HAMMERS, "Hammers");
english.add(EItemTags.COMPRESSED_HAMMERS, "Compressed Hammers");
english.add(EItemTags.SIEVE_MESHES, "Sieve Meshes");
english.add(EItemTags.PEBBLES, "Pebbles");
english.add(EItemTags.END_CAKE_MATERIAL, "End Cake Materials");
@ -40,6 +43,13 @@ class English {
english.add(EItemTags.STONE_BARRELS, "Stone Barrels");
english.add(EItemTags.BARRELS, "Barrels");
for (var variant : ECompressedBlocks.ALL_VARIANTS) {
// todo add a "capitalize ID" method to ModKit so I don't have to keep track of this code
//noinspection deprecation
english.add(variant.getTag(), WordUtils.capitalize(variant.getId().getPath().replace('_', ' ')));
}
english.add(EItemTags.COMPRESSED_SANDS, "Compressed Sands");
english.add(EFluids.WITCH_WATER_TYPE.get(), "Witch Water");
english.add(TranslationKeys.MAIN_CREATIVE_TAB, "Ex Deorum");
@ -85,9 +95,11 @@ class English {
english.add(TranslationKeys.CRUCIBLE_HEAT_SOURCE_CATEGORY_TITLE, "Crucible Heat Sources");
english.add(TranslationKeys.CRUCIBLE_HEAT_SOURCE_CATEGORY_MULTIPLIER, "Melt Rate: %sx");
english.add(TranslationKeys.HAMMER_CATEGORY_TITLE, "Hammer");
english.add(TranslationKeys.COMPRESSED_HAMMER_CATEGORY_TITLE, "Compressed Hammer");
english.add(TranslationKeys.CROOK_CATEGORY_TITLE, "Crook");
english.add(TranslationKeys.CROOK_CATEGORY_REQUIRES_STATE, "Requires properties:");
english.add(TranslationKeys.SIEVE_CATEGORY_TITLE, "Sieve");
english.add(TranslationKeys.COMPRESSED_SIEVE_CATEGORY_TITLE, "Compressed Sieve");
english.add(TranslationKeys.SIEVE_RECIPE_CHANCE, "Chance: %s%%");
english.add(TranslationKeys.SIEVE_RECIPE_AVERAGE_OUTPUT, "Avg. Output: %s");
english.add(TranslationKeys.SIEVE_RECIPE_MIN_OUTPUT, "Min: %s");

View File

@ -33,11 +33,10 @@ import net.minecraft.world.level.levelgen.structure.StructureSet;
import net.minecraft.world.level.material.Fluid;
import thedarkcolour.exdeorum.ExDeorum;
import thedarkcolour.exdeorum.block.AbstractCrucibleBlock;
import thedarkcolour.exdeorum.material.AbstractCrucibleMaterial;
import thedarkcolour.exdeorum.material.BarrelMaterial;
import thedarkcolour.exdeorum.material.DefaultMaterials;
import thedarkcolour.exdeorum.material.SieveMaterial;
import thedarkcolour.exdeorum.compat.ModIds;
import thedarkcolour.exdeorum.material.*;
import thedarkcolour.exdeorum.registry.EBlocks;
import thedarkcolour.exdeorum.registry.ECompressedBlocks;
import thedarkcolour.exdeorum.registry.EFluids;
import thedarkcolour.exdeorum.registry.EItems;
import thedarkcolour.exdeorum.tag.EBlockTags;
@ -71,17 +70,24 @@ class ModTags {
.add(WOODEN_BARRELS.stream().map(BarrelMaterial::getBlock).toArray(Block[]::new))
.add(DefaultMaterials.SIEVES.stream().filter(material -> material != DefaultMaterials.CRYSTALLIZED_SIEVE).map(SieveMaterial::getBlock).toArray(Block[]::new))
.add(DefaultMaterials.WATER_CRUCIBLES.stream().map(AbstractCrucibleMaterial::getBlock).toArray(Block[]::new))
.add(DefaultMaterials.WARPED_CRUCIBLE.getBlock(), DefaultMaterials.CRIMSON_CRUCIBLE.getBlock(), DefaultMaterials.HELLBARK_CRUCIBLE.getBlock());
.add(DefaultMaterials.WARPED_CRUCIBLE.getBlock(), DefaultMaterials.CRIMSON_CRUCIBLE.getBlock(), DefaultMaterials.HELLBARK_CRUCIBLE.getBlock())
.add(DefaultMaterials.COMPRESSED_SIEVES.stream().filter(material -> material != DefaultMaterials.CRYSTALLIZED_COMPRESSED_SIEVE).map(CompressedSieveMaterial::getBlock).toArray(Block[]::new));
tags.tag(BlockTags.MINEABLE_WITH_PICKAXE)
.add(EBlocks.UNFIRED_PORCELAIN_CRUCIBLE, EBlocks.MECHANICAL_SIEVE, EBlocks.MECHANICAL_HAMMER)
.add(DefaultMaterials.STONE_BARREL.getBlock(), DefaultMaterials.CRYSTALLIZED_BARREL.getBlock(), DefaultMaterials.CRYSTALLIZED_SIEVE.getBlock(), DefaultMaterials.PORCELAIN_CRUCIBLE.getBlock(), DefaultMaterials.CRYSTALLIZED_CRUCIBLE.getBlock());
tags.tag(BlockTags.MINEABLE_WITH_SHOVEL).add(EBlocks.DUST, EBlocks.CRUSHED_NETHERRACK, EBlocks.CRUSHED_END_STONE, EBlocks.CRUSHED_DEEPSLATE, EBlocks.CRUSHED_BLACKSTONE);
tags.tag(BlockTags.MINEABLE_WITH_HOE).add(EBlocks.INFESTED_LEAVES);
.add(DefaultMaterials.STONE_BARREL.getBlock(), DefaultMaterials.CRYSTALLIZED_BARREL.getBlock(), DefaultMaterials.CRYSTALLIZED_SIEVE.getBlock(), DefaultMaterials.PORCELAIN_CRUCIBLE.getBlock(), DefaultMaterials.CRYSTALLIZED_CRUCIBLE.getBlock())
.add(ECompressedBlocks.COMPRESSED_COBBLESTONE.getBlock(), ECompressedBlocks.COMPRESSED_DIORITE.getBlock(), ECompressedBlocks.COMPRESSED_GRANITE.getBlock(), ECompressedBlocks.COMPRESSED_ANDESITE.getBlock(), ECompressedBlocks.COMPRESSED_DEEPSLATE.getBlock(), ECompressedBlocks.COMPRESSED_COBBLED_DEEPSLATE.getBlock(), ECompressedBlocks.COMPRESSED_NETHERRACK.getBlock(), ECompressedBlocks.COMPRESSED_BLACKSTONE.getBlock(), ECompressedBlocks.COMPRESSED_END_STONE.getBlock());
tags.tag(BlockTags.MINEABLE_WITH_SHOVEL)
.add(EBlocks.DUST, EBlocks.CRUSHED_NETHERRACK, EBlocks.CRUSHED_END_STONE, EBlocks.CRUSHED_DEEPSLATE, EBlocks.CRUSHED_BLACKSTONE)
.add(ECompressedBlocks.COMPRESSED_DIRT.getBlock(), ECompressedBlocks.COMPRESSED_GRAVEL.getBlock(), ECompressedBlocks.COMPRESSED_SAND.getBlock(), ECompressedBlocks.COMPRESSED_DUST.getBlock(), ECompressedBlocks.COMPRESSED_RED_SAND.getBlock(), ECompressedBlocks.COMPRESSED_CRUSHED_DEEPSLATE.getBlock(), ECompressedBlocks.COMPRESSED_CRUSHED_BLACKSTONE.getBlock(), ECompressedBlocks.COMPRESSED_CRUSHED_NETHERRACK.getBlock(), ECompressedBlocks.COMPRESSED_SOUL_SAND.getBlock(), ECompressedBlocks.COMPRESSED_CRUSHED_END_STONE.getBlock());
tags.tag(BlockTags.MINEABLE_WITH_HOE)
.add(EBlocks.INFESTED_LEAVES)
.add(ECompressedBlocks.COMPRESSED_MOSS_BLOCK.getBlock());
tags.tag(BlockTags.LEAVES).add(EBlocks.INFESTED_LEAVES);
}
public static void createItemTags(MKTagsProvider<Item> tags) {
tags.tag(EItemTags.HAMMERS).add(EItems.WOODEN_HAMMER, EItems.STONE_HAMMER, EItems.GOLDEN_HAMMER, EItems.IRON_HAMMER, EItems.DIAMOND_HAMMER, EItems.NETHERITE_HAMMER);
tags.tag(EItemTags.COMPRESSED_HAMMERS).add(EItems.COMPRESSED_WOODEN_HAMMER, EItems.COMPRESSED_STONE_HAMMER, EItems.COMPRESSED_GOLDEN_HAMMER, EItems.COMPRESSED_IRON_HAMMER, EItems.COMPRESSED_DIAMOND_HAMMER, EItems.COMPRESSED_NETHERITE_HAMMER);
tags.tag(EItemTags.CROOKS).add(EItems.CROOK, EItems.BONE_CROOK);
tags.tag(EItemTags.SIEVE_MESHES).add(EItems.STRING_MESH, EItems.FLINT_MESH, EItems.IRON_MESH, EItems.GOLDEN_MESH, EItems.DIAMOND_MESH, EItems.NETHERITE_MESH);
tags.tag(EItemTags.PEBBLES).add(EItems.STONE_PEBBLE, EItems.DIORITE_PEBBLE, EItems.GRANITE_PEBBLE, EItems.ANDESITE_PEBBLE, EItems.DEEPSLATE_PEBBLE, EItems.TUFF_PEBBLE, EItems.CALCITE_PEBBLE, EItems.BLACKSTONE_PEBBLE, EItems.BASALT_PEBBLE);
@ -89,6 +95,21 @@ class ModTags {
tags.tag(EItemTags.WOODEN_BARRELS).add(WOODEN_BARRELS.stream().map(BarrelMaterial::getItem).toArray(Item[]::new));
tags.tag(EItemTags.STONE_BARRELS).add(DefaultMaterials.STONE_BARREL.getItem(), DefaultMaterials.CRYSTALLIZED_BARREL.getItem());
tags.tag(EItemTags.BARRELS).addTags(EItemTags.WOODEN_BARRELS, EItemTags.STONE_BARRELS);
// Cyclic adds ONE compressed block :)
tags.tag(ECompressedBlocks.COMPRESSED_COBBLESTONE.getTag()).addOptional(new ResourceLocation(ModIds.CYCLIC, "compressed_cobblestone"));
for (var variant : ECompressedBlocks.ALL_VARIANTS) {
var builder = tags.tag(variant.getTag()).add(variant.getItem());
if (variant.hasAtc()) {
builder.addOptional(variant.getAtc());
}
if (variant.hasCompressium()) {
builder.addOptional(variant.getCompressium());
}
}
tags.tag(EItemTags.COMPRESSED_SANDS).addTags(ECompressedBlocks.COMPRESSED_SAND.getTag(), ECompressedBlocks.COMPRESSED_RED_SAND.getTag());
}
public static void createStructureSetTags(MKTagsProvider<StructureSet> tags) {

View File

@ -70,9 +70,11 @@ public class TranslationKeys {
public static final String CRUCIBLE_HEAT_SOURCE_CATEGORY_TITLE = "gui." + ExDeorum.ID + ".category.crucible_heat_source";
public static final String CRUCIBLE_HEAT_SOURCE_CATEGORY_MULTIPLIER = "gui." + ExDeorum.ID + ".category.crucible_heat_source.multiplier";
public static final String HAMMER_CATEGORY_TITLE = "gui." + ExDeorum.ID + ".category.hammer";
public static final String COMPRESSED_HAMMER_CATEGORY_TITLE = "gui." + ExDeorum.ID + ".category.compressed_hammer";
public static final String CROOK_CATEGORY_TITLE = "gui." + ExDeorum.ID + ".category.crook";
public static final String CROOK_CATEGORY_REQUIRES_STATE = "gui." + ExDeorum.ID + ".category.crook.requires_state";
public static final String SIEVE_CATEGORY_TITLE = "gui." + ExDeorum.ID + ".category.sieve";
public static final String COMPRESSED_SIEVE_CATEGORY_TITLE = "gui." + ExDeorum.ID + ".category.sieve";
public static final String SIEVE_RECIPE_CHANCE = "gui." + ExDeorum.ID + ".category.sieve.chance";
public static final String SIEVE_RECIPE_AVERAGE_OUTPUT = "gui." + ExDeorum.ID + ".category.sieve.average_output";
public static final String SIEVE_RECIPE_MIN_OUTPUT = "gui." + ExDeorum.ID + ".category.sieve.min_output";

View File

@ -22,6 +22,7 @@ import net.minecraft.advancements.critereon.StatePropertiesPredicate;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.data.recipes.RecipeCategory;
import net.minecraft.data.recipes.RecipeOutput;
import net.minecraft.data.recipes.ShapelessRecipeBuilder;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.BlockTags;
import net.minecraft.tags.ItemTags;
@ -37,6 +38,7 @@ import net.minecraft.world.level.block.CampfireBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.level.storage.loot.providers.number.BinomialDistributionGenerator;
import net.minecraft.world.level.storage.loot.providers.number.ConstantValue;
import net.minecraft.world.level.storage.loot.providers.number.NumberProvider;
import net.minecraft.world.level.storage.loot.providers.number.UniformGenerator;
@ -59,19 +61,24 @@ import thedarkcolour.exdeorum.recipe.BlockPredicate;
import thedarkcolour.exdeorum.recipe.crook.CrookRecipe;
import thedarkcolour.exdeorum.recipe.crucible.CrucibleHeatRecipe;
import thedarkcolour.exdeorum.recipe.crucible.CrucibleRecipe;
import thedarkcolour.exdeorum.recipe.hammer.CompressedHammerRecipe;
import thedarkcolour.exdeorum.recipe.hammer.HammerRecipe;
import thedarkcolour.exdeorum.registry.EBlocks;
import thedarkcolour.exdeorum.registry.ECompressedBlocks;
import thedarkcolour.exdeorum.registry.EFluids;
import thedarkcolour.exdeorum.registry.EItems;
import thedarkcolour.exdeorum.tag.EItemTags;
import thedarkcolour.modkit.data.MKRecipeProvider;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
import static net.minecraft.world.level.storage.loot.providers.number.BinomialDistributionGenerator.binomial;
import static net.minecraft.world.level.storage.loot.providers.number.ConstantValue.exactly;
import static net.minecraft.world.level.storage.loot.providers.number.UniformGenerator.between;
import static thedarkcolour.modkit.data.MKRecipeProvider.ingredient;
import static thedarkcolour.modkit.data.MKRecipeProvider.path;
import static thedarkcolour.modkit.data.MKRecipeProvider.*;
import static thedarkcolour.modkit.data.MKRecipeProvider.id;
public class Recipes {
private static final Ingredient SPORES_AND_SEEDS = ingredient(EItems.GRASS_SEEDS, EItems.MYCELIUM_SPORES, EItems.WARPED_NYLIUM_SPORES, EItems.CRIMSON_NYLIUM_SPORES);
@ -82,6 +89,7 @@ public class Recipes {
SieveRecipes.sieveRecipes(writer);
crucibleRecipes(writer);
hammerRecipes(writer);
compressedHammerRecipes(writer);
crookRecipes(writer);
crucibleHeatSources(writer);
barrelCompostRecipes(writer);
@ -194,6 +202,79 @@ public class Recipes {
recipes.grid2x2(RecipeCategory.BUILDING_BLOCKS, Items.COPPER_ORE, ingredient(EItems.COPPER_ORE_CHUNK));
recipes.grid2x2(RecipeCategory.BUILDING_BLOCKS, Items.MOSS_BLOCK, ingredient(EItems.GRASS_SEEDS));
// Compressed hammers
recipes.grid3x3(RecipeCategory.TOOLS, EItems.COMPRESSED_WOODEN_HAMMER.get(), ingredient(EItems.WOODEN_HAMMER));
recipes.grid3x3(RecipeCategory.TOOLS, EItems.COMPRESSED_STONE_HAMMER.get(), ingredient(EItems.STONE_HAMMER));
recipes.grid3x3(RecipeCategory.TOOLS, EItems.COMPRESSED_GOLDEN_HAMMER.get(), ingredient(EItems.GOLDEN_HAMMER));
recipes.grid3x3(RecipeCategory.TOOLS, EItems.COMPRESSED_IRON_HAMMER.get(), ingredient(EItems.IRON_HAMMER));
recipes.grid3x3(RecipeCategory.TOOLS, EItems.COMPRESSED_DIAMOND_HAMMER.get(), ingredient(EItems.DIAMOND_HAMMER));
recipes.grid3x3(RecipeCategory.TOOLS, EItems.COMPRESSED_NETHERITE_HAMMER.get(), ingredient(EItems.NETHERITE_HAMMER));
// Compressed blocks
for (var variant : ECompressedBlocks.ALL_VARIANTS) {
var storage = variant.getBlock();
var material = variant.getBase();
// Auto disable my recipe when other "compressed" mods are present
if (variant.hasCompressium() || variant.hasAtc()) {
var conditions = new ArrayList<ICondition>();
if (variant.hasAtc()) {
conditions.add(modNotInstalled(ModIds.ALL_THE_COMPRESSED));
}
if (variant.hasCompressium()) {
conditions.add(modNotInstalled(ModIds.COMPRESSIUM));
}
recipes.conditional(path(storage), conditions, newWriter -> {
recipes.grid3x3(RecipeCategory.BUILDING_BLOCKS, storage, Ingredient.of(material));
});
} else {
recipes.grid3x3(RecipeCategory.BUILDING_BLOCKS, storage, Ingredient.of(material));
}
// still allow uncrafting
ShapelessRecipeBuilder fromStorage = new ShapelessRecipeBuilder(RecipeCategory.MISC, material, 9);
unlockedByHaving(fromStorage, storage);
fromStorage.requires(storage);
fromStorage.save(writer, id(material).withSuffix("_from_" + id(storage).getPath()));
}
// Compressed sieves
compressedSieve(recipes, DefaultMaterials.OAK_COMPRESSED_SIEVE, ingredient(Items.OAK_LOG));
compressedSieve(recipes, DefaultMaterials.SPRUCE_COMPRESSED_SIEVE, ingredient(Items.SPRUCE_LOG));
compressedSieve(recipes, DefaultMaterials.BIRCH_COMPRESSED_SIEVE, ingredient(Items.BIRCH_LOG));
compressedSieve(recipes, DefaultMaterials.JUNGLE_COMPRESSED_SIEVE, ingredient(Items.JUNGLE_LOG));
compressedSieve(recipes, DefaultMaterials.ACACIA_COMPRESSED_SIEVE, ingredient(Items.ACACIA_LOG));
compressedSieve(recipes, DefaultMaterials.DARK_OAK_COMPRESSED_SIEVE, ingredient(Items.DARK_OAK_LOG));
compressedSieve(recipes, DefaultMaterials.MANGROVE_COMPRESSED_SIEVE, ingredient(Items.MANGROVE_LOG));
compressedSieve(recipes, DefaultMaterials.CHERRY_COMPRESSED_SIEVE, ingredient(Items.CHERRY_LOG));
compressedSieve(recipes, DefaultMaterials.BAMBOO_COMPRESSED_SIEVE, ingredient(Items.BAMBOO_BLOCK));
compressedSieve(recipes, DefaultMaterials.WARPED_COMPRESSED_SIEVE, ingredient(Items.WARPED_STEM));
compressedSieve(recipes, DefaultMaterials.CRIMSON_COMPRESSED_SIEVE, ingredient(Items.CRIMSON_STEM));
modCompressedSieve(recipes, ModIds.BIOMES_O_PLENTY, DefaultMaterials.FIR_COMPRESSED_SIEVE, ingredient(ModCompatData.FIR_LOG_ITEM));
modCompressedSieve(recipes, ModIds.BIOMES_O_PLENTY, DefaultMaterials.REDWOOD_COMPRESSED_SIEVE, ingredient(ModCompatData.REDWOOD_LOG_ITEM));
modCompressedSieve(recipes, ModIds.BIOMES_O_PLENTY, DefaultMaterials.MAHOGANY_COMPRESSED_SIEVE, ingredient(ModCompatData.MAHOGANY_LOG_ITEM));
modCompressedSieve(recipes, ModIds.BIOMES_O_PLENTY, DefaultMaterials.JACARANDA_COMPRESSED_SIEVE, ingredient(ModCompatData.JACARANDA_LOG_ITEM));
modCompressedSieve(recipes, ModIds.BIOMES_O_PLENTY, DefaultMaterials.PALM_COMPRESSED_SIEVE, ingredient(ModCompatData.PALM_LOG_ITEM));
modCompressedSieve(recipes, ModIds.BIOMES_O_PLENTY, DefaultMaterials.WILLOW_COMPRESSED_SIEVE, ingredient(ModCompatData.WILLOW_LOG_ITEM));
modCompressedSieve(recipes, ModIds.BIOMES_O_PLENTY, DefaultMaterials.DEAD_COMPRESSED_SIEVE, ingredient(ModCompatData.DEAD_LOG_ITEM));
modCompressedSieve(recipes, ModIds.BIOMES_O_PLENTY, DefaultMaterials.MAGIC_COMPRESSED_SIEVE, ingredient(ModCompatData.MAGIC_LOG_ITEM));
modCompressedSieve(recipes, ModIds.BIOMES_O_PLENTY, DefaultMaterials.UMBRAN_COMPRESSED_SIEVE, ingredient(ModCompatData.UMBRAN_LOG_ITEM));
modCompressedSieve(recipes, ModIds.BIOMES_O_PLENTY, DefaultMaterials.HELLBARK_COMPRESSED_SIEVE, ingredient(ModCompatData.HELLBARK_LOG_ITEM));
modCompressedSieve(recipes, ModIds.ARS_NOUVEAU, DefaultMaterials.CASCADING_ARCHWOOD_COMPRESSED_SIEVE, ingredient(ModCompatData.CASCADING_ARCHWOOD_LOG_ITEM));
modCompressedSieve(recipes, ModIds.ARS_NOUVEAU, DefaultMaterials.BLAZING_ARCHWOOD_COMPRESSED_SIEVE, ingredient(ModCompatData.BLAZING_ARCHWOOD_LOG_ITEM));
modCompressedSieve(recipes, ModIds.ARS_NOUVEAU, DefaultMaterials.VEXING_ARCHWOOD_COMPRESSED_SIEVE, ingredient(ModCompatData.VEXING_ARCHWOOD_LOG_ITEM));
modCompressedSieve(recipes, ModIds.ARS_NOUVEAU, DefaultMaterials.FLOURISHING_ARCHWOOD_COMPRESSED_SIEVE, ingredient(ModCompatData.FLOURISHING_ARCHWOOD_LOG_ITEM));
modCompressedSieve(recipes, ModIds.AETHER, DefaultMaterials.SKYROOT_COMPRESSED_SIEVE, ingredient(ModCompatData.SKYROOT_LOG_ITEM));
modCompressedSieve(recipes, ModIds.AETHER, DefaultMaterials.GOLDEN_OAK_COMPRESSED_SIEVE, ingredient(ModCompatData.GOLDEN_OAK_LOG_ITEM));
modCompressedSieve(recipes, ModIds.BLUE_SKIES, DefaultMaterials.BLUEBRIGHT_COMPRESSED_SIEVE, ingredient(ModCompatData.BLUEBRIGHT_LOG_ITEM));
modCompressedSieve(recipes, ModIds.BLUE_SKIES, DefaultMaterials.STARLIT_COMPRESSED_SIEVE, ingredient(ModCompatData.STARLIT_LOG_ITEM));
modCompressedSieve(recipes, ModIds.BLUE_SKIES, DefaultMaterials.FROSTBRIGHT_COMPRESSED_SIEVE, ingredient(ModCompatData.FROSTBRIGHT_LOG_ITEM));
modCompressedSieve(recipes, ModIds.BLUE_SKIES, DefaultMaterials.COMET_COMPRESSED_SIEVE, ingredient(ModCompatData.COMET_LOG_ITEM));
modCompressedSieve(recipes, ModIds.BLUE_SKIES, DefaultMaterials.LUNAR_COMPRESSED_SIEVE, ingredient(ModCompatData.LUNAR_LOG_ITEM));
modCompressedSieve(recipes, ModIds.BLUE_SKIES, DefaultMaterials.DUSK_COMPRESSED_SIEVE, ingredient(ModCompatData.DUSK_LOG_ITEM));
modCompressedSieve(recipes, ModIds.BLUE_SKIES, DefaultMaterials.MAPLE_COMPRESSED_SIEVE, ingredient(ModCompatData.MAPLE_LOG_ITEM));
modCompressedSieve(recipes, ModIds.BLUE_SKIES, DefaultMaterials.CRYSTALLIZED_COMPRESSED_SIEVE, ingredient(ModCompatData.CRYSTALLIZED_LOG_ITEM));
// Modded ores
grid2x2TagResult(writer, EItemTags.ORES_ALUMINUM, ingredient(EItems.ALUMINUM_ORE_CHUNK));
grid2x2TagResult(writer, EItemTags.ORES_COBALT, ingredient(EItems.COBALT_ORE_CHUNK));
@ -375,6 +456,23 @@ public class Recipes {
});
}
private static void compressedSieve(MKRecipeProvider recipes, ItemLike result, Ingredient log) {
recipes.shapedCrafting(RecipeCategory.MISC, result.asItem(), recipe -> {
recipe.define('O', log);
recipe.define('I', Tags.Items.RODS_WOODEN);
recipe.define('_', Tags.Items.INGOTS_IRON);
recipe.pattern("O O");
recipe.pattern("O_O");
recipe.pattern("I I");
});
}
private static void modCompressedSieve(MKRecipeProvider recipes, String modid, ItemLike result, Ingredient log) {
recipes.conditional(path(result), List.of(modInstalled(modid)), writer1 -> {
compressedSieve(recipes, result, log);
});
}
private static void mesh(MKRecipeProvider recipes, Supplier<? extends Item> result, Ingredient ingredient) {
recipes.shapedCrafting(RecipeCategory.MISC, result.get(), recipe -> {
recipe.define('#', ingredient);
@ -488,6 +586,22 @@ public class Recipes {
hammerRecipe(writer, "pointed_dripstone", ingredient(Items.DRIPSTONE_BLOCK), Items.POINTED_DRIPSTONE, between(2, 4));
}
private static void compressedHammerRecipes(RecipeOutput writer) {
compressedHammerRecipe(writer, Items.GRAVEL, ingredient(ECompressedBlocks.COMPRESSED_COBBLESTONE.getTag(), ECompressedBlocks.COMPRESSED_DIORITE.getTag(), ECompressedBlocks.COMPRESSED_GRANITE.getTag(), ECompressedBlocks.COMPRESSED_ANDESITE.getTag()));
compressedHammerRecipe(writer, Items.SAND, ingredient(ECompressedBlocks.COMPRESSED_GRAVEL.getTag()));
compressedHammerRecipe(writer, EItems.DUST.get(), ingredient(EItemTags.COMPRESSED_SANDS));
compressedHammerRecipe(writer, EItems.CRUSHED_DEEPSLATE.get(), ingredient(ECompressedBlocks.COMPRESSED_DEEPSLATE.getTag(), ECompressedBlocks.COMPRESSED_COBBLED_DEEPSLATE.getTag()));
compressedHammerRecipe(writer, EItems.CRUSHED_NETHERRACK.get(), ingredient(ECompressedBlocks.COMPRESSED_NETHERRACK.getTag()));
compressedHammerRecipe(writer, EItems.CRUSHED_BLACKSTONE.get(), ingredient(ECompressedBlocks.COMPRESSED_BLACKSTONE.getTag()));
compressedHammerRecipe(writer, EItems.CRUSHED_END_STONE.get(), ingredient(ECompressedBlocks.COMPRESSED_END_STONE.getTag()));
compressedHammerRecipe(writer, Items.RED_SAND, ingredient(ECompressedBlocks.COMPRESSED_CRUSHED_NETHERRACK.getTag()));
}
private static void compressedHammerRecipe(RecipeOutput writer, ItemLike result, Ingredient block) {
writer.accept(modLoc("compressed_hammer/" + path(result)), new CompressedHammerRecipe(block, result.asItem(), exactly(9)), null);
}
private static void hammerRecipe(RecipeOutput writer, String name, Ingredient block, ItemLike result) {
hammerRecipe(writer, name, block, result, ConstantValue.exactly(1f));
}
@ -655,7 +769,19 @@ public class Recipes {
return new ModLoadedCondition(modid);
}
static ICondition modNotInstalled(String modid) {
return new NotCondition(modInstalled(modid));
}
static final ICondition AE2 = modInstalled(ModIds.APPLIED_ENERGISTICS_2);
static final ICondition ENDERIO = modInstalled(ModIds.ENDERIO);
static final ICondition EXTREME_REACTORS = modInstalled(ModIds.EXTREME_REACTORS);
static NumberProvider compressedMultiplier(NumberProvider resultAmount) {
if (resultAmount instanceof BinomialDistributionGenerator binomial) {
return binomial((int) ((ConstantValue) binomial.n()).value() * 7, ((ConstantValue) binomial.p()).value());
} else {
throw new IllegalArgumentException("Unable to multiply type " + resultAmount.getClass());
}
}
}

View File

@ -18,8 +18,9 @@
package thedarkcolour.exdeorum.data.recipe;
import com.google.common.collect.ImmutableMap;
import net.minecraft.data.recipes.RecipeOutput;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.level.ItemLike;
@ -27,26 +28,57 @@ import net.minecraft.world.level.storage.loot.providers.number.BinomialDistribut
import net.minecraft.world.level.storage.loot.providers.number.NumberProvider;
import net.neoforged.neoforge.common.conditions.ICondition;
import net.neoforged.neoforge.registries.DeferredItem;
import thedarkcolour.exdeorum.ExDeorum;
import thedarkcolour.exdeorum.compat.ModIds;
import thedarkcolour.exdeorum.data.ModCompatData;
import thedarkcolour.exdeorum.recipe.sieve.CompressedSieveRecipe;
import thedarkcolour.exdeorum.recipe.sieve.SieveRecipe;
import thedarkcolour.exdeorum.registry.ECompressedBlocks;
import thedarkcolour.exdeorum.registry.EItems;
import thedarkcolour.exdeorum.tag.EItemTags;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import static net.minecraft.world.level.storage.loot.providers.number.BinomialDistributionGenerator.binomial;
import static thedarkcolour.exdeorum.data.recipe.Recipes.modLoc;
import static thedarkcolour.modkit.data.MKRecipeProvider.ingredient;
import static thedarkcolour.modkit.data.MKRecipeProvider.path;
class SieveRecipes {
// Ingredients do not implement .equals, so we need constants in order to map them to compressed variants
private static final Ingredient
DIRT = ingredient(Items.DIRT),
GRAVEL = ingredient(Items.GRAVEL),
SAND = ingredient(Items.SAND),
DUST = ingredient(EItems.DUST.get()),
RED_SAND = ingredient(Items.RED_SAND),
CRUSHED_DEEPSLATE = ingredient(EItems.CRUSHED_DEEPSLATE.get()),
CRUSHED_BLACKSTONE = ingredient(EItems.CRUSHED_BLACKSTONE.get()),
CRUSHED_NETHERRACK = ingredient(EItems.CRUSHED_NETHERRACK.get()),
SOUL_SAND = ingredient(Items.SOUL_SAND),
CRUSHED_END_STONE = ingredient(EItems.CRUSHED_END_STONE),
MOSS_BLOCK = ingredient(Items.MOSS_BLOCK);
// mod condition is null for ex deorum blocks (ex deorum is always last priority)
private static final Map<Ingredient, Ingredient> COMPRESSED_VARIANTS = ImmutableMap.<Ingredient, Ingredient>builder()
.put(DIRT, ingredient(ECompressedBlocks.COMPRESSED_DIRT.getTag()))
.put(GRAVEL, ingredient(ECompressedBlocks.COMPRESSED_GRAVEL.getTag()))
.put(SAND, ingredient(ECompressedBlocks.COMPRESSED_SAND.getTag()))
.put(DUST, ingredient(ECompressedBlocks.COMPRESSED_DUST.getTag()))
.put(RED_SAND, ingredient(ECompressedBlocks.COMPRESSED_RED_SAND.getTag()))
.put(CRUSHED_DEEPSLATE, ingredient(ECompressedBlocks.COMPRESSED_CRUSHED_DEEPSLATE.getTag()))
.put(CRUSHED_BLACKSTONE, ingredient(ECompressedBlocks.COMPRESSED_CRUSHED_BLACKSTONE.getTag()))
.put(CRUSHED_NETHERRACK, ingredient(ECompressedBlocks.COMPRESSED_CRUSHED_NETHERRACK.getTag()))
.put(SOUL_SAND, ingredient(ECompressedBlocks.COMPRESSED_SOUL_SAND.getTag()))
.put(CRUSHED_END_STONE, ingredient(ECompressedBlocks.COMPRESSED_CRUSHED_END_STONE.getTag()))
.put(MOSS_BLOCK, ingredient(ECompressedBlocks.COMPRESSED_MOSS_BLOCK.getTag()))
.build();
static void sieveRecipes(RecipeOutput writer) {
var allMeshes = List.of(EItems.STRING_MESH, EItems.FLINT_MESH, EItems.IRON_MESH, EItems.GOLDEN_MESH, EItems.DIAMOND_MESH, EItems.NETHERITE_MESH);
// Dirt -> String mesh
forMesh(writer, ingredient(Items.DIRT), EItems.STRING_MESH, drops -> {
forMesh(writer, DIRT, EItems.STRING_MESH, drops -> {
drops.add(EItems.STONE_PEBBLE.get(), binomial(7, 0.6f));
drops.add(Items.FLINT, chance(0.25f));
drops.add(Items.WHEAT_SEEDS, chance(0.125f));
@ -64,7 +96,7 @@ class SieveRecipes {
// Flint mesh will be used to get a larger variety of outputs from dirt, just so people don't always
// have the inventory spam that are the -ite pebbles.
// Dirt -> Flint mesh
forMesh(writer, ingredient(Items.DIRT), EItems.FLINT_MESH, drops -> {
forMesh(writer, DIRT, EItems.FLINT_MESH, drops -> {
drops.add(EItems.STONE_PEBBLE.get(), binomial(7, 0.6f));
drops.add(Items.FLINT, chance(0.3f));
drops.add(EItems.ANDESITE_PEBBLE.get(), binomial(7, 0.4f));
@ -85,7 +117,7 @@ class SieveRecipes {
drops.addConditional(ModCompatData.SOURCEBERRY.get(), chance(0.03f), Recipes.modInstalled(ModIds.ARS_NOUVEAU));
});
// Dirt -> Iron mesh
forMesh(writer, ingredient(Items.DIRT), EItems.IRON_MESH, drops -> {
forMesh(writer, DIRT, EItems.IRON_MESH, drops -> {
drops.add(EItems.STONE_PEBBLE.get(), binomial(8, 0.65f));
drops.add(EItems.DEEPSLATE_PEBBLE.get(), binomial(3, 0.45f));
drops.add(Items.FLINT, chance(0.3f));
@ -102,7 +134,7 @@ class SieveRecipes {
});
// Gold tends to spread its luster to whatever passes through it...
// Dirt -> Gold mesh
forMesh(writer, ingredient(Items.DIRT), EItems.GOLDEN_MESH, drops -> {
forMesh(writer, DIRT, EItems.GOLDEN_MESH, drops -> {
drops.add(EItems.STONE_PEBBLE.get(), binomial(8, 0.7f));
drops.add(EItems.DEEPSLATE_PEBBLE.get(), binomial(3, 0.55f));
drops.add(Items.FLINT, chance(0.2f));
@ -120,7 +152,7 @@ class SieveRecipes {
});
// Diamond tables have less junk items in them. Maybe you want those items? Use other meshes!
// Dirt -> Diamond mesh
forMesh(writer, ingredient(Items.DIRT), EItems.DIAMOND_MESH, drops -> {
forMesh(writer, DIRT, EItems.DIAMOND_MESH, drops -> {
drops.add(EItems.STONE_PEBBLE.get(), binomial(8, 0.7f));
drops.add(EItems.DEEPSLATE_PEBBLE.get(), binomial(3, 0.60f));
drops.add(Items.FLINT, binomial(3, 0.3f));
@ -132,7 +164,7 @@ class SieveRecipes {
});
// Netherite should be the best for all drops (except pebbles)
// Dirt -> Netherite mesh
forMesh(writer, ingredient(Items.DIRT), EItems.NETHERITE_MESH, drops -> {
forMesh(writer, DIRT, EItems.NETHERITE_MESH, drops -> {
drops.add(EItems.STONE_PEBBLE.get(), binomial(5, 0.4f));
drops.add(EItems.DEEPSLATE_PEBBLE.get(), binomial(4, 0.65f));
drops.add(Items.FLINT, binomial(3, 0.4f));
@ -146,7 +178,7 @@ class SieveRecipes {
});
// Gravel -> String mesh
forMesh(writer, ingredient(Items.GRAVEL), EItems.STRING_MESH, drops -> {
forMesh(writer, GRAVEL, EItems.STRING_MESH, drops -> {
drops.add(EItems.STONE_PEBBLE.get(), binomial(4, 0.4f));
drops.add(Items.FLINT, chance(0.2f));
drops.add(Items.COAL, chance(0.1f));
@ -171,7 +203,7 @@ class SieveRecipes {
drops.addConditional(EItems.BORON_ORE_CHUNK.get(), chance(0.03f), Recipes.tagNotEmpty(EItemTags.ORES_BORON));
});
// Gravel -> Flint mesh
forMesh(writer, ingredient(Items.GRAVEL), EItems.FLINT_MESH, drops -> {
forMesh(writer, GRAVEL, EItems.FLINT_MESH, drops -> {
drops.add(EItems.STONE_PEBBLE.get(), binomial(4, 0.5f));
drops.add(EItems.ANDESITE_PEBBLE.get(), binomial(4, 0.4f));
drops.add(EItems.GRANITE_PEBBLE.get(), binomial(4, 0.4f));
@ -200,7 +232,7 @@ class SieveRecipes {
drops.addConditional(EItems.BORON_ORE_CHUNK.get(), chance(0.0325f), Recipes.tagNotEmpty(EItemTags.ORES_BORON));
});
// Gravel -> Iron mesh
forMesh(writer, ingredient(Items.GRAVEL), EItems.IRON_MESH, drops -> {
forMesh(writer, GRAVEL, EItems.IRON_MESH, drops -> {
drops.add(EItems.STONE_PEBBLE.get(), binomial(4, 0.5f));
drops.add(EItems.DEEPSLATE_PEBBLE.get(), binomial(3, 0.55f));
drops.add(Items.FLINT, chance(0.15f));
@ -227,7 +259,7 @@ class SieveRecipes {
});
// Golden mesh has much higher drops for gold and gems
// Gravel -> Golden mesh
forMesh(writer, ingredient(Items.GRAVEL), EItems.GOLDEN_MESH, drops -> {
forMesh(writer, GRAVEL, EItems.GOLDEN_MESH, drops -> {
drops.add(EItems.STONE_PEBBLE.get(), binomial(4, 0.5f));
drops.add(EItems.DEEPSLATE_PEBBLE.get(), binomial(3, 0.55f));
drops.add(Items.FLINT, chance(0.13f));
@ -255,7 +287,7 @@ class SieveRecipes {
drops.addConditional(EItems.BORON_ORE_CHUNK.get(), chance(0.04f), Recipes.tagNotEmpty(EItemTags.ORES_BORON));
});
// Gravel -> Diamond mesh
forMesh(writer, ingredient(Items.GRAVEL), EItems.DIAMOND_MESH, drops -> {
forMesh(writer, GRAVEL, EItems.DIAMOND_MESH, drops -> {
drops.add(EItems.DEEPSLATE_PEBBLE.get(), binomial(5, 0.6f));
drops.add(Items.FLINT, chance(0.05f));
drops.add(Items.COAL, chance(0.06f));
@ -280,7 +312,7 @@ class SieveRecipes {
drops.addConditional(EItems.BORON_ORE_CHUNK.get(), chance(0.06f), Recipes.tagNotEmpty(EItemTags.ORES_BORON));
});
// Gravel -> Netherite mesh
forMesh(writer, ingredient(Items.GRAVEL), EItems.NETHERITE_MESH, drops -> {
forMesh(writer, GRAVEL, EItems.NETHERITE_MESH, drops -> {
drops.add(EItems.DEEPSLATE_PEBBLE.get(), binomial(6, 0.625f));
drops.add(Items.COAL, chance(0.06f));
drops.add(Items.LAPIS_LAZULI, chance(0.11f));
@ -307,7 +339,7 @@ class SieveRecipes {
});
// Sand -> String mesh
forMesh(writer, ingredient(Items.SAND), EItems.STRING_MESH, drops -> {
forMesh(writer, SAND, EItems.STRING_MESH, drops -> {
drops.add(Items.CACTUS, chance(0.13f));
drops.add(Items.FLINT, chance(0.2f));
drops.add(Items.DEAD_BUSH, chance(0.08f));
@ -319,7 +351,7 @@ class SieveRecipes {
drops.addConditional(ModCompatData.CERTUS_QUARTZ_CRYSTAL.get(), chance(0.03f), Recipes.modInstalled(ModIds.APPLIED_ENERGISTICS_2));
drops.addConditional(ModCompatData.CHARGED_CERTUS_QUARTZ_CRYSTAL.get(), chance(0.005f), Recipes.modInstalled(ModIds.APPLIED_ENERGISTICS_2));
});
forMesh(writer, ingredient(Items.SAND), EItems.FLINT_MESH, drops -> {
forMesh(writer, SAND, EItems.FLINT_MESH, drops -> {
drops.add(Items.FLINT, binomial(2, 0.2f));
drops.add(Items.DEAD_BUSH, chance(0.03f));
drops.add(Items.GOLD_NUGGET, chance(0.16f));
@ -329,7 +361,7 @@ class SieveRecipes {
drops.addConditional(ModCompatData.CERTUS_QUARTZ_CRYSTAL.get(), chance(0.04f), Recipes.modInstalled(ModIds.APPLIED_ENERGISTICS_2));
drops.addConditional(ModCompatData.CHARGED_CERTUS_QUARTZ_CRYSTAL.get(), chance(0.005f), Recipes.modInstalled(ModIds.APPLIED_ENERGISTICS_2));
});
forMesh(writer, ingredient(Items.SAND), EItems.IRON_MESH, drops -> {
forMesh(writer, SAND, EItems.IRON_MESH, drops -> {
drops.add(Items.CACTUS, chance(0.13f));
drops.add(Items.FLINT, chance(0.23f));
drops.add(Items.DEAD_BUSH, chance(0.08f));
@ -343,7 +375,7 @@ class SieveRecipes {
drops.addConditional(ModCompatData.CERTUS_QUARTZ_CRYSTAL.get(), chance(0.06f), Recipes.modInstalled(ModIds.APPLIED_ENERGISTICS_2));
drops.addConditional(ModCompatData.CHARGED_CERTUS_QUARTZ_CRYSTAL.get(), chance(0.0125f), Recipes.modInstalled(ModIds.APPLIED_ENERGISTICS_2));
});
forMesh(writer, ingredient(Items.SAND), EItems.GOLDEN_MESH, drops -> {
forMesh(writer, SAND, EItems.GOLDEN_MESH, drops -> {
drops.add(Items.CACTUS, chance(0.10f));
drops.add(Items.FLINT, chance(0.18f));
drops.add(Items.DEAD_BUSH, chance(0.06f));
@ -359,7 +391,7 @@ class SieveRecipes {
drops.addConditional(ModCompatData.CERTUS_QUARTZ_CRYSTAL.get(), chance(0.07f), Recipes.modInstalled(ModIds.APPLIED_ENERGISTICS_2));
drops.addConditional(ModCompatData.CHARGED_CERTUS_QUARTZ_CRYSTAL.get(), chance(0.015f), Recipes.modInstalled(ModIds.APPLIED_ENERGISTICS_2));
});
forMesh(writer, ingredient(Items.SAND), EItems.DIAMOND_MESH, drops -> {
forMesh(writer, SAND, EItems.DIAMOND_MESH, drops -> {
drops.add(Items.FLINT, chance(0.23f));
drops.add(Items.GOLD_NUGGET, chance(0.22f));
drops.add(Items.IRON_NUGGET, chance(0.22f));
@ -369,7 +401,7 @@ class SieveRecipes {
drops.addConditional(ModCompatData.CERTUS_QUARTZ_CRYSTAL.get(), chance(0.09f), Recipes.modInstalled(ModIds.APPLIED_ENERGISTICS_2));
drops.addConditional(ModCompatData.CHARGED_CERTUS_QUARTZ_CRYSTAL.get(), chance(0.02f), Recipes.modInstalled(ModIds.APPLIED_ENERGISTICS_2));
});
forMesh(writer, ingredient(Items.SAND), EItems.NETHERITE_MESH, drops -> {
forMesh(writer, SAND, EItems.NETHERITE_MESH, drops -> {
drops.add(Items.CACTUS, chance(0.15f));
drops.add(Items.FLINT, binomial(2, 0.23f));
drops.add(Items.GOLD_NUGGET, chance(0.23f));
@ -384,49 +416,49 @@ class SieveRecipes {
});
// Red Sand -> String mesh
forMesh(writer, ingredient(Items.RED_SAND), EItems.STRING_MESH, drops -> {
forMesh(writer, RED_SAND, EItems.STRING_MESH, drops -> {
drops.add(Items.CACTUS, chance(0.12f));
drops.add(Items.DEAD_BUSH, chance(0.07f));
drops.add(Items.GOLD_NUGGET, chance(0.09f));
drops.add(Items.REDSTONE, chance(0.08f));
drops.add(Items.RAW_GOLD, chance(0.03f));
});
forMesh(writer, ingredient(Items.RED_SAND), EItems.FLINT_MESH, drops -> {
forMesh(writer, RED_SAND, EItems.FLINT_MESH, drops -> {
drops.add(Items.CACTUS, chance(0.12f));
drops.add(Items.DEAD_BUSH, chance(0.07f));
drops.add(Items.GOLD_NUGGET, chance(0.12f));
drops.add(Items.REDSTONE, chance(0.09f));
drops.add(Items.RAW_GOLD, chance(0.04f));
});
forMesh(writer, ingredient(Items.RED_SAND), EItems.IRON_MESH, drops -> {
forMesh(writer, RED_SAND, EItems.IRON_MESH, drops -> {
drops.add(Items.CACTUS, chance(0.12f));
drops.add(Items.DEAD_BUSH, chance(0.07f));
drops.add(Items.GOLD_NUGGET, chance(0.09f));
drops.add(Items.REDSTONE, chance(0.11f));
drops.add(Items.RAW_GOLD, chance(0.06f));
});
forMesh(writer, ingredient(Items.RED_SAND), EItems.GOLDEN_MESH, drops -> {
forMesh(writer, RED_SAND, EItems.GOLDEN_MESH, drops -> {
drops.add(Items.CACTUS, chance(0.12f));
drops.add(Items.DEAD_BUSH, chance(0.07f));
drops.add(Items.GOLD_NUGGET, chance(0.19f));
drops.add(Items.REDSTONE, chance(0.07f));
drops.add(Items.RAW_GOLD, chance(0.11f));
});
forMesh(writer, ingredient(Items.RED_SAND), EItems.DIAMOND_MESH, drops -> {
forMesh(writer, RED_SAND, EItems.DIAMOND_MESH, drops -> {
drops.add(Items.CACTUS, chance(0.10f));
drops.add(Items.DEAD_BUSH, chance(0.03f));
drops.add(Items.GOLD_NUGGET, chance(0.14f));
drops.add(Items.REDSTONE, chance(0.14f));
drops.add(Items.RAW_GOLD, chance(0.08f));
});
forMesh(writer, ingredient(Items.RED_SAND), EItems.NETHERITE_MESH, drops -> {
forMesh(writer, RED_SAND, EItems.NETHERITE_MESH, drops -> {
drops.add(Items.CACTUS, chance(0.12f));
drops.add(Items.GOLD_NUGGET, chance(0.15f));
drops.add(Items.REDSTONE, chance(0.17f));
drops.add(Items.RAW_GOLD, chance(0.10f));
});
forMesh(writer, ingredient(EItems.DUST.get()), EItems.STRING_MESH, drops -> {
forMesh(writer, DUST, EItems.STRING_MESH, drops -> {
drops.add(Items.GUNPOWDER, chance(0.1f));
drops.add(Items.BONE_MEAL, chance(0.1f));
drops.add(Items.REDSTONE, chance(0.06f));
@ -438,7 +470,7 @@ class SieveRecipes {
drops.addConditional(ModCompatData.SKY_STONE_DUST.get(), chance(0.06f), Recipes.AE2);
drops.addConditional(ModCompatData.CERTUS_QUARTZ_DUST.get(), chance(0.06f), Recipes.AE2);
});
forMesh(writer, ingredient(EItems.DUST.get()), EItems.FLINT_MESH, drops -> {
forMesh(writer, DUST, EItems.FLINT_MESH, drops -> {
drops.add(Items.GUNPOWDER, chance(0.11f));
drops.add(Items.BONE_MEAL, chance(0.11f));
drops.add(Items.REDSTONE, chance(0.09f));
@ -450,7 +482,7 @@ class SieveRecipes {
drops.addConditional(ModCompatData.SKY_STONE_DUST.get(), chance(0.07f), Recipes.AE2);
drops.addConditional(ModCompatData.CERTUS_QUARTZ_DUST.get(), chance(0.07f), Recipes.AE2);
});
forMesh(writer, ingredient(EItems.DUST.get()), EItems.IRON_MESH, drops -> {
forMesh(writer, DUST, EItems.IRON_MESH, drops -> {
drops.add(Items.GUNPOWDER, chance(0.13f));
drops.add(Items.BONE_MEAL, chance(0.12f));
drops.add(Items.REDSTONE, chance(0.1f));
@ -463,7 +495,7 @@ class SieveRecipes {
drops.addConditional(ModCompatData.SKY_STONE_DUST.get(), chance(0.075f), Recipes.AE2);
drops.addConditional(ModCompatData.CERTUS_QUARTZ_DUST.get(), chance(0.075f), Recipes.AE2);
});
forMesh(writer, ingredient(EItems.DUST.get()), EItems.GOLDEN_MESH, drops -> {
forMesh(writer, DUST, EItems.GOLDEN_MESH, drops -> {
drops.add(Items.GUNPOWDER, chance(0.13f));
drops.add(Items.BONE_MEAL, chance(0.11f));
drops.add(Items.REDSTONE, chance(0.12f));
@ -477,7 +509,7 @@ class SieveRecipes {
drops.addConditional(ModCompatData.SKY_STONE_DUST.get(), chance(0.08f), Recipes.AE2);
drops.addConditional(ModCompatData.CERTUS_QUARTZ_DUST.get(), chance(0.08f), Recipes.AE2);
});
forMesh(writer, ingredient(EItems.DUST.get()), EItems.DIAMOND_MESH, drops -> {
forMesh(writer, DUST, EItems.DIAMOND_MESH, drops -> {
drops.add(Items.GUNPOWDER, chance(0.14f));
drops.add(Items.BONE_MEAL, chance(0.10f));
drops.add(Items.REDSTONE, chance(0.12f));
@ -490,7 +522,7 @@ class SieveRecipes {
drops.addConditional(ModCompatData.SKY_STONE_DUST.get(), chance(0.10f), Recipes.AE2);
drops.addConditional(ModCompatData.CERTUS_QUARTZ_DUST.get(), chance(0.10f), Recipes.AE2);
});
forMesh(writer, ingredient(EItems.DUST.get()), EItems.NETHERITE_MESH, drops -> {
forMesh(writer, DUST, EItems.NETHERITE_MESH, drops -> {
drops.add(Items.GUNPOWDER, chance(0.14f));
drops.add(Items.BONE_MEAL, chance(0.13f));
drops.add(Items.REDSTONE, chance(0.14f));
@ -506,7 +538,7 @@ class SieveRecipes {
});
// Crushed Deepslate -> String mesh
forMesh(writer, ingredient(EItems.CRUSHED_DEEPSLATE.get()), EItems.STRING_MESH, drops -> {
forMesh(writer, CRUSHED_DEEPSLATE, EItems.STRING_MESH, drops -> {
drops.add(EItems.DEEPSLATE_PEBBLE.get(), binomial(4, 0.5f));
drops.add(EItems.COPPER_ORE_CHUNK.get(), chance(0.12f));
drops.add(EItems.IRON_ORE_CHUNK.get(), chance(0.12f));
@ -529,7 +561,7 @@ class SieveRecipes {
drops.addConditional(EItems.BORON_ORE_CHUNK.get(), chance(0.05f), Recipes.tagNotEmpty(EItemTags.ORES_BORON));
drops.addConditional(EItems.LITHIUM_ORE_CHUNK.get(), chance(0.045f), Recipes.tagNotEmpty(EItemTags.ORES_LITHIUM));
});
forMesh(writer, ingredient(EItems.CRUSHED_DEEPSLATE.get()), EItems.FLINT_MESH, drops -> {
forMesh(writer, CRUSHED_DEEPSLATE, EItems.FLINT_MESH, drops -> {
drops.add(EItems.DEEPSLATE_PEBBLE.get(), binomial(4, 0.5f));
drops.add(EItems.TUFF_PEBBLE.get(), binomial(4, 0.4f));
drops.add(EItems.CALCITE_PEBBLE.get(), binomial(4, 0.4f));
@ -555,7 +587,7 @@ class SieveRecipes {
drops.addConditional(EItems.BORON_ORE_CHUNK.get(), chance(0.06f), Recipes.tagNotEmpty(EItemTags.ORES_BORON));
drops.addConditional(EItems.LITHIUM_ORE_CHUNK.get(), chance(0.05f), Recipes.tagNotEmpty(EItemTags.ORES_LITHIUM));
});
forMesh(writer, ingredient(EItems.CRUSHED_DEEPSLATE.get()), EItems.IRON_MESH, drops -> {
forMesh(writer, CRUSHED_DEEPSLATE, EItems.IRON_MESH, drops -> {
drops.add(EItems.DEEPSLATE_PEBBLE.get(), binomial(4, 0.6f));
drops.add(EItems.COPPER_ORE_CHUNK.get(), chance(0.10f));
drops.add(EItems.IRON_ORE_CHUNK.get(), chance(0.15f));
@ -578,7 +610,7 @@ class SieveRecipes {
drops.addConditional(EItems.BORON_ORE_CHUNK.get(), chance(0.06f), Recipes.tagNotEmpty(EItemTags.ORES_BORON));
drops.addConditional(EItems.LITHIUM_ORE_CHUNK.get(), chance(0.06f), Recipes.tagNotEmpty(EItemTags.ORES_LITHIUM));
});
forMesh(writer, ingredient(EItems.CRUSHED_DEEPSLATE.get()), EItems.GOLDEN_MESH, drops -> {
forMesh(writer, CRUSHED_DEEPSLATE, EItems.GOLDEN_MESH, drops -> {
drops.add(EItems.DEEPSLATE_PEBBLE.get(), binomial(4, 0.65f));
drops.add(EItems.COPPER_ORE_CHUNK.get(), chance(0.09f));
drops.add(EItems.IRON_ORE_CHUNK.get(), chance(0.15f));
@ -603,7 +635,7 @@ class SieveRecipes {
drops.addConditional(EItems.BORON_ORE_CHUNK.get(), chance(0.065f), Recipes.tagNotEmpty(EItemTags.ORES_BORON));
drops.addConditional(EItems.LITHIUM_ORE_CHUNK.get(), chance(0.065f), Recipes.tagNotEmpty(EItemTags.ORES_LITHIUM));
});
forMesh(writer, ingredient(EItems.CRUSHED_DEEPSLATE.get()), EItems.DIAMOND_MESH, drops -> {
forMesh(writer, CRUSHED_DEEPSLATE, EItems.DIAMOND_MESH, drops -> {
drops.add(EItems.DEEPSLATE_PEBBLE.get(), binomial(4, 0.65f));
drops.add(EItems.COPPER_ORE_CHUNK.get(), chance(0.09f));
drops.add(EItems.IRON_ORE_CHUNK.get(), chance(0.18f));
@ -626,7 +658,7 @@ class SieveRecipes {
drops.addConditional(EItems.BORON_ORE_CHUNK.get(), chance(0.08f), Recipes.tagNotEmpty(EItemTags.ORES_BORON));
drops.addConditional(EItems.LITHIUM_ORE_CHUNK.get(), chance(0.08f), Recipes.tagNotEmpty(EItemTags.ORES_LITHIUM));
});
forMesh(writer, ingredient(EItems.CRUSHED_DEEPSLATE.get()), EItems.NETHERITE_MESH, drops -> {
forMesh(writer, CRUSHED_DEEPSLATE, EItems.NETHERITE_MESH, drops -> {
drops.add(EItems.DEEPSLATE_PEBBLE.get(), binomial(4, 0.7f));
drops.add(EItems.COPPER_ORE_CHUNK.get(), chance(0.10f));
drops.add(EItems.IRON_ORE_CHUNK.get(), chance(0.20f));
@ -650,7 +682,7 @@ class SieveRecipes {
drops.addConditional(EItems.LITHIUM_ORE_CHUNK.get(), chance(0.085f), Recipes.tagNotEmpty(EItemTags.ORES_LITHIUM));
});
forMesh(writer, ingredient(EItems.CRUSHED_BLACKSTONE.get()), EItems.STRING_MESH, drops -> {
forMesh(writer, CRUSHED_BLACKSTONE, EItems.STRING_MESH, drops -> {
drops.add(EItems.BLACKSTONE_PEBBLE.get(), binomial(4, 0.6f));
drops.add(EItems.BASALT_PEBBLE.get(), binomial(3, 0.5f));
drops.add(Items.ANCIENT_DEBRIS, chance(0.02f));
@ -659,7 +691,7 @@ class SieveRecipes {
drops.add(Items.GUNPOWDER, chance(0.07f));
drops.add(Items.BLACK_DYE, chance(0.07f));
});
forMesh(writer, ingredient(EItems.CRUSHED_BLACKSTONE.get()), EItems.FLINT_MESH, drops -> {
forMesh(writer, CRUSHED_BLACKSTONE, EItems.FLINT_MESH, drops -> {
drops.add(EItems.BLACKSTONE_PEBBLE.get(), binomial(4, 0.65f));
drops.add(EItems.BASALT_PEBBLE.get(), binomial(3, 0.55f));
drops.add(Items.ANCIENT_DEBRIS, chance(0.03f));
@ -668,7 +700,7 @@ class SieveRecipes {
drops.add(Items.GUNPOWDER, chance(0.09f));
drops.add(Items.BLACK_DYE, chance(0.08f));
});
forMesh(writer, ingredient(EItems.CRUSHED_BLACKSTONE.get()), EItems.IRON_MESH, drops -> {
forMesh(writer, CRUSHED_BLACKSTONE, EItems.IRON_MESH, drops -> {
drops.add(EItems.BLACKSTONE_PEBBLE.get(), binomial(5, 0.65f));
drops.add(EItems.BASALT_PEBBLE.get(), binomial(4, 0.55f));
drops.add(Items.ANCIENT_DEBRIS, chance(0.04f));
@ -677,7 +709,7 @@ class SieveRecipes {
drops.add(Items.GUNPOWDER, chance(0.09f));
drops.add(Items.BLACK_DYE, chance(0.08f));
});
forMesh(writer, ingredient(EItems.CRUSHED_BLACKSTONE.get()), EItems.GOLDEN_MESH, drops -> {
forMesh(writer, CRUSHED_BLACKSTONE, EItems.GOLDEN_MESH, drops -> {
drops.add(EItems.BLACKSTONE_PEBBLE.get(), binomial(5, 0.7f));
drops.add(EItems.BASALT_PEBBLE.get(), binomial(4, 0.5f));
drops.add(Items.ANCIENT_DEBRIS, chance(0.05f));
@ -686,14 +718,14 @@ class SieveRecipes {
drops.add(Items.GUNPOWDER, chance(0.1f));
drops.add(Items.BLACK_DYE, chance(0.06f));
});
forMesh(writer, ingredient(EItems.CRUSHED_BLACKSTONE.get()), EItems.DIAMOND_MESH, drops -> {
forMesh(writer, CRUSHED_BLACKSTONE, EItems.DIAMOND_MESH, drops -> {
drops.add(EItems.BLACKSTONE_PEBBLE.get(), binomial(5, 0.7f));
drops.add(Items.ANCIENT_DEBRIS, chance(0.06f));
drops.add(Items.GOLD_NUGGET, binomial(4, 0.275f));
drops.add(Items.MAGMA_CREAM, chance(0.11f));
drops.add(Items.GUNPOWDER, chance(0.11f));
});
forMesh(writer, ingredient(EItems.CRUSHED_BLACKSTONE.get()), EItems.NETHERITE_MESH, drops -> {
forMesh(writer, CRUSHED_BLACKSTONE, EItems.NETHERITE_MESH, drops -> {
drops.add(EItems.BLACKSTONE_PEBBLE.get(), binomial(5, 0.75f));
drops.add(Items.ANCIENT_DEBRIS, chance(0.1f));
drops.add(Items.GOLD_NUGGET, binomial(4, 0.325f));
@ -701,7 +733,7 @@ class SieveRecipes {
drops.add(Items.GUNPOWDER, chance(0.11f));
});
forMesh(writer, ingredient(EItems.CRUSHED_NETHERRACK.get()), EItems.STRING_MESH, drops -> {
forMesh(writer, CRUSHED_NETHERRACK, EItems.STRING_MESH, drops -> {
drops.add(EItems.BLACKSTONE_PEBBLE.get(), binomial(3, 0.4f));
drops.add(EItems.BASALT_PEBBLE.get(), binomial(3, 0.3f));
drops.add(Items.BLAZE_POWDER, chance(0.08f));
@ -714,7 +746,7 @@ class SieveRecipes {
drops.addConditional(EItems.COBALT_ORE_CHUNK.get(), chance(0.04f), Recipes.tagNotEmpty(EItemTags.ORES_COBALT));
});
forMesh(writer, ingredient(EItems.CRUSHED_NETHERRACK.get()), EItems.FLINT_MESH, drops -> {
forMesh(writer, CRUSHED_NETHERRACK, EItems.FLINT_MESH, drops -> {
drops.add(EItems.BLACKSTONE_PEBBLE.get(), binomial(4, 0.5f));
drops.add(EItems.BASALT_PEBBLE.get(), binomial(4, 0.4f));
drops.add(Items.BLAZE_POWDER, chance(0.09f));
@ -727,7 +759,7 @@ class SieveRecipes {
drops.addConditional(EItems.COBALT_ORE_CHUNK.get(), chance(0.05f), Recipes.tagNotEmpty(EItemTags.ORES_COBALT));
});
forMesh(writer, ingredient(EItems.CRUSHED_NETHERRACK.get()), EItems.IRON_MESH, drops -> {
forMesh(writer, CRUSHED_NETHERRACK, EItems.IRON_MESH, drops -> {
drops.add(EItems.BLACKSTONE_PEBBLE.get(), binomial(4, 0.6f));
drops.add(EItems.BASALT_PEBBLE.get(), binomial(4, 0.45f));
drops.add(Items.BLAZE_POWDER, chance(0.1f));
@ -740,7 +772,7 @@ class SieveRecipes {
drops.addConditional(EItems.COBALT_ORE_CHUNK.get(), chance(0.065f), Recipes.tagNotEmpty(EItemTags.ORES_COBALT));
});
forMesh(writer, ingredient(EItems.CRUSHED_NETHERRACK.get()), EItems.GOLDEN_MESH, drops -> {
forMesh(writer, CRUSHED_NETHERRACK, EItems.GOLDEN_MESH, drops -> {
drops.add(EItems.BLACKSTONE_PEBBLE.get(), binomial(4, 0.6f));
drops.add(EItems.BASALT_PEBBLE.get(), binomial(4, 0.45f));
drops.add(Items.BLAZE_POWDER, chance(0.11f));
@ -754,7 +786,7 @@ class SieveRecipes {
drops.addConditional(EItems.COBALT_ORE_CHUNK.get(), chance(0.07f), Recipes.tagNotEmpty(EItemTags.ORES_COBALT));
});
forMesh(writer, ingredient(EItems.CRUSHED_NETHERRACK.get()), EItems.DIAMOND_MESH, drops -> {
forMesh(writer, CRUSHED_NETHERRACK, EItems.DIAMOND_MESH, drops -> {
drops.add(EItems.BLACKSTONE_PEBBLE.get(), binomial(4, 0.6f));
drops.add(Items.BLAZE_POWDER, chance(0.14f));
drops.add(Items.QUARTZ, chance(0.13f));
@ -764,7 +796,7 @@ class SieveRecipes {
drops.addConditional(EItems.COBALT_ORE_CHUNK.get(), chance(0.09f), Recipes.tagNotEmpty(EItemTags.ORES_COBALT));
});
forMesh(writer, ingredient(EItems.CRUSHED_NETHERRACK.get()), EItems.NETHERITE_MESH, drops -> {
forMesh(writer, CRUSHED_NETHERRACK, EItems.NETHERITE_MESH, drops -> {
drops.add(EItems.BLACKSTONE_PEBBLE.get(), binomial(5, 0.65f));
drops.add(Items.BLAZE_POWDER, chance(0.15f));
drops.add(Items.QUARTZ, chance(0.15f));
@ -775,7 +807,7 @@ class SieveRecipes {
drops.addConditional(EItems.COBALT_ORE_CHUNK.get(), chance(0.11f), Recipes.tagNotEmpty(EItemTags.ORES_COBALT));
});
forMesh(writer, ingredient(Items.SOUL_SAND), EItems.STRING_MESH, drops -> {
forMesh(writer, SOUL_SAND, EItems.STRING_MESH, drops -> {
drops.add(Items.QUARTZ, chance(0.12f));
drops.add(Items.GUNPOWDER, chance(0.07f));
drops.add(Items.BONE, chance(0.08f));
@ -783,7 +815,7 @@ class SieveRecipes {
drops.add(Items.NETHER_WART, chance(0.06f));
drops.add(Items.GLOWSTONE_DUST, chance(0.06f));
});
forMesh(writer, ingredient(Items.SOUL_SAND), EItems.FLINT_MESH, drops -> {
forMesh(writer, SOUL_SAND, EItems.FLINT_MESH, drops -> {
drops.add(Items.QUARTZ, chance(0.14f));
drops.add(Items.GUNPOWDER, chance(0.08f));
drops.add(Items.BONE, chance(0.1f));
@ -793,7 +825,7 @@ class SieveRecipes {
drops.add(EItems.WARPED_NYLIUM_SPORES.get(), chance(0.03f));
drops.add(EItems.CRIMSON_NYLIUM_SPORES.get(), chance(0.03f));
});
forMesh(writer, ingredient(Items.SOUL_SAND), EItems.IRON_MESH, drops -> {
forMesh(writer, SOUL_SAND, EItems.IRON_MESH, drops -> {
drops.add(Items.QUARTZ, chance(0.15f));
drops.add(Items.GUNPOWDER, chance(0.07f));
drops.add(Items.BONE, chance(0.08f));
@ -801,7 +833,7 @@ class SieveRecipes {
drops.add(Items.GLOWSTONE_DUST, chance(0.06f));
drops.add(Items.NETHER_WART, chance(0.05f));
});
forMesh(writer, ingredient(Items.SOUL_SAND), EItems.GOLDEN_MESH, drops -> {
forMesh(writer, SOUL_SAND, EItems.GOLDEN_MESH, drops -> {
drops.add(Items.QUARTZ, chance(0.17f));
drops.add(Items.GUNPOWDER, chance(0.1f));
drops.add(Items.BONE, chance(0.11f));
@ -810,14 +842,14 @@ class SieveRecipes {
drops.add(Items.NETHER_WART, chance(0.08f));
drops.add(Items.GOLD_NUGGET, chance(0.15f));
});
forMesh(writer, ingredient(Items.SOUL_SAND), EItems.DIAMOND_MESH, drops -> {
forMesh(writer, SOUL_SAND, EItems.DIAMOND_MESH, drops -> {
drops.add(Items.QUARTZ, chance(0.19f));
drops.add(Items.GUNPOWDER, chance(0.11f));
drops.add(Items.GHAST_TEAR, chance(0.09f));
drops.add(Items.GLOWSTONE_DUST, chance(0.11f));
drops.add(Items.NETHER_WART, chance(0.1f));
});
forMesh(writer, ingredient(Items.SOUL_SAND), EItems.NETHERITE_MESH, drops -> {
forMesh(writer, SOUL_SAND, EItems.NETHERITE_MESH, drops -> {
drops.add(Items.QUARTZ, chance(0.21f));
drops.add(Items.GUNPOWDER, chance(0.14f));
drops.add(Items.GHAST_TEAR, chance(0.11f));
@ -825,37 +857,37 @@ class SieveRecipes {
drops.add(Items.NETHER_WART, chance(0.12f));
});
forMesh(writer, ingredient(EItems.CRUSHED_END_STONE), EItems.STRING_MESH, drops -> {
forMesh(writer, CRUSHED_END_STONE, EItems.STRING_MESH, drops -> {
drops.add(Items.ENDER_PEARL, chance(0.07f));
drops.add(Items.CHORUS_FRUIT, chance(0.09f));
drops.add(Items.CHORUS_FLOWER, chance(0.04f));
drops.add(Items.ENDER_EYE, chance(0.02f));
});
forMesh(writer, ingredient(EItems.CRUSHED_END_STONE), EItems.FLINT_MESH, drops -> {
forMesh(writer, CRUSHED_END_STONE, EItems.FLINT_MESH, drops -> {
drops.add(Items.ENDER_PEARL, chance(0.08f));
drops.add(Items.CHORUS_FRUIT, chance(0.11f));
drops.add(Items.CHORUS_FLOWER, chance(0.06f));
drops.add(Items.ENDER_EYE, chance(0.03f));
});
forMesh(writer, ingredient(EItems.CRUSHED_END_STONE), EItems.IRON_MESH, drops -> {
forMesh(writer, CRUSHED_END_STONE, EItems.IRON_MESH, drops -> {
drops.add(Items.ENDER_PEARL, chance(0.10f));
drops.add(Items.CHORUS_FRUIT, chance(0.13f));
drops.add(Items.CHORUS_FLOWER, chance(0.07f));
drops.add(Items.ENDER_EYE, chance(0.04f));
});
forMesh(writer, ingredient(EItems.CRUSHED_END_STONE), EItems.GOLDEN_MESH, drops -> {
forMesh(writer, CRUSHED_END_STONE, EItems.GOLDEN_MESH, drops -> {
drops.add(Items.ENDER_PEARL, chance(0.12f));
drops.add(Items.CHORUS_FRUIT, chance(0.12f));
drops.add(Items.CHORUS_FLOWER, chance(0.06f));
drops.add(Items.ENDER_EYE, chance(0.07f));
});
forMesh(writer, ingredient(EItems.CRUSHED_END_STONE), EItems.DIAMOND_MESH, drops -> {
forMesh(writer, CRUSHED_END_STONE, EItems.DIAMOND_MESH, drops -> {
drops.add(Items.ENDER_PEARL, chance(0.15f));
drops.add(Items.CHORUS_FRUIT, chance(0.10f));
drops.add(Items.CHORUS_FLOWER, chance(0.04f));
drops.add(Items.ENDER_EYE, chance(0.09f));
});
forMesh(writer, ingredient(EItems.CRUSHED_END_STONE), EItems.NETHERITE_MESH, drops -> {
forMesh(writer, CRUSHED_END_STONE, EItems.NETHERITE_MESH, drops -> {
drops.add(Items.ENDER_PEARL, chance(0.17f));
drops.add(Items.CHORUS_FRUIT, chance(0.10f));
drops.add(Items.CHORUS_FLOWER, chance(0.04f));
@ -867,7 +899,7 @@ class SieveRecipes {
for (int i = 0; i < allMeshes.size(); i++) {
var mesh = allMeshes.get(i);
final int j = i;
forMesh(writer, ingredient(Items.MOSS_BLOCK), mesh, drops -> {
forMesh(writer, MOSS_BLOCK, mesh, drops -> {
drops.add(Items.OAK_SAPLING, chance(0.13f));
drops.add(Items.SPRUCE_SAPLING, chance(0.11f));
drops.add(Items.BIRCH_SAPLING, chance(0.11f));
@ -911,7 +943,7 @@ class SieveRecipes {
drops.addConditional(ModCompatData.SOURCEBERRY.get(), chance(0.01f), ars);
});
}
forMesh(writer, ingredient(Items.MOSS_BLOCK), EItems.FLINT_MESH, drops -> {
forMesh(writer, MOSS_BLOCK, EItems.FLINT_MESH, drops -> {
drops.add(Items.SWEET_BERRIES, chance(0.03f));
drops.add(Items.FLOWERING_AZALEA, chance(0.03f));
drops.add(Items.GLOW_LICHEN, chance(0.04f));
@ -923,20 +955,35 @@ class SieveRecipes {
return binomial(1, p);
}
private static void forMesh(RecipeOutput output, Ingredient block, DeferredItem<?> mesh, Consumer<MeshDrops> addDrops) {
private static void forMesh(RecipeOutput output, Ingredient block, DeferredItem<? extends Item> mesh, Consumer<MeshDrops> addDrops) {
var folder = mesh.getId().getPath().replace("_mesh", "/");
var basePath = path(block.getItems()[0].getItem()) + "/" + folder;
addDrops.accept(new MeshDrops(output, "sieve/" + basePath, block, mesh));
addDrops.accept(new MeshDrops(output, "sieve/" + basePath, "compressed_sieve/" + basePath, block, mesh.get()));
}
private record MeshDrops(RecipeOutput output, String basePath, Ingredient block, ItemLike mesh) {
private void add(ItemLike result, NumberProvider resultAmount) {
this.output.accept(new ResourceLocation(ExDeorum.ID, this.basePath + path(result)), new SieveRecipe(this.block, result.asItem(), resultAmount, this.mesh.asItem(), false), null);
private record MeshDrops(RecipeOutput output, String basePath, String baseCompressedPath, Ingredient block, Item mesh) {
private void add(Item result, NumberProvider resultAmount) {
this.output.accept(modLoc(this.basePath + path(result)), new SieveRecipe(this.block, result, resultAmount, this.mesh, false), null);
if (COMPRESSED_VARIANTS.containsKey(this.block)) {
var compressedLoc = modLoc(this.baseCompressedPath + path(result));
var multiplied = Recipes.compressedMultiplier(resultAmount);
this.output.accept(compressedLoc, new CompressedSieveRecipe(COMPRESSED_VARIANTS.get(this.block), result, multiplied, this.mesh, false), null);
}
}
private void addConditional(ItemLike result, NumberProvider resultAmount, ICondition condition) {
this.output.accept(new ResourceLocation(ExDeorum.ID, this.basePath + path(result)), new SieveRecipe(this.block, result.asItem(), resultAmount, this.mesh.asItem(), false), null, condition);
var path = modLoc(this.basePath + path(result));
this.output.accept(path, new SieveRecipe(this.block, result.asItem(), resultAmount, this.mesh.asItem(), false), null, condition);
if (COMPRESSED_VARIANTS.containsKey(this.block)) {
var compressedLoc = modLoc(this.baseCompressedPath + path(result));
var multiplied = Recipes.compressedMultiplier(resultAmount);
this.output.accept(compressedLoc, new CompressedSieveRecipe(COMPRESSED_VARIANTS.get(this.block), result.asItem(), multiplied, this.mesh.asItem(), false), null, condition);
}
}
}
}

View File

@ -0,0 +1,34 @@
package thedarkcolour.exdeorum.item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Tier;
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.level.block.Block;
import net.neoforged.neoforge.common.util.Lazy;
import org.jetbrains.annotations.Nullable;
import thedarkcolour.exdeorum.recipe.RecipeUtil;
import thedarkcolour.exdeorum.registry.EItems;
import java.util.Set;
public class CompressedHammerItem extends HammerItem {
private static Lazy<Set<Block>> validBlocks = Lazy.of(() -> HammerItem.computeValidBlocks(RecipeUtil.getCachedCompressedHammerRecipes()));
public static void refreshValidBlocks() {
validBlocks = Lazy.of(() -> HammerItem.computeValidBlocks(RecipeUtil.getCachedCompressedHammerRecipes()));
}
public CompressedHammerItem(Tier tier, Properties properties) {
super(tier, properties);
}
@Override
protected Set<Block> getValidBlocks() {
return validBlocks.get();
}
@Override
public int getBurnTime(ItemStack stack, @Nullable RecipeType<?> recipeType) {
return this == EItems.COMPRESSED_WOODEN_HAMMER.get() ? 200 : 0;
}
}

View File

@ -19,7 +19,6 @@
package thedarkcolour.exdeorum.item;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import net.minecraft.client.Minecraft;
import net.minecraft.tags.BlockTags;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.DiggerItem;
@ -29,35 +28,24 @@ import net.minecraft.world.item.crafting.RecipeHolder;
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.fml.loading.FMLEnvironment;
import net.neoforged.neoforge.common.TierSortingRegistry;
import net.neoforged.neoforge.common.util.Lazy;
import net.neoforged.neoforge.server.ServerLifecycleHooks;
import org.jetbrains.annotations.Nullable;
import thedarkcolour.exdeorum.recipe.RecipeUtil;
import thedarkcolour.exdeorum.recipe.hammer.HammerRecipe;
import thedarkcolour.exdeorum.registry.EItems;
import thedarkcolour.exdeorum.registry.ERecipeTypes;
import java.util.Collection;
import java.util.Objects;
import java.util.Set;
public class HammerItem extends DiggerItem {
public static Lazy<Set<Block>> validBlocks = Lazy.of(HammerItem::computeValidBlocks);
private static Lazy<Set<Block>> validBlocks = Lazy.of(() -> computeValidBlocks(RecipeUtil.getCachedHammerRecipes()));
public HammerItem(Tier tier, Properties properties) {
super(1.0f, -2.8f, tier, null, properties);
}
public static Set<Block> computeValidBlocks() {
Collection<RecipeHolder<HammerRecipe>> hammerRecipes;
// todo test that this works properly
if (FMLEnvironment.dist == Dist.CLIENT) {
hammerRecipes = Objects.requireNonNull(Minecraft.getInstance().level).getRecipeManager().byType(ERecipeTypes.HAMMER.get()).values();
} else {
hammerRecipes = ServerLifecycleHooks.getCurrentServer().getRecipeManager().byType(ERecipeTypes.HAMMER.get()).values();
}
protected static Set<Block> computeValidBlocks(Collection<? extends RecipeHolder<? extends HammerRecipe>> hammerRecipes) {
var validBlocks = new ObjectOpenHashSet<Block>(hammerRecipes.size());
for (var recipe : hammerRecipes) {
@ -72,7 +60,7 @@ public class HammerItem extends DiggerItem {
}
public static void refreshValidBlocks() {
validBlocks = Lazy.of(HammerItem::computeValidBlocks);
validBlocks = Lazy.of(() -> computeValidBlocks(RecipeUtil.getCachedHammerRecipes()));
}
protected Set<Block> getValidBlocks() {

View File

@ -0,0 +1,29 @@
package thedarkcolour.exdeorum.loot;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition;
import net.neoforged.neoforge.common.loot.IGlobalLootModifier;
import net.neoforged.neoforge.common.loot.LootModifier;
import org.jetbrains.annotations.Nullable;
import thedarkcolour.exdeorum.recipe.RecipeUtil;
import thedarkcolour.exdeorum.recipe.hammer.HammerRecipe;
public class CompressedHammerLootModifier extends HammerLootModifier {
public static final Codec<CompressedHammerLootModifier> CODEC = RecordCodecBuilder.create(inst -> LootModifier.codecStart(inst).apply(inst, CompressedHammerLootModifier::new));
public CompressedHammerLootModifier(LootItemCondition[] conditionsIn) {
super(conditionsIn);
}
@Override
public Codec<? extends IGlobalLootModifier> codec() {
return CODEC;
}
@Override
protected @Nullable HammerRecipe getRecipe(Item itemForm) {
return RecipeUtil.getCompressedHammerRecipe(itemForm);
}
}

View File

@ -22,6 +22,7 @@ import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.minecraft.util.RandomSource;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.enchantment.Enchantments;
@ -30,7 +31,9 @@ import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition;
import net.neoforged.neoforge.common.loot.IGlobalLootModifier;
import net.neoforged.neoforge.common.loot.LootModifier;
import org.jetbrains.annotations.Nullable;
import thedarkcolour.exdeorum.recipe.RecipeUtil;
import thedarkcolour.exdeorum.recipe.hammer.HammerRecipe;
import javax.annotation.Nonnull;
@ -49,7 +52,7 @@ public class HammerLootModifier extends LootModifier {
if (state != null) {
var itemForm = state.getBlock().asItem();
if (itemForm != Items.AIR) {
var recipe = RecipeUtil.getHammerRecipe(itemForm);
var recipe = getRecipe(itemForm);
if (recipe != null) {
ObjectArrayList<ItemStack> newLoot = new ObjectArrayList<>();
@ -72,6 +75,11 @@ public class HammerLootModifier extends LootModifier {
return generatedLoot;
}
@Nullable
protected HammerRecipe getRecipe(Item itemForm) {
return RecipeUtil.getHammerRecipe(itemForm);
}
@Override
public Codec<? extends IGlobalLootModifier> codec() {
return CODEC;

View File

@ -0,0 +1,34 @@
/*
* 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.material;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.SoundType;
import thedarkcolour.exdeorum.block.CompressedSieveBlock;
public class CompressedSieveMaterial extends SieveMaterial {
protected CompressedSieveMaterial(SoundType soundType, float strength, boolean needsCorrectTool, String requiredModId) {
super(soundType, strength, needsCorrectTool, requiredModId);
}
@Override
protected Block createBlock() {
return new CompressedSieveBlock(props().noOcclusion());
}
}

View File

@ -27,6 +27,7 @@ import thedarkcolour.exdeorum.compat.ModIds;
public class DefaultMaterials {
public static final MaterialRegistry<BarrelMaterial> BARRELS = new MaterialRegistry<>("barrel");
public static final MaterialRegistry<SieveMaterial> SIEVES = new MaterialRegistry<>("sieve");
public static final MaterialRegistry<CompressedSieveMaterial> COMPRESSED_SIEVES = new MaterialRegistry<>("compressed_sieve");
public static final MaterialRegistry<AbstractCrucibleMaterial> LAVA_CRUCIBLES = new MaterialRegistry<>("lava_crucible", "crucible");
public static final MaterialRegistry<AbstractCrucibleMaterial> WATER_CRUCIBLES = new MaterialRegistry<>("water_crucible", "crucible");
@ -105,6 +106,47 @@ public class DefaultMaterials {
public static final SieveMaterial MAPLE_SIEVE = addDefaultSieve("maple", SoundType.WOOD, ModIds.BLUE_SKIES);
public static final SieveMaterial CRYSTALLIZED_SIEVE = addDefaultSieve("crystallized", SoundType.GLASS, true, ModIds.BLUE_SKIES);
// Ex Deorum
public static final CompressedSieveMaterial OAK_COMPRESSED_SIEVE = addDefaultCompressedSieve("oak", SoundType.WOOD, ExDeorum.ID);
public static final CompressedSieveMaterial SPRUCE_COMPRESSED_SIEVE = addDefaultCompressedSieve("spruce", SoundType.WOOD, ExDeorum.ID);
public static final CompressedSieveMaterial BIRCH_COMPRESSED_SIEVE = addDefaultCompressedSieve("birch", SoundType.WOOD, ExDeorum.ID);
public static final CompressedSieveMaterial JUNGLE_COMPRESSED_SIEVE = addDefaultCompressedSieve("jungle", SoundType.WOOD, ExDeorum.ID);
public static final CompressedSieveMaterial ACACIA_COMPRESSED_SIEVE = addDefaultCompressedSieve("acacia", SoundType.WOOD, ExDeorum.ID);
public static final CompressedSieveMaterial DARK_OAK_COMPRESSED_SIEVE = addDefaultCompressedSieve("dark_oak", SoundType.WOOD, ExDeorum.ID);
public static final CompressedSieveMaterial MANGROVE_COMPRESSED_SIEVE = addDefaultCompressedSieve("mangrove", SoundType.WOOD, ExDeorum.ID);
public static final CompressedSieveMaterial CHERRY_COMPRESSED_SIEVE = addDefaultCompressedSieve("cherry", SoundType.CHERRY_WOOD, ExDeorum.ID);
public static final CompressedSieveMaterial BAMBOO_COMPRESSED_SIEVE = addDefaultCompressedSieve("bamboo", SoundType.BAMBOO_WOOD, ExDeorum.ID);
public static final CompressedSieveMaterial WARPED_COMPRESSED_SIEVE = addDefaultCompressedSieve("warped", SoundType.NETHER_WOOD, ExDeorum.ID);
public static final CompressedSieveMaterial CRIMSON_COMPRESSED_SIEVE = addDefaultCompressedSieve("crimson", SoundType.NETHER_WOOD, ExDeorum.ID);
// Biomes O' Plenty
public static final CompressedSieveMaterial FIR_COMPRESSED_SIEVE = addDefaultCompressedSieve("fir", SoundType.WOOD, ModIds.BIOMES_O_PLENTY);
public static final CompressedSieveMaterial REDWOOD_COMPRESSED_SIEVE = addDefaultCompressedSieve("redwood", SoundType.WOOD, ModIds.BIOMES_O_PLENTY);
public static final CompressedSieveMaterial MAHOGANY_COMPRESSED_SIEVE = addDefaultCompressedSieve("mahogany", SoundType.WOOD, ModIds.BIOMES_O_PLENTY);
public static final CompressedSieveMaterial JACARANDA_COMPRESSED_SIEVE = addDefaultCompressedSieve("jacaranda", SoundType.WOOD, ModIds.BIOMES_O_PLENTY);
public static final CompressedSieveMaterial PALM_COMPRESSED_SIEVE = addDefaultCompressedSieve("palm", SoundType.WOOD, ModIds.BIOMES_O_PLENTY);
public static final CompressedSieveMaterial WILLOW_COMPRESSED_SIEVE = addDefaultCompressedSieve("willow", SoundType.WOOD, ModIds.BIOMES_O_PLENTY);
public static final CompressedSieveMaterial DEAD_COMPRESSED_SIEVE = addDefaultCompressedSieve("dead", SoundType.WOOD, ModIds.BIOMES_O_PLENTY);
public static final CompressedSieveMaterial MAGIC_COMPRESSED_SIEVE = addDefaultCompressedSieve("magic", SoundType.WOOD, ModIds.BIOMES_O_PLENTY);
public static final CompressedSieveMaterial UMBRAN_COMPRESSED_SIEVE = addDefaultCompressedSieve("umbran", SoundType.WOOD, ModIds.BIOMES_O_PLENTY);
public static final CompressedSieveMaterial HELLBARK_COMPRESSED_SIEVE = addDefaultCompressedSieve("hellbark", SoundType.WOOD, ModIds.BIOMES_O_PLENTY);
// Ars Nouveau
public static final CompressedSieveMaterial CASCADING_ARCHWOOD_COMPRESSED_SIEVE = addDefaultCompressedSieve("blue_archwood", SoundType.WOOD, ModIds.ARS_NOUVEAU);
public static final CompressedSieveMaterial BLAZING_ARCHWOOD_COMPRESSED_SIEVE = addDefaultCompressedSieve("red_archwood", SoundType.WOOD, ModIds.ARS_NOUVEAU);
public static final CompressedSieveMaterial VEXING_ARCHWOOD_COMPRESSED_SIEVE = addDefaultCompressedSieve("purple_archwood", SoundType.WOOD, ModIds.ARS_NOUVEAU);
public static final CompressedSieveMaterial FLOURISHING_ARCHWOOD_COMPRESSED_SIEVE = addDefaultCompressedSieve("green_archwood", SoundType.WOOD, ModIds.ARS_NOUVEAU);
// Aether
public static final CompressedSieveMaterial SKYROOT_COMPRESSED_SIEVE = addDefaultCompressedSieve("skyroot", SoundType.WOOD, ModIds.AETHER);
public static final CompressedSieveMaterial GOLDEN_OAK_COMPRESSED_SIEVE = addDefaultCompressedSieve("golden_oak", SoundType.WOOD, ModIds.AETHER);
// Blue Skies
public static final CompressedSieveMaterial BLUEBRIGHT_COMPRESSED_SIEVE = addDefaultCompressedSieve("bluebright", SoundType.WOOD, ModIds.BLUE_SKIES);
public static final CompressedSieveMaterial STARLIT_COMPRESSED_SIEVE = addDefaultCompressedSieve("starlit", SoundType.WOOD, ModIds.BLUE_SKIES);
public static final CompressedSieveMaterial FROSTBRIGHT_COMPRESSED_SIEVE = addDefaultCompressedSieve("frostbright", SoundType.WOOD, ModIds.BLUE_SKIES);
public static final CompressedSieveMaterial COMET_COMPRESSED_SIEVE = addDefaultCompressedSieve("comet", SoundType.WOOD, ModIds.BLUE_SKIES);
public static final CompressedSieveMaterial LUNAR_COMPRESSED_SIEVE = addDefaultCompressedSieve("lunar", SoundType.WOOD, ModIds.BLUE_SKIES);
public static final CompressedSieveMaterial DUSK_COMPRESSED_SIEVE = addDefaultCompressedSieve("dusk", SoundType.WOOD, ModIds.BLUE_SKIES);
public static final CompressedSieveMaterial MAPLE_COMPRESSED_SIEVE = addDefaultCompressedSieve("maple", SoundType.WOOD, ModIds.BLUE_SKIES);
public static final CompressedSieveMaterial CRYSTALLIZED_COMPRESSED_SIEVE = addDefaultCompressedSieve("crystallized", SoundType.WOOD, true, ModIds.BLUE_SKIES);
// Ex Deorum
public static final LavaCrucibleMaterial PORCELAIN_CRUCIBLE = addDefaultLavaCrucible("porcelain", SoundType.STONE, 2.0f, false, MapColor.TERRACOTTA_WHITE, ExDeorum.ID);
public static final LavaCrucibleMaterial WARPED_CRUCIBLE = addDefaultLavaCrucible("warped", SoundType.STEM, 1.5f, false, MapColor.CRIMSON_STEM, ExDeorum.ID);
@ -171,6 +213,16 @@ public class DefaultMaterials {
return material;
}
private static CompressedSieveMaterial addDefaultCompressedSieve(String name, SoundType soundType, String requiredModID) {
return addDefaultCompressedSieve(name, soundType, false, requiredModID);
}
private static CompressedSieveMaterial addDefaultCompressedSieve(String name, SoundType soundType, boolean needsCorrectTool, String requiredModId) {
var material = new CompressedSieveMaterial(soundType, 2.0f, needsCorrectTool, requiredModId);
COMPRESSED_SIEVES.register(name, material);
return material;
}
private static LavaCrucibleMaterial addDefaultLavaCrucible(String name, SoundType soundType, float strength, boolean needsCorrectTool, MapColor color, String requiredModId) {
var material = new LavaCrucibleMaterial(soundType, strength, needsCorrectTool, color.id, requiredModId);
LAVA_CRUCIBLES.register(name, material);
@ -187,6 +239,7 @@ public class DefaultMaterials {
public static void registerMaterials() {
BARRELS.search(BarrelMaterial::readFromJson);
SIEVES.search(SieveMaterial::readFromJson);
// todo compressed sieve JSON
LAVA_CRUCIBLES.search(parser -> AbstractCrucibleMaterial.readFromJson(parser, LavaCrucibleMaterial::new));
WATER_CRUCIBLES.search(parser -> AbstractCrucibleMaterial.readFromJson(parser, WaterCrucibleMaterial::new));
}

View File

@ -33,6 +33,7 @@ import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.RecipeHolder;
import net.minecraft.world.item.crafting.RecipeManager;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.Property;
@ -44,6 +45,7 @@ import net.minecraft.world.level.storage.loot.providers.number.*;
import net.neoforged.neoforge.fluids.FluidStack;
import org.jetbrains.annotations.Nullable;
import thedarkcolour.exdeorum.compat.PreferredOres;
import thedarkcolour.exdeorum.item.CompressedHammerItem;
import thedarkcolour.exdeorum.item.HammerItem;
import thedarkcolour.exdeorum.loot.SummationGenerator;
import thedarkcolour.exdeorum.recipe.barrel.BarrelCompostRecipe;
@ -53,7 +55,9 @@ import thedarkcolour.exdeorum.recipe.barrel.FluidTransformationRecipe;
import thedarkcolour.exdeorum.recipe.cache.*;
import thedarkcolour.exdeorum.recipe.crook.CrookRecipe;
import thedarkcolour.exdeorum.recipe.crucible.CrucibleRecipe;
import thedarkcolour.exdeorum.recipe.hammer.CompressedHammerRecipe;
import thedarkcolour.exdeorum.recipe.hammer.HammerRecipe;
import thedarkcolour.exdeorum.recipe.sieve.CompressedSieveRecipe;
import thedarkcolour.exdeorum.recipe.sieve.SieveRecipe;
import thedarkcolour.exdeorum.registry.ENumberProviders;
import thedarkcolour.exdeorum.registry.ERecipeTypes;
@ -71,7 +75,9 @@ public final class RecipeUtil {
private static SingleIngredientRecipeCache<CrucibleRecipe> lavaCrucibleRecipeCache;
private static SingleIngredientRecipeCache<CrucibleRecipe> waterCrucibleRecipeCache;
private static SingleIngredientRecipeCache<HammerRecipe> hammerRecipeCache;
private static SieveRecipeCache sieveRecipeCache;
private static SingleIngredientRecipeCache<CompressedHammerRecipe> compressedHammerRecipeCache;
private static SieveRecipeCache<SieveRecipe> sieveRecipeCache;
private static SieveRecipeCache<CompressedSieveRecipe> compressedSieveRecipeCache;
private static BarrelFluidMixingRecipeCache barrelFluidMixingRecipeCache;
private static FluidTransformationRecipeCache fluidTransformationRecipeCache;
private static CrookRecipeCache crookRecipeCache;
@ -81,13 +87,16 @@ public final class RecipeUtil {
barrelCompostRecipeCache = new SingleIngredientRecipeCache<>(recipes, ERecipeTypes.BARREL_COMPOST);
lavaCrucibleRecipeCache = new SingleIngredientRecipeCache<>(recipes, ERecipeTypes.LAVA_CRUCIBLE);
waterCrucibleRecipeCache = new SingleIngredientRecipeCache<>(recipes, ERecipeTypes.WATER_CRUCIBLE);
hammerRecipeCache = new SingleIngredientRecipeCache<>(recipes, ERecipeTypes.HAMMER);
sieveRecipeCache = new SieveRecipeCache(recipes);
hammerRecipeCache = new SingleIngredientRecipeCache<>(recipes, ERecipeTypes.HAMMER).trackAllRecipes();
compressedHammerRecipeCache = new SingleIngredientRecipeCache<>(recipes, ERecipeTypes.COMPRESSED_HAMMER).trackAllRecipes();
sieveRecipeCache = new SieveRecipeCache<>(recipes, ERecipeTypes.SIEVE);
compressedSieveRecipeCache = new SieveRecipeCache<>(recipes, ERecipeTypes.COMPRESSED_SIEVE);
barrelFluidMixingRecipeCache = new BarrelFluidMixingRecipeCache(recipes);
fluidTransformationRecipeCache = new FluidTransformationRecipeCache(recipes);
crookRecipeCache = new CrookRecipeCache(recipes);
crucibleHeatRecipeCache = new CrucibleHeatRecipeCache(recipes);
HammerItem.refreshValidBlocks();
CompressedHammerItem.refreshValidBlocks();
}
public static void unload() {
@ -95,7 +104,9 @@ public final class RecipeUtil {
lavaCrucibleRecipeCache = null;
waterCrucibleRecipeCache = null;
hammerRecipeCache = null;
compressedHammerRecipeCache = null;
sieveRecipeCache = null;
compressedSieveRecipeCache = null;
barrelFluidMixingRecipeCache = null;
fluidTransformationRecipeCache = null;
crookRecipeCache = null;
@ -106,6 +117,10 @@ public final class RecipeUtil {
return sieveRecipeCache.getRecipe(mesh, item);
}
public static List<CompressedSieveRecipe> getCompressedSieveRecipes(Item mesh, ItemStack item) {
return compressedSieveRecipeCache.getRecipe(mesh, item);
}
@Nullable
public static CrucibleRecipe getLavaCrucibleRecipe(ItemStack item) {
return lavaCrucibleRecipeCache.getRecipe(item);
@ -126,6 +141,19 @@ public final class RecipeUtil {
return hammerRecipeCache.getRecipe(item);
}
public static Collection<RecipeHolder<HammerRecipe>> getCachedHammerRecipes() {
return hammerRecipeCache.getAllRecipes();
}
@Nullable
public static CompressedHammerRecipe getCompressedHammerRecipe(Item item) {
return compressedHammerRecipeCache.getRecipe(item);
}
public static Collection<RecipeHolder<CompressedHammerRecipe>> getCachedCompressedHammerRecipes() {
return compressedHammerRecipeCache.getAllRecipes();
}
public static void toNetworkNumberProvider(FriendlyByteBuf buffer, NumberProvider provider) {
if (provider.getType() == NumberProviders.CONSTANT) {
buffer.writeByte(CONSTANT_TYPE);

View File

@ -22,25 +22,28 @@ import com.google.common.collect.ImmutableList;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.RecipeManager;
import net.minecraft.world.item.crafting.RecipeType;
import org.jetbrains.annotations.Nullable;
import thedarkcolour.exdeorum.recipe.sieve.SieveRecipe;
import thedarkcolour.exdeorum.registry.ERecipeTypes;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
public class SieveRecipeCache {
public class SieveRecipeCache<T extends SieveRecipe> {
private RecipeManager recipeManager;
private final Supplier<? extends RecipeType<T>> recipeType;
@Nullable
private Map<Item, MeshRecipeCache> meshCaches;
private Map<Item, MeshRecipeCache<T>> meshCaches;
public SieveRecipeCache(RecipeManager recipeManager) {
public SieveRecipeCache(RecipeManager recipeManager, Supplier<? extends RecipeType<T>> recipeType) {
this.recipeManager = recipeManager;
this.recipeType = recipeType;
}
public List<SieveRecipe> getRecipe(Item mesh, ItemStack input) {
public List<T> getRecipe(Item mesh, ItemStack input) {
if (this.meshCaches == null) {
buildRecipes();
}
@ -50,14 +53,14 @@ public class SieveRecipeCache {
private void buildRecipes() {
// Group recipes based on their mesh
var tempMap = new HashMap<Item, List<SieveRecipe>>();
for (var holder : this.recipeManager.byType(ERecipeTypes.SIEVE.get()).values()) {
var tempMap = new HashMap<Item, List<T>>();
for (var holder : this.recipeManager.byType(this.recipeType.get()).values()) {
var recipe = holder.value();
tempMap.computeIfAbsent(recipe.mesh, k -> new ArrayList<>()).add(recipe);
}
this.meshCaches = new HashMap<>();
for (var mesh : tempMap.entrySet()) {
this.meshCaches.put(mesh.getKey(), new MeshRecipeCache(mesh.getValue()));
this.meshCaches.put(mesh.getKey(), new MeshRecipeCache<>(mesh.getValue()));
}
this.recipeManager = null;
}
@ -67,12 +70,12 @@ public class SieveRecipeCache {
// conveying this information in JEI would be difficult (ex. Bottle drops from Sand, but only if the Sand has a
// certain enchantment). Thirdly, I do not see anybody needing this use case, and if they do, they should contact
// me on GitHub or Discord so that I can get around to actually implementing it.
private static class MeshRecipeCache {
private final Map<Item, List<SieveRecipe>> simpleRecipes;
private static class MeshRecipeCache<T extends SieveRecipe> {
private final Map<Item, List<T>> simpleRecipes;
private MeshRecipeCache(List<SieveRecipe> recipes) {
private MeshRecipeCache(List<T> recipes) {
this.simpleRecipes = new HashMap<>();
var temp = new HashMap<Item, ImmutableList.Builder<SieveRecipe>>();
var temp = new HashMap<Item, ImmutableList.Builder<T>>();
for (var recipe : recipes) {
for (var item : recipe.ingredient.getItems()) {
@ -85,7 +88,7 @@ public class SieveRecipeCache {
}
}
public List<SieveRecipe> getRecipes(ItemStack input) {
public List<T> getRecipes(ItemStack input) {
var result = this.simpleRecipes.get(input.getItem());
return result == null ? List.of() : result;
}

View File

@ -40,12 +40,20 @@ public class SingleIngredientRecipeCache<T extends SingleIngredientRecipe> {
private Map<Item, T> simpleRecipes;
@Nullable
private List<T> complexRecipes;
@Nullable
private Collection<RecipeHolder<T>> allRecipes;
private boolean trackAllRecipes;
public SingleIngredientRecipeCache(RecipeManager recipeManager, Supplier<RecipeType<T>> recipeType) {
this.recipeType = recipeType;
this.recipeManager = recipeManager;
}
public SingleIngredientRecipeCache<T> trackAllRecipes() {
this.trackAllRecipes = true;
return this;
}
@Nullable
public T getRecipe(Item item) {
return getRecipe(new ItemStack(item));
@ -74,6 +82,13 @@ public class SingleIngredientRecipeCache<T extends SingleIngredientRecipe> {
}
}
public Collection<RecipeHolder<T>> getAllRecipes() {
if (this.simpleRecipes == null) {
buildRecipes();
}
return this.allRecipes;
}
/**
* Called when this recipe cache is first queried. First, scans available recipes for recipes with "simple"
* ingredients that do not check an item's NBT. All of these recipes are added to the {@link #simpleRecipes}
@ -105,6 +120,10 @@ public class SingleIngredientRecipeCache<T extends SingleIngredientRecipe> {
if (this.complexRecipes.isEmpty()) {
this.complexRecipes = null;
}
// Track list of simple and complex recipes (only used by hammer so far)
if (this.trackAllRecipes) {
this.allRecipes = allRecipes;
}
this.recipeManager = null;
}

View File

@ -0,0 +1,42 @@
package thedarkcolour.exdeorum.recipe.hammer;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.RecipeSerializer;
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.level.storage.loot.providers.number.NumberProvider;
import thedarkcolour.exdeorum.recipe.ProbabilityRecipe;
import thedarkcolour.exdeorum.registry.ERecipeSerializers;
import thedarkcolour.exdeorum.registry.ERecipeTypes;
public class CompressedHammerRecipe extends HammerRecipe {
private static final Codec<CompressedHammerRecipe> CODEC = RecordCodecBuilder.create(instance -> ProbabilityRecipe.commonFields(instance).apply(instance, CompressedHammerRecipe::new));
public CompressedHammerRecipe(Ingredient ingredient, Item result, NumberProvider resultAmount) {
super(ingredient, result, resultAmount);
}
@Override
public RecipeSerializer<?> getSerializer() {
return ERecipeSerializers.COMPRESSED_HAMMER.get();
}
@Override
public RecipeType<?> getType() {
return ERecipeTypes.COMPRESSED_HAMMER.get();
}
public static class Serializer extends HammerRecipe.AbstractSerializer<CompressedHammerRecipe> {
@Override
protected CompressedHammerRecipe createHammerRecipe(Ingredient ingredient, Item result, NumberProvider resultAmount) {
return new CompressedHammerRecipe(ingredient, result, resultAmount);
}
@Override
public Codec<CompressedHammerRecipe> codec() {
return CODEC;
}
}
}

View File

@ -32,8 +32,10 @@ import thedarkcolour.exdeorum.recipe.RecipeUtil;
import thedarkcolour.exdeorum.registry.ERecipeSerializers;
import thedarkcolour.exdeorum.registry.ERecipeTypes;
import java.util.Objects;
public class HammerRecipe extends ProbabilityRecipe {
public static final Codec<HammerRecipe> CODEC = RecordCodecBuilder.create(instance -> ProbabilityRecipe.commonFields(instance).apply(instance, HammerRecipe::new));
private static final Codec<HammerRecipe> CODEC = RecordCodecBuilder.create(instance -> ProbabilityRecipe.commonFields(instance).apply(instance, HammerRecipe::new));
public HammerRecipe(Ingredient ingredient, Item result, NumberProvider resultAmount) {
super(ingredient, result, resultAmount);
@ -49,25 +51,34 @@ public class HammerRecipe extends ProbabilityRecipe {
return ERecipeTypes.HAMMER.get();
}
public static class Serializer implements RecipeSerializer<HammerRecipe> {
public static abstract class AbstractSerializer<T extends HammerRecipe> implements RecipeSerializer<T> {
protected abstract T createHammerRecipe(Ingredient ingredient, Item result, NumberProvider resultAmount);
@Override
public T fromNetwork(FriendlyByteBuf buffer) {
Ingredient ingredient = Ingredient.fromNetwork(buffer);
Item result = Objects.requireNonNull(buffer.readById(BuiltInRegistries.ITEM));
NumberProvider resultAmount = RecipeUtil.fromNetworkNumberProvider(buffer);
return createHammerRecipe(ingredient, result, resultAmount);
}
@Override
public void toNetwork(FriendlyByteBuf buffer, T recipe) {
recipe.getIngredient().toNetwork(buffer);
buffer.writeId(BuiltInRegistries.ITEM, recipe.result);
RecipeUtil.toNetworkNumberProvider(buffer, recipe.resultAmount);
}
}
public static class Serializer extends HammerRecipe.AbstractSerializer<HammerRecipe> {
@Override
public Codec<HammerRecipe> codec() {
return CODEC;
}
@Override
public HammerRecipe fromNetwork(FriendlyByteBuf buffer) {
Ingredient ingredient = Ingredient.fromNetwork(buffer);
Item result = buffer.readById(BuiltInRegistries.ITEM);
NumberProvider resultAmount = RecipeUtil.fromNetworkNumberProvider(buffer);
protected HammerRecipe createHammerRecipe(Ingredient ingredient, Item result, NumberProvider resultAmount) {
return new HammerRecipe(ingredient, result, resultAmount);
}
@Override
public void toNetwork(FriendlyByteBuf buffer, HammerRecipe recipe) {
recipe.getIngredient().toNetwork(buffer);
buffer.writeId(BuiltInRegistries.ITEM, recipe.result);
RecipeUtil.toNetworkNumberProvider(buffer, recipe.resultAmount);
}
}
}

View File

@ -0,0 +1,41 @@
package thedarkcolour.exdeorum.recipe.sieve;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.RecipeSerializer;
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.level.storage.loot.providers.number.NumberProvider;
import thedarkcolour.exdeorum.registry.ERecipeSerializers;
import thedarkcolour.exdeorum.registry.ERecipeTypes;
public class CompressedSieveRecipe extends SieveRecipe {
private static final Codec<CompressedSieveRecipe> CODEC = RecordCodecBuilder.create(instance -> commonSieveFields(instance).apply(instance, CompressedSieveRecipe::new));
public CompressedSieveRecipe(Ingredient ingredient, Item result, NumberProvider resultAmount, Item mesh, boolean byHandOnly) {
super(ingredient, result, resultAmount, mesh, byHandOnly);
}
@Override
public RecipeSerializer<?> getSerializer() {
return ERecipeSerializers.COMPRESSED_SIEVE.get();
}
@Override
public RecipeType<?> getType() {
return ERecipeTypes.COMPRESSED_SIEVE.get();
}
public static class Serializer extends SieveRecipe.AbstractSerializer<CompressedSieveRecipe> {
@Override
protected CompressedSieveRecipe createSieveRecipe(Ingredient ingredient, Item result, NumberProvider resultAmount, Item mesh, boolean byHandOnly) {
return new CompressedSieveRecipe(ingredient, result, resultAmount, mesh, byHandOnly);
}
@Override
public Codec<CompressedSieveRecipe> codec() {
return CODEC;
}
}
}

View File

@ -18,7 +18,7 @@
package thedarkcolour.exdeorum.recipe.sieve;
import com.google.common.base.Preconditions;
import com.mojang.datafixers.Products;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.registries.BuiltInRegistries;
@ -37,11 +37,15 @@ import thedarkcolour.exdeorum.registry.ERecipeTypes;
import java.util.Objects;
public class SieveRecipe extends ProbabilityRecipe {
public static final Codec<SieveRecipe> CODEC = RecordCodecBuilder.create(instance -> commonFields(instance).and(
instance.group(
CodecUtil.itemField("mesh", SieveRecipe::getMesh),
Codec.BOOL.optionalFieldOf("by_hand_only", false).forGetter(SieveRecipe::isByHandOnly)
)).apply(instance, SieveRecipe::new));
private static final Codec<SieveRecipe> CODEC = RecordCodecBuilder.create(instance -> commonSieveFields(instance).apply(instance, SieveRecipe::new));
protected static <T extends SieveRecipe> Products.P5<RecordCodecBuilder.Mu<T>, Ingredient, Item, NumberProvider, Item, Boolean> commonSieveFields(RecordCodecBuilder.Instance<T> instance) {
return commonFields(instance).and(
instance.group(
CodecUtil.itemField("mesh", SieveRecipe::getMesh),
Codec.BOOL.optionalFieldOf("by_hand_only", false).forGetter(SieveRecipe::isByHandOnly)
));
}
public final Item mesh;
public final boolean byHandOnly;
@ -71,21 +75,18 @@ public class SieveRecipe extends ProbabilityRecipe {
return ERecipeTypes.SIEVE.get();
}
public static class Serializer implements RecipeSerializer<SieveRecipe> {
public static abstract class AbstractSerializer<T extends SieveRecipe> implements RecipeSerializer<T> {
@Override
public Codec<SieveRecipe> codec() {
return CODEC;
}
@Override
public SieveRecipe fromNetwork(FriendlyByteBuf buffer) {
public T fromNetwork(FriendlyByteBuf buffer) {
Ingredient ingredient = Ingredient.fromNetwork(buffer);
Item mesh = Objects.requireNonNull(buffer.readById(BuiltInRegistries.ITEM));
Item result = Objects.requireNonNull(buffer.readById(BuiltInRegistries.ITEM));
NumberProvider resultAmount = RecipeUtil.fromNetworkNumberProvider(buffer);
return new SieveRecipe(ingredient, result, resultAmount, mesh, buffer.readBoolean());
return createSieveRecipe(ingredient, result, resultAmount, mesh, buffer.readBoolean());
}
protected abstract T createSieveRecipe(Ingredient ingredient, Item result, NumberProvider resultAmount, Item mesh, boolean byHandOnly);
@Override
public void toNetwork(FriendlyByteBuf buffer, SieveRecipe recipe) {
recipe.getIngredient().toNetwork(buffer);
@ -95,4 +96,16 @@ public class SieveRecipe extends ProbabilityRecipe {
buffer.writeBoolean(recipe.byHandOnly);
}
}
public static class Serializer extends AbstractSerializer<SieveRecipe> {
@Override
protected SieveRecipe createSieveRecipe(Ingredient ingredient, Item result, NumberProvider resultAmount, Item mesh, boolean byHandOnly) {
return new SieveRecipe(ingredient, result, resultAmount, mesh, byHandOnly);
}
@Override
public Codec<SieveRecipe> codec() {
return CODEC;
}
}
}

View File

@ -34,6 +34,7 @@ public class EBlockEntities {
public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<WaterCrucibleBlockEntity>> WATER_CRUCIBLE = BLOCK_ENTITIES.register("water_crucible", () -> DefaultMaterials.WATER_CRUCIBLES.createBlockEntityType(WaterCrucibleBlockEntity::new));
public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<BarrelBlockEntity>> BARREL = BLOCK_ENTITIES.register("barrel", () -> DefaultMaterials.BARRELS.createBlockEntityType(BarrelBlockEntity::new));
public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<SieveBlockEntity>> SIEVE = BLOCK_ENTITIES.register("sieve", () -> DefaultMaterials.SIEVES.createBlockEntityType(SieveBlockEntity::new));
public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<CompressedSieveBlockEntity>> COMPRESSED_SIEVE = BLOCK_ENTITIES.register("compressed_sieve", () -> DefaultMaterials.COMPRESSED_SIEVES.createBlockEntityType(CompressedSieveBlockEntity::new));
public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<MechanicalSieveBlockEntity>> MECHANICAL_SIEVE = BLOCK_ENTITIES.register("mechanical_sieve", () -> BlockEntityType.Builder.of(MechanicalSieveBlockEntity::new, EBlocks.MECHANICAL_SIEVE.get()).build(null));
public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<MechanicalHammerBlockEntity>> MECHANICAL_HAMMER = BLOCK_ENTITIES.register("mechanical_hammer", () -> BlockEntityType.Builder.of(MechanicalHammerBlockEntity::new, EBlocks.MECHANICAL_HAMMER.get()).build(null));
}

View File

@ -30,7 +30,7 @@ import thedarkcolour.exdeorum.block.*;
import static net.minecraft.world.level.block.state.BlockBehaviour.Properties.*;
// READER'S NOTE: More blocks are found in DefaultMaterials.java
// READER'S NOTE: More blocks are found in DefaultMaterials.java and ECompressedBlocks.java
public class EBlocks {
public static final DeferredRegister.Blocks BLOCKS = DeferredRegister.createBlocks(ExDeorum.ID);

View File

@ -0,0 +1,52 @@
package thedarkcolour.exdeorum.registry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.neoforged.neoforge.registries.DeferredBlock;
import thedarkcolour.exdeorum.block.CompressedBlockType;
import java.util.ArrayList;
import java.util.List;
public class ECompressedBlocks {
public static final List<CompressedBlockType> ALL_VARIANTS = new ArrayList<>();
public static final CompressedBlockType COMPRESSED_DIRT = register(Blocks.DIRT).withCompressium();
public static final CompressedBlockType COMPRESSED_COBBLESTONE = register(Blocks.COBBLESTONE).withCompressium();
public static final CompressedBlockType COMPRESSED_DIORITE = register(Blocks.DIORITE).withCompressium();
public static final CompressedBlockType COMPRESSED_GRANITE = register(Blocks.GRANITE).withCompressium();
public static final CompressedBlockType COMPRESSED_ANDESITE = register(Blocks.ANDESITE).withCompressium();
public static final CompressedBlockType COMPRESSED_GRAVEL = register(Blocks.GRAVEL).withCompressium();
public static final CompressedBlockType COMPRESSED_SAND = register(Blocks.SAND).withCompressium();
public static final CompressedBlockType COMPRESSED_DUST = register(EBlocks.DUST);
public static final CompressedBlockType COMPRESSED_RED_SAND = register(Blocks.RED_SAND).withCompressium();
public static final CompressedBlockType COMPRESSED_DEEPSLATE = register(Blocks.DEEPSLATE);
public static final CompressedBlockType COMPRESSED_COBBLED_DEEPSLATE = register(Blocks.COBBLED_DEEPSLATE);
public static final CompressedBlockType COMPRESSED_NETHERRACK = register(Blocks.NETHERRACK).withCompressium();
public static final CompressedBlockType COMPRESSED_BLACKSTONE = register(Blocks.BLACKSTONE);
public static final CompressedBlockType COMPRESSED_END_STONE = register(Blocks.END_STONE);
public static final CompressedBlockType COMPRESSED_CRUSHED_DEEPSLATE = register(EBlocks.CRUSHED_DEEPSLATE);
public static final CompressedBlockType COMPRESSED_CRUSHED_BLACKSTONE = register(EBlocks.CRUSHED_BLACKSTONE);
public static final CompressedBlockType COMPRESSED_CRUSHED_NETHERRACK = register(EBlocks.CRUSHED_NETHERRACK);
public static final CompressedBlockType COMPRESSED_SOUL_SAND = register(Blocks.SOUL_SAND).withCompressium();
public static final CompressedBlockType COMPRESSED_CRUSHED_END_STONE = register(EBlocks.CRUSHED_END_STONE);
public static final CompressedBlockType COMPRESSED_MOSS_BLOCK = register(Blocks.MOSS_BLOCK);
private static CompressedBlockType register(Block vanillaBase) {
CompressedBlockType type = new CompressedBlockType(BuiltInRegistries.BLOCK.getKey(vanillaBase).getPath(), () -> vanillaBase);
// AllTheCompressed has every vanilla block that Ex Deorum uses so far
type.withAtc();
ALL_VARIANTS.add(type);
return type;
}
private static CompressedBlockType register(DeferredBlock<Block> base) {
CompressedBlockType type = new CompressedBlockType(base.getId().getPath(), base);
ALL_VARIANTS.add(type);
return type;
}
public static void register() {
}
}

View File

@ -24,6 +24,7 @@ import net.neoforged.neoforge.registries.DeferredHolder;
import net.neoforged.neoforge.registries.DeferredRegister;
import net.neoforged.neoforge.registries.NeoForgeRegistries;
import thedarkcolour.exdeorum.ExDeorum;
import thedarkcolour.exdeorum.loot.CompressedHammerLootModifier;
import thedarkcolour.exdeorum.loot.CrookLootModifier;
import thedarkcolour.exdeorum.loot.HammerLootModifier;
@ -32,4 +33,5 @@ public class EGlobalLootModifiers {
public static final DeferredHolder<Codec<? extends IGlobalLootModifier>, Codec<CrookLootModifier>> CROOK = GLOBAL_LOOT_MODIFIERS.register("crook", () -> CrookLootModifier.CODEC);
public static final DeferredHolder<Codec<? extends IGlobalLootModifier>, Codec<HammerLootModifier>> HAMMER = GLOBAL_LOOT_MODIFIERS.register("hammer", () -> HammerLootModifier.CODEC);
public static final DeferredHolder<Codec<? extends IGlobalLootModifier>, Codec<CompressedHammerLootModifier>> COMPRESSED_HAMMER = GLOBAL_LOOT_MODIFIERS.register("compressed_hammer", () -> CompressedHammerLootModifier.CODEC);
}

View File

@ -18,6 +18,7 @@
package thedarkcolour.exdeorum.registry;
import com.google.common.collect.Iterables;
import net.minecraft.world.food.FoodProperties;
import net.minecraft.world.item.*;
import net.minecraft.world.level.block.Block;
@ -28,6 +29,7 @@ import net.neoforged.neoforge.registries.DeferredBlock;
import net.neoforged.neoforge.registries.DeferredItem;
import net.neoforged.neoforge.registries.DeferredRegister;
import thedarkcolour.exdeorum.ExDeorum;
import thedarkcolour.exdeorum.compat.CompatUtil;
import thedarkcolour.exdeorum.item.*;
import thedarkcolour.exdeorum.material.DefaultMaterials;
import thedarkcolour.exdeorum.recipe.RecipeUtil;
@ -70,6 +72,14 @@ public class EItems {
public static final DeferredItem<Item> DIAMOND_HAMMER = ITEMS.register("diamond_hammer", () -> new HammerItem(Tiers.DIAMOND, props()));
public static final DeferredItem<Item> NETHERITE_HAMMER = ITEMS.register("netherite_hammer", () -> new HammerItem(Tiers.NETHERITE, props()));
// Compressed Hammers
public static final DeferredItem<Item> COMPRESSED_WOODEN_HAMMER = ITEMS.register("compressed_wooden_hammer", () -> new CompressedHammerItem(Tiers.WOOD, props()));
public static final DeferredItem<Item> COMPRESSED_STONE_HAMMER = ITEMS.register("compressed_stone_hammer", () -> new CompressedHammerItem(Tiers.STONE, props()));
public static final DeferredItem<Item> COMPRESSED_GOLDEN_HAMMER = ITEMS.register("compressed_golden_hammer", () -> new CompressedHammerItem(Tiers.GOLD, props()));
public static final DeferredItem<Item> COMPRESSED_IRON_HAMMER = ITEMS.register("compressed_iron_hammer", () -> new CompressedHammerItem(Tiers.IRON, props()));
public static final DeferredItem<Item> COMPRESSED_DIAMOND_HAMMER = ITEMS.register("compressed_diamond_hammer", () -> new CompressedHammerItem(Tiers.DIAMOND, props()));
public static final DeferredItem<Item> COMPRESSED_NETHERITE_HAMMER = ITEMS.register("compressed_netherite_hammer", () -> new CompressedHammerItem(Tiers.NETHERITE, props()));
// Ore Chunks
public static final DeferredItem<Item> IRON_ORE_CHUNK = registerSimpleItem("iron_ore_chunk");
public static final DeferredItem<Item> COPPER_ORE_CHUNK = registerSimpleItem("copper_ore_chunk");
@ -156,31 +166,16 @@ public class EItems {
public static void addItemsToMainTab(CreativeModeTab.Output output) {
for (var material : DefaultMaterials.BARRELS) {
if (ModList.get().isLoaded(material.requiredModId)) {
output.accept(material.getItem());
}
}
for (var material : DefaultMaterials.SIEVES) {
if (ModList.get().isLoaded(material.requiredModId)) {
output.accept(material.getItem());
}
for (var material : Iterables.concat(CompatUtil.getAvailableBarrels(true), CompatUtil.getAvailableSieves(true, false), CompatUtil.getAvailableCompressedSieves(true))) {
output.accept(material);
}
output.accept(MECHANICAL_SIEVE.get());
output.accept(MECHANICAL_HAMMER.get());
output.accept(UNFIRED_PORCELAIN_CRUCIBLE.get());
for (var material : DefaultMaterials.LAVA_CRUCIBLES) {
if (ModList.get().isLoaded(material.requiredModId)) {
output.accept(material.getItem());
}
}
for (var material : DefaultMaterials.WATER_CRUCIBLES) {
if (ModList.get().isLoaded(material.requiredModId)) {
output.accept(material.getItem());
}
for (var material : Iterables.concat(CompatUtil.getAvailableLavaCrucibles(true), CompatUtil.getAvailableWaterCrucibles(true))) {
output.accept(material);
}
output.accept(DUST.get());
@ -188,6 +183,28 @@ public class EItems {
output.accept(CRUSHED_END_STONE.get());
output.accept(CRUSHED_DEEPSLATE.get());
output.accept(CRUSHED_BLACKSTONE.get());
output.accept(ECompressedBlocks.COMPRESSED_DIRT.getItem());
output.accept(ECompressedBlocks.COMPRESSED_COBBLESTONE.getItem());
output.accept(ECompressedBlocks.COMPRESSED_DIORITE.getItem());
output.accept(ECompressedBlocks.COMPRESSED_GRANITE.getItem());
output.accept(ECompressedBlocks.COMPRESSED_ANDESITE.getItem());
output.accept(ECompressedBlocks.COMPRESSED_GRAVEL.getItem());
output.accept(ECompressedBlocks.COMPRESSED_SAND.getItem());
output.accept(ECompressedBlocks.COMPRESSED_DUST.getItem());
output.accept(ECompressedBlocks.COMPRESSED_RED_SAND.getItem());
output.accept(ECompressedBlocks.COMPRESSED_DEEPSLATE.getItem());
output.accept(ECompressedBlocks.COMPRESSED_COBBLED_DEEPSLATE.getItem());
output.accept(ECompressedBlocks.COMPRESSED_NETHERRACK.getItem());
output.accept(ECompressedBlocks.COMPRESSED_BLACKSTONE.getItem());
output.accept(ECompressedBlocks.COMPRESSED_END_STONE.getItem());
output.accept(ECompressedBlocks.COMPRESSED_CRUSHED_DEEPSLATE.getItem());
output.accept(ECompressedBlocks.COMPRESSED_CRUSHED_BLACKSTONE.getItem());
output.accept(ECompressedBlocks.COMPRESSED_CRUSHED_NETHERRACK.getItem());
output.accept(ECompressedBlocks.COMPRESSED_SOUL_SAND.getItem());
output.accept(ECompressedBlocks.COMPRESSED_CRUSHED_END_STONE.getItem());
output.accept(ECompressedBlocks.COMPRESSED_MOSS_BLOCK.getItem());
output.accept(END_CAKE.get());
output.accept(RANDOM_ARMOR_TRIM.get());
output.accept(RANDOM_POTTERY_SHERD.get());
@ -214,6 +231,12 @@ public class EItems {
output.accept(IRON_HAMMER.get());
output.accept(DIAMOND_HAMMER.get());
output.accept(NETHERITE_HAMMER.get());
output.accept(COMPRESSED_WOODEN_HAMMER.get());
output.accept(COMPRESSED_STONE_HAMMER.get());
output.accept(COMPRESSED_GOLDEN_HAMMER.get());
output.accept(COMPRESSED_IRON_HAMMER.get());
output.accept(COMPRESSED_DIAMOND_HAMMER.get());
output.accept(COMPRESSED_NETHERITE_HAMMER.get());
output.accept(IRON_ORE_CHUNK.get());
output.accept(COPPER_ORE_CHUNK.get());
output.accept(GOLD_ORE_CHUNK.get());

View File

@ -31,7 +31,9 @@ import thedarkcolour.exdeorum.recipe.barrel.BarrelMixingRecipe;
import thedarkcolour.exdeorum.recipe.crook.CrookRecipe;
import thedarkcolour.exdeorum.recipe.crucible.CrucibleHeatRecipe;
import thedarkcolour.exdeorum.recipe.crucible.CrucibleRecipe;
import thedarkcolour.exdeorum.recipe.hammer.CompressedHammerRecipe;
import thedarkcolour.exdeorum.recipe.hammer.HammerRecipe;
import thedarkcolour.exdeorum.recipe.sieve.CompressedSieveRecipe;
import thedarkcolour.exdeorum.recipe.sieve.SieveRecipe;
public class ERecipeSerializers {
@ -43,6 +45,7 @@ public class ERecipeSerializers {
public static final DeferredHolder<RecipeSerializer<?>, RecipeSerializer<FluidTransformationRecipe>> BARREL_FLUID_TRANSFORMATION = RECIPE_SERIALIZERS.register("barrel_fluid_transformation", FluidTransformationRecipe.Serializer::new);
public static final DeferredHolder<RecipeSerializer<?>, RecipeSerializer<HammerRecipe>> HAMMER = RECIPE_SERIALIZERS.register("hammer", HammerRecipe.Serializer::new);
public static final DeferredHolder<RecipeSerializer<?>, RecipeSerializer<CompressedHammerRecipe>> COMPRESSED_HAMMER = RECIPE_SERIALIZERS.register("compressed_hammer", CompressedHammerRecipe.Serializer::new);
public static final DeferredHolder<RecipeSerializer<?>, RecipeSerializer<CrookRecipe>> CROOK = RECIPE_SERIALIZERS.register("crook", CrookRecipe.Serializer::new);
public static final DeferredHolder<RecipeSerializer<?>, RecipeSerializer<CrucibleHeatRecipe>> CRUCIBLE_HEAT_SOURCE = RECIPE_SERIALIZERS.register("crucible_heat_source", CrucibleHeatRecipe.Serializer::new);
@ -50,6 +53,7 @@ public class ERecipeSerializers {
public static final DeferredHolder<RecipeSerializer<?>, RecipeSerializer<CrucibleRecipe.Water>> WATER_CRUCIBLE = RECIPE_SERIALIZERS.register("water_crucible", () -> new CrucibleRecipe.Serializer<>(CrucibleRecipe.Water.CODEC, CrucibleRecipe.Water::new));
public static final DeferredHolder<RecipeSerializer<?>, RecipeSerializer<SieveRecipe>> SIEVE = RECIPE_SERIALIZERS.register("sieve", SieveRecipe.Serializer::new);
public static final DeferredHolder<RecipeSerializer<?>, RecipeSerializer<CompressedSieveRecipe>> COMPRESSED_SIEVE = RECIPE_SERIALIZERS.register("compressed_sieve", CompressedSieveRecipe.Serializer::new);
public static final DeferredHolder<RecipeSerializer<?>, RecipeSerializer<OreChunkRecipe>> ORE_CHUNK = RECIPE_SERIALIZERS.register("ore_chunk", OreChunkRecipe.Serializer::new);
}

View File

@ -30,7 +30,9 @@ import thedarkcolour.exdeorum.recipe.barrel.BarrelMixingRecipe;
import thedarkcolour.exdeorum.recipe.crook.CrookRecipe;
import thedarkcolour.exdeorum.recipe.crucible.CrucibleHeatRecipe;
import thedarkcolour.exdeorum.recipe.crucible.CrucibleRecipe;
import thedarkcolour.exdeorum.recipe.hammer.CompressedHammerRecipe;
import thedarkcolour.exdeorum.recipe.hammer.HammerRecipe;
import thedarkcolour.exdeorum.recipe.sieve.CompressedSieveRecipe;
import thedarkcolour.exdeorum.recipe.sieve.SieveRecipe;
public class ERecipeTypes {
@ -45,8 +47,10 @@ public class ERecipeTypes {
public static final DeferredHolder<RecipeType<?>, RecipeType<CrucibleRecipe>> WATER_CRUCIBLE = RECIPE_TYPES.register("water_crucible", () -> RecipeType.simple(ERecipeTypes.WATER_CRUCIBLE.getId()));
public static final DeferredHolder<RecipeType<?>, RecipeType<HammerRecipe>> HAMMER = RECIPE_TYPES.register("hammer", () -> RecipeType.simple(ERecipeTypes.HAMMER.getId()));
public static final DeferredHolder<RecipeType<?>, RecipeType<CompressedHammerRecipe>> COMPRESSED_HAMMER = RECIPE_TYPES.register("compressed_hammer", () -> RecipeType.simple(ERecipeTypes.COMPRESSED_HAMMER.getId()));
public static final DeferredHolder<RecipeType<?>, RecipeType<CrookRecipe>> CROOK = RECIPE_TYPES.register("crook", () -> RecipeType.simple(ERecipeTypes.CROOK.getId()));
public static final DeferredHolder<RecipeType<?>, RecipeType<CrucibleHeatRecipe>> CRUCIBLE_HEAT_SOURCE = RECIPE_TYPES.register("crucible_heat_source", () -> RecipeType.simple(ERecipeTypes.CRUCIBLE_HEAT_SOURCE.getId()));
public static final DeferredHolder<RecipeType<?>, RecipeType<SieveRecipe>> SIEVE = RECIPE_TYPES.register("sieve", () -> RecipeType.simple(ERecipeTypes.SIEVE.getId()));
public static final DeferredHolder<RecipeType<?>, RecipeType<CompressedSieveRecipe>> COMPRESSED_SIEVE = RECIPE_TYPES.register("compressed_sieve", () -> RecipeType.simple(ERecipeTypes.COMPRESSED_SIEVE.getId()));
}

View File

@ -27,6 +27,7 @@ import thedarkcolour.exdeorum.ExDeorum;
public class EItemTags {
public static final TagKey<Item> CROOKS = tag("crooks");
public static final TagKey<Item> HAMMERS = tag("hammers");
public static final TagKey<Item> COMPRESSED_HAMMERS = tag("compressed_hammers");
public static final TagKey<Item> SIEVE_MESHES = tag("sieve_meshes");
public static final TagKey<Item> PEBBLES = tag("pebbles");
public static final TagKey<Item> END_CAKE_MATERIAL = tag("end_cake_materials");
@ -51,6 +52,8 @@ public class EItemTags {
public static final TagKey<Item> ORES_LITHIUM = forgeTag("ores/lithium");
public static final TagKey<Item> ORES_BORON = forgeTag("ores/boron");
public static final TagKey<Item> COMPRESSED_SANDS = tag("compressed/sands");
public static TagKey<Item> tag(String name) {
return ItemTags.create(new ResourceLocation(ExDeorum.ID, name));
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,104 @@
{
"parent": "minecraft:block/block",
"textures": {
"particle": "#texture"
},
"elements": [
{
"from": [0, 8, 0],
"to": [15, 14, 1],
"faces": {
"north": {"uv": [1, 2, 16, 8], "texture": "#texture"},
"east": {"uv": [15, 2, 16, 8], "texture": "#texture"},
"south": {"uv": [0, 2, 15, 8], "texture": "#texture"},
"west": {"uv": [0, 2, 1, 8], "texture": "#texture"},
"up": {"uv": [0, 0, 15, 1], "texture": "#texture"},
"down": {"uv": [0, 15, 15, 16], "texture": "#texture"}
}
},
{
"from": [15, 8, 0],
"to": [16, 14, 15],
"faces": {
"north": {"uv": [0, 2, 1, 8], "texture": "#texture"},
"east": {"uv": [1, 2, 16, 8], "texture": "#texture"},
"south": {"uv": [15, 2, 16, 8], "texture": "#texture"},
"west": {"uv": [0, 2, 15, 8], "texture": "#texture"},
"up": {"uv": [15, 0, 16, 15], "texture": "#texture"},
"down": {"uv": [15, 1, 16, 16], "texture": "#texture"}
}
},
{
"from": [1, 8, 15],
"to": [16, 14, 16],
"faces": {
"north": {"uv": [0, 2, 15, 8], "texture": "#texture"},
"east": {"uv": [0, 2, 1, 8], "texture": "#texture"},
"south": {"uv": [1, 2, 16, 8], "texture": "#texture"},
"west": {"uv": [15, 2, 16, 8], "texture": "#texture"},
"up": {"uv": [1, 15, 16, 16], "texture": "#texture"},
"down": {"uv": [1, 0, 16, 1], "texture": "#texture"}
}
},
{
"from": [0, 8, 1],
"to": [1, 14, 16],
"faces": {
"north": {"uv": [15, 2, 16, 8], "texture": "#texture"},
"east": {"uv": [0, 2, 15, 8], "texture": "#texture"},
"south": {"uv": [0, 2, 1, 8], "texture": "#texture"},
"west": {"uv": [1, 2, 16, 8], "texture": "#texture"},
"up": {"uv": [0, 1, 1, 16], "texture": "#texture"},
"down": {"uv": [0, 0, 1, 15], "texture": "#texture"}
}
},
{
"from": [1, 0, 1],
"to": [3, 14, 3],
"faces": {
"north": {"uv": [13, 2, 15, 16], "texture": "#texture"},
"east": {"uv": [13, 2, 15, 16], "texture": "#texture"},
"south": {"uv": [1, 2, 3, 16], "texture": "#texture"},
"west": {"uv": [1, 2, 3, 16], "texture": "#texture"},
"up": {"uv": [1, 1, 3, 3], "texture": "#texture"},
"down": {"uv": [1, 13, 3, 15], "texture": "#texture"}
}
},
{
"from": [1, 0, 13],
"to": [3, 14, 15],
"faces": {
"north": {"uv": [13, 2, 15, 16], "texture": "#texture"},
"east": {"uv": [1, 2, 3, 16], "texture": "#texture"},
"south": {"uv": [1, 2, 3, 16], "texture": "#texture"},
"west": {"uv": [13, 2, 15, 16], "texture": "#texture"},
"up": {"uv": [1, 13, 3, 15], "texture": "#texture"},
"down": {"uv": [1, 1, 3, 3], "texture": "#texture"}
}
},
{
"from": [13, 0, 1],
"to": [15, 14, 3],
"faces": {
"north": {"uv": [1, 2, 3, 16], "texture": "#texture"},
"east": {"uv": [13, 2, 15, 16], "texture": "#texture"},
"south": {"uv": [13, 2, 15, 16], "texture": "#texture"},
"west": {"uv": [1, 2, 3, 16], "texture": "#texture"},
"up": {"uv": [13, 1, 15, 3], "texture": "#texture"},
"down": {"uv": [13, 13, 15, 15], "texture": "#texture"}
}
},
{
"from": [13, 0, 13],
"to": [15, 14, 15],
"faces": {
"north": {"uv": [1, 2, 3, 16], "texture": "#texture"},
"east": {"uv": [1, 2, 3, 16], "texture": "#texture"},
"south": {"uv": [13, 2, 15, 16], "texture": "#texture"},
"west": {"uv": [13, 2, 15, 16], "texture": "#texture"},
"up": {"uv": [13, 13, 15, 15], "texture": "#texture"},
"down": {"uv": [13, 1, 15, 3], "texture": "#texture"}
}
}
]
}