Finish up Crook Recipes, add Crucible Heat Source recipes.
This commit is contained in:
parent
40e6896135
commit
03798aefac
|
|
@ -1,10 +1,12 @@
|
|||
## Ex Deorum 1.21
|
||||
- Added Crook recipes. It is now possible to add drops to the crook, for example, you could make it so that using a Crook on tall grass would have a 1% chance of dropping a diamond.
|
||||
- Added Crucible Heat Source recipes. Instead of using KubeJS, crucible heat sources can now be added with datapacks. Old KubeJS scripts will still work fine.
|
||||
- Added Jade compatibility
|
||||
- Added partial compatibility with Roughly Enough Items to hide compat blocks for mods that aren't installed (use REI Plugin Compatibilities mod to gain full compatibility with Ex Deorum)
|
||||
- Added Roughly Enough Items compatibility to hide compat blocks for mods that aren't installed (use REI Plugin Compatibilities mod to gain full compatibility with Ex Deorum)
|
||||
- Added configurable sifting interval to limit speed of sifting by hand in order to curb the speed of autoclickers on sieves. (PR #47 by CPearl0)
|
||||
- Added Chinese translation (PR #45 by CPearl0)
|
||||
- Infested leaves string drop rate can now be configured in the server config.
|
||||
- Fixed dedicated server crash when using Mycelium Spores to convert a cow into a Mooshroom (PR #44 by CPearl0)
|
||||
- Fixed incorrect block lighting in JEI displays for Crucible heat sources and Crook recipes
|
||||
|
||||
## Ex Deorum 1.20
|
||||
- Added Mechanical Hammer, a machine that uses FE to hammer blocks automatically. Uses 20 FE a tick by default and takes 200 ticks (10 seconds) to hammer an item with a hammer that has no efficiency.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// 1.20.1 2024-02-01T18:59:58.2832542 Loot Tables
|
||||
// 1.20.1 2024-02-09T12:37:53.8355693 Loot Tables
|
||||
105d8a61ea7145d7798146d385d4aad24fd1588d data/exdeorum/loot_tables/blocks/acacia_barrel.json
|
||||
1e77127a82cbba0937bb02694f65cf1893aeffcb data/exdeorum/loot_tables/blocks/acacia_crucible.json
|
||||
fcc00910a8cc94bed6339d6833fcec53c501a0d7 data/exdeorum/loot_tables/blocks/acacia_sieve.json
|
||||
|
|
@ -51,7 +51,6 @@ b3b8c57f4614b036263f1e107bb1e0acf4a69122 data/exdeorum/loot_tables/blocks/green_
|
|||
32602e363024f1bbd0a174a19c61b4cb0e4f3b2c data/exdeorum/loot_tables/blocks/hellbark_barrel.json
|
||||
cbf36cffd7f38d618435ca03142ded5e74f217aa data/exdeorum/loot_tables/blocks/hellbark_crucible.json
|
||||
bf41c8c33133269ddde2c6b098aca056acd7e4ea data/exdeorum/loot_tables/blocks/hellbark_sieve.json
|
||||
0834fe6d98295ca2ced32a3a50a04de3ae6204e9 data/exdeorum/loot_tables/blocks/infested_leaves.json
|
||||
ce4254c53a4ce6c2712775708415f14e63f21b67 data/exdeorum/loot_tables/blocks/jacaranda_barrel.json
|
||||
b23b0494ef9f535744f7390f74a35527442aee6f data/exdeorum/loot_tables/blocks/jacaranda_crucible.json
|
||||
1817eb94fb9656a3ad853f2cca138c1cd012bd26 data/exdeorum/loot_tables/blocks/jacaranda_sieve.json
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
// 1.20.1 2024-02-07T15:07:17.5326478 ModKit Language: en_us for mod 'exdeorum'
|
||||
313d90779f26fbca4597861071060dba9e94411a assets/exdeorum/lang/en_us.json
|
||||
// 1.20.1 2024-02-09T20:14:05.8728621 ModKit Language: en_us for mod 'exdeorum'
|
||||
43e0f1f023ef626ab7571ad14c1ecdf5cd594823 assets/exdeorum/lang/en_us.json
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// 1.20.1 2024-02-07T21:04:33.4555528 Recipes
|
||||
// 1.20.1 2024-02-09T20:14:05.875864 Recipes
|
||||
e37b64428f17e304e91539ac0513456d7ce40cd1 data/exdeorum/advancements/recipes/building_blocks/sponge.json
|
||||
5ad481a0c376c1a1785a5d3b992064d0ec0bf3b0 data/exdeorum/advancements/recipes/food/end_cake.json
|
||||
25dd027e844a72b03c95dbe5e3c3dd8c738ceb00 data/exdeorum/advancements/recipes/misc/acacia_barrel.json
|
||||
|
|
@ -207,6 +207,19 @@ ba90fbda213e52dc15ea532c8f10c63ea47747de data/exdeorum/recipes/cobblestone.json
|
|||
f6a9036c1bbc4fa0cdc25ef4c851de5ddac0a4ff data/exdeorum/recipes/crook.json
|
||||
ae7e544d3e51182204eeb1efe15079103ea09802 data/exdeorum/recipes/crook/silkworm.json
|
||||
b8636418dc9384bd44313de1d17fd4bbc06c0152 data/exdeorum/recipes/crook/silkworm_bonus.json
|
||||
00b082310773af07d2d418d34c25f5772d0e4a20 data/exdeorum/recipes/crook/string_roll_1.json
|
||||
47dce4f15c91271429cfab63d22ce4d33ff3fa99 data/exdeorum/recipes/crook/string_roll_2.json
|
||||
96f8d146949641588a2cc309e031ac19ed80e041 data/exdeorum/recipes/crucible_heat_source/fire.json
|
||||
e70d081bb3c73fad2e7925b9a6e606f6e4c4a418 data/exdeorum/recipes/crucible_heat_source/lantern.json
|
||||
43a4cc20f18334fc43f35879bc9af381254c5671 data/exdeorum/recipes/crucible_heat_source/lava.json
|
||||
fac62befa53f1a335136c50d24808df52b8a050b data/exdeorum/recipes/crucible_heat_source/lit_campfire.json
|
||||
01c9ed5d8be13335868f9b5ac500425b277c3745 data/exdeorum/recipes/crucible_heat_source/lit_soul_campfire.json
|
||||
77eb7e88dbfedd36935e66b171163cfe642f981b data/exdeorum/recipes/crucible_heat_source/soul_fire.json
|
||||
09735fcbbd7aa4379d87bda8e1a3c776e057d8fc data/exdeorum/recipes/crucible_heat_source/soul_lantern.json
|
||||
c633abee6307560c55a4de010a1a827ef4870b70 data/exdeorum/recipes/crucible_heat_source/soul_torch.json
|
||||
46a18c4e353ef57c4cedb047dc2c66a84338fcf0 data/exdeorum/recipes/crucible_heat_source/soul_wall_torch.json
|
||||
d6996ab8fbd7d4b49a497947c8bab2652d2e665f data/exdeorum/recipes/crucible_heat_source/torch.json
|
||||
85e99f299ad22301b07dc770a981b6d69c6d307a data/exdeorum/recipes/crucible_heat_source/wall_torch.json
|
||||
c81379fe022f3667ce506e4927aac97d1b66999f data/exdeorum/recipes/crystallized_barrel.json
|
||||
77cf611f4e10c507fc4ec116ba0a9d9d1ce58273 data/exdeorum/recipes/crystallized_crucible.json
|
||||
324b6222287940a7fb008b9c6a1e9caecada8af3 data/exdeorum/recipes/crystallized_sieve.json
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@
|
|||
"block.exdeorum.hellbark_crucible": "Hellbark Crucible",
|
||||
"block.exdeorum.hellbark_sieve": "Hellbark Sieve",
|
||||
"block.exdeorum.infested_leaves": "Infested Leaves",
|
||||
"block.exdeorum.infested_leaves.fully_infested": "Fully Infested",
|
||||
"block.exdeorum.jacaranda_barrel": "Jacaranda Barrel",
|
||||
"block.exdeorum.jacaranda_crucible": "Jacaranda Crucible",
|
||||
"block.exdeorum.jacaranda_sieve": "Jacaranda Sieve",
|
||||
|
|
@ -132,6 +133,8 @@
|
|||
"gui.exdeorum.category.barrel_fluid_mixing": "Barrel Fluid Mixing",
|
||||
"gui.exdeorum.category.barrel_fluid_mixing.contents_are_consumed": "Contents are consumed",
|
||||
"gui.exdeorum.category.barrel_mixing": "Barrel Mixing",
|
||||
"gui.exdeorum.category.crook": "Crook",
|
||||
"gui.exdeorum.category.crook.requires_state": "Requires properties:",
|
||||
"gui.exdeorum.category.crucible_heat_source": "Crucible Heat Sources",
|
||||
"gui.exdeorum.category.crucible_heat_source.multiplier": "Melt Rate: %sx",
|
||||
"gui.exdeorum.category.hammer": "Hammer",
|
||||
|
|
|
|||
|
|
@ -1,21 +0,0 @@
|
|||
{
|
||||
"type": "minecraft:block",
|
||||
"pools": [
|
||||
{
|
||||
"bonus_rolls": 0.0,
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"functions": [
|
||||
{
|
||||
"function": "exdeorum:infested_string"
|
||||
}
|
||||
],
|
||||
"name": "minecraft:string"
|
||||
}
|
||||
],
|
||||
"rolls": 1.0
|
||||
}
|
||||
],
|
||||
"random_sequence": "exdeorum:blocks/infested_leaves"
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"type": "exdeorum:crook",
|
||||
"block_predicate": {
|
||||
"block": "exdeorum:infested_leaves",
|
||||
"state": {
|
||||
"fully_infested": "true"
|
||||
}
|
||||
},
|
||||
"chance": 0.4,
|
||||
"result": "minecraft:string"
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"type": "exdeorum:crook",
|
||||
"block_predicate": {
|
||||
"block": "exdeorum:infested_leaves",
|
||||
"state": {
|
||||
"fully_infested": "true"
|
||||
}
|
||||
},
|
||||
"chance": 0.1,
|
||||
"result": "minecraft:string"
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"type": "exdeorum:crucible_heat_source",
|
||||
"block_predicate": {
|
||||
"block": "minecraft:fire"
|
||||
},
|
||||
"heat_value": 5
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"type": "exdeorum:crucible_heat_source",
|
||||
"block_predicate": {
|
||||
"block": "minecraft:lantern"
|
||||
},
|
||||
"heat_value": 1
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"type": "exdeorum:crucible_heat_source",
|
||||
"block_predicate": {
|
||||
"block": "minecraft:lava"
|
||||
},
|
||||
"heat_value": 3
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"type": "exdeorum:crucible_heat_source",
|
||||
"block_predicate": {
|
||||
"block": "minecraft:campfire",
|
||||
"state": {
|
||||
"lit": "true"
|
||||
}
|
||||
},
|
||||
"heat_value": 2
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"type": "exdeorum:crucible_heat_source",
|
||||
"block_predicate": {
|
||||
"block": "minecraft:soul_campfire",
|
||||
"state": {
|
||||
"lit": "true"
|
||||
}
|
||||
},
|
||||
"heat_value": 2
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"type": "exdeorum:crucible_heat_source",
|
||||
"block_predicate": {
|
||||
"block": "minecraft:soul_fire"
|
||||
},
|
||||
"heat_value": 5
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"type": "exdeorum:crucible_heat_source",
|
||||
"block_predicate": {
|
||||
"block": "minecraft:soul_lantern"
|
||||
},
|
||||
"heat_value": 2
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"type": "exdeorum:crucible_heat_source",
|
||||
"block_predicate": {
|
||||
"block": "minecraft:soul_torch"
|
||||
},
|
||||
"heat_value": 2
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"type": "exdeorum:crucible_heat_source",
|
||||
"block_predicate": {
|
||||
"block": "minecraft:soul_wall_torch"
|
||||
},
|
||||
"heat_value": 2
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"type": "exdeorum:crucible_heat_source",
|
||||
"block_predicate": {
|
||||
"block": "minecraft:torch"
|
||||
},
|
||||
"heat_value": 1
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"type": "exdeorum:crucible_heat_source",
|
||||
"block_predicate": {
|
||||
"block": "minecraft:wall_torch"
|
||||
},
|
||||
"heat_value": 1
|
||||
}
|
||||
|
|
@ -18,84 +18,25 @@
|
|||
|
||||
package thedarkcolour.exdeorum.blockentity;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntLinkedOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.CampfireBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import thedarkcolour.exdeorum.recipe.RecipeUtil;
|
||||
import thedarkcolour.exdeorum.recipe.crucible.CrucibleRecipe;
|
||||
import thedarkcolour.exdeorum.registry.EBlockEntities;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class LavaCrucibleBlockEntity extends AbstractCrucibleBlockEntity {
|
||||
public static final Object2IntMap<BlockState> HEAT_REGISTRY = new Object2IntOpenHashMap<>();
|
||||
public static final Object2IntMap<BlockState> KUBEJS_HEAT_VALUES = new Object2IntLinkedOpenHashMap<>();
|
||||
|
||||
static {
|
||||
putDefaultHeatValues();
|
||||
}
|
||||
|
||||
public static void putDefaultHeatValues() {
|
||||
HEAT_REGISTRY.clear();
|
||||
|
||||
putDefaults(HEAT_REGISTRY);
|
||||
|
||||
for (var entry : KUBEJS_HEAT_VALUES.object2IntEntrySet()) {
|
||||
if (entry.getIntValue() <= 0) {
|
||||
HEAT_REGISTRY.removeInt(entry.getKey());
|
||||
} else {
|
||||
HEAT_REGISTRY.put(entry.getKey(), entry.getIntValue());
|
||||
}
|
||||
}
|
||||
|
||||
KUBEJS_HEAT_VALUES.clear();
|
||||
}
|
||||
|
||||
public static void putDefaults(Object2IntMap<BlockState> heatMap) {
|
||||
putAllStates(Blocks.TORCH, 1, heatMap);
|
||||
putAllStates(Blocks.WALL_TORCH, 1, heatMap);
|
||||
putAllStates(Blocks.LANTERN, 1, heatMap);
|
||||
putAllStates(Blocks.SOUL_TORCH, 2, heatMap);
|
||||
putAllStates(Blocks.SOUL_WALL_TORCH, 2, heatMap);
|
||||
putAllStates(Blocks.SOUL_LANTERN, 2, heatMap);
|
||||
putAllStates(Blocks.LAVA, 3, heatMap);
|
||||
putAllStates(Blocks.FIRE, 5, heatMap);
|
||||
putAllStates(Blocks.SOUL_FIRE, 5, heatMap);
|
||||
|
||||
putStates(Blocks.CAMPFIRE, 2, state -> state.getValue(CampfireBlock.LIT), heatMap);
|
||||
putStates(Blocks.SOUL_CAMPFIRE, 2, state -> state.getValue(CampfireBlock.LIT), heatMap);
|
||||
}
|
||||
|
||||
public static void putAllStates(Block block, int heat, Object2IntMap<BlockState> heatMap) {
|
||||
for (var state : block.getStateDefinition().getPossibleStates()) {
|
||||
heatMap.put(state, heat);
|
||||
}
|
||||
}
|
||||
|
||||
public static void putStates(Block block, int heat, Predicate<BlockState> predicate, Object2IntMap<BlockState> heatMap) {
|
||||
for (var state : block.getStateDefinition().getPossibleStates()) {
|
||||
if (predicate.test(state)) {
|
||||
heatMap.put(state, heat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public LavaCrucibleBlockEntity(BlockPos pos, BlockState state) {
|
||||
super(EBlockEntities.LAVA_CRUCIBLE.get(), pos, state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMeltingRate() {
|
||||
BlockState state = this.level.getBlockState(getBlockPos().below());
|
||||
|
||||
return HEAT_REGISTRY.getInt(state);
|
||||
return RecipeUtil.getHeatValue(this.level.getBlockState(getBlockPos().below()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -43,4 +43,5 @@ public class ModIds {
|
|||
public static final String NUCLEARCRAFT_NEOTERIC = "nuclearcraft";
|
||||
public static final String JEI = "jei";
|
||||
public static final String INVENTORY_SORTER = "inventorysorter";
|
||||
public static final String REI_PC = "rei_plugin_compatibilities";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
package thedarkcolour.exdeorum.compat.jade;
|
||||
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import snownee.jade.api.BlockAccessor;
|
||||
|
|
@ -25,6 +26,7 @@ import snownee.jade.api.IBlockComponentProvider;
|
|||
import snownee.jade.api.ITooltip;
|
||||
import snownee.jade.api.config.IPluginConfig;
|
||||
import thedarkcolour.exdeorum.blockentity.InfestedLeavesBlockEntity;
|
||||
import thedarkcolour.exdeorum.data.TranslationKeys;
|
||||
|
||||
enum InfestedLeavesComponentProvider implements IBlockComponentProvider {
|
||||
INSTANCE;
|
||||
|
|
@ -33,7 +35,11 @@ enum InfestedLeavesComponentProvider implements IBlockComponentProvider {
|
|||
public void appendTooltip(ITooltip tooltip, BlockAccessor blockAccessor, IPluginConfig config) {
|
||||
if (blockAccessor.getBlockEntity() instanceof InfestedLeavesBlockEntity leaves) {
|
||||
int progress = (int) (leaves.getProgress() * 100.0f);
|
||||
tooltip.add(Component.literal("Progress: ").append(Component.literal(progress + "%")));
|
||||
if (progress == 100) {
|
||||
tooltip.add(Component.translatable(TranslationKeys.INFESTED_LEAVES_FULLY_INFESTED));
|
||||
} else {
|
||||
tooltip.add(Component.literal("Progress: ").append(Component.literal(progress + "%")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,13 +24,20 @@ import com.mojang.blaze3d.vertex.BufferBuilder;
|
|||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.Tesselator;
|
||||
import com.mojang.math.Axis;
|
||||
import me.shedaniel.rei.api.client.view.ViewSearchBuilder;
|
||||
import me.shedaniel.rei.jeicompat.JEIPluginDetector;
|
||||
import mezz.jei.api.ingredients.IIngredientRenderer;
|
||||
import mezz.jei.api.ingredients.IIngredientType;
|
||||
import mezz.jei.api.ingredients.ITypedIngredient;
|
||||
import mezz.jei.api.recipe.IFocusFactory;
|
||||
import mezz.jei.api.recipe.RecipeIngredientRole;
|
||||
import mezz.jei.api.runtime.IIngredientManager;
|
||||
import mezz.jei.api.runtime.IRecipesGui;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.CrashReport;
|
||||
import net.minecraft.CrashReportCategory;
|
||||
import net.minecraft.ReportedException;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.Font;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.client.renderer.ItemBlockRenderTypes;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
|
|
@ -55,19 +62,27 @@ import net.minecraft.world.level.block.state.BlockState;
|
|||
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.world.level.material.Fluids;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.fml.ModList;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Vector3f;
|
||||
import thedarkcolour.exdeorum.compat.ModIds;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
class ClientJeiUtil {
|
||||
private static final FluidState EMPTY = Fluids.EMPTY.defaultFluidState();
|
||||
private static final BlockState AIR = Blocks.AIR.defaultBlockState();
|
||||
|
||||
// From https://github.com/The-Aether-Team/Nitrogen/blob/1.20.1-develop/src/main/java/com/aetherteam/nitrogen/integration/jei/BlockStateRenderer.java
|
||||
private static final Vector3f L1 = new Vector3f(0.4F, 0.0F, 1.0F).normalize();
|
||||
private static final Vector3f L2 = new Vector3f(-0.4F, 1.0F, -0.2F).normalize();
|
||||
|
||||
// https://github.com/way2muchnoise/JustEnoughResources/blob/89ee40ff068c8d6eb6ab103f76381445691cffc9/Common/src/main/java/jeresources/util/RenderHelper.java#L100
|
||||
static void renderBlock(GuiGraphics guiGraphics, BlockState block, float x, float y, float z, float scale) {
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
static void renderBlock(GuiGraphics guiGraphics, BlockState block, float x, float y, float z, float scale, RenderBlockFn renderFunction) {
|
||||
PoseStack poseStack = guiGraphics.pose();
|
||||
|
||||
poseStack.translate(x, y, z);
|
||||
|
|
@ -85,9 +100,10 @@ class ClientJeiUtil {
|
|||
FluidState fluidState = block.getFluidState();
|
||||
|
||||
if (fluidState.isEmpty()) {
|
||||
MultiBufferSource.BufferSource buffers = mc.renderBuffers().bufferSource();
|
||||
MultiBufferSource.BufferSource buffers = Minecraft.getInstance().renderBuffers().bufferSource();
|
||||
|
||||
mc.getBlockRenderer().renderSingleBlock(block, poseStack, buffers, 15728880, OverlayTexture.NO_OVERLAY);
|
||||
RenderSystem.setupGui3DDiffuseLighting(L1, L2);
|
||||
renderFunction.renderBlock(block, poseStack, buffers);
|
||||
|
||||
buffers.endBatch();
|
||||
} else {
|
||||
|
|
@ -104,7 +120,7 @@ class ClientJeiUtil {
|
|||
|
||||
Dummy.tempState = block;
|
||||
Dummy.tempFluid = fluidState;
|
||||
mc.getBlockRenderer().renderLiquid(BlockPos.ZERO, Dummy.INSTANCE, builder, block, block.getFluidState());
|
||||
Minecraft.getInstance().getBlockRenderer().renderLiquid(BlockPos.ZERO, Dummy.INSTANCE, builder, block, block.getFluidState());
|
||||
Dummy.tempFluid = EMPTY;
|
||||
Dummy.tempState = AIR;
|
||||
|
||||
|
|
@ -174,6 +190,35 @@ class ClientJeiUtil {
|
|||
RenderSystem.disableBlend();
|
||||
}
|
||||
|
||||
// Required due to broken JEI implementation in REI plugin compatibility
|
||||
public static <T> void checkTypedIngredient(IIngredientManager manager, IIngredientType<T> ingredientType, T uncheckedIngredient, Consumer<ITypedIngredient<T>> action) {
|
||||
if ((uncheckedIngredient instanceof ItemStack stack && !stack.isEmpty()) || (uncheckedIngredient instanceof FluidStack fluidStack && !fluidStack.isEmpty())) {
|
||||
manager.createTypedIngredient(ingredientType, uncheckedIngredient).ifPresent(action);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> void showRecipes(IFocusFactory focusFactory, ITypedIngredient<T> ingredient) {
|
||||
if (Minecraft.getInstance().screen instanceof IRecipesGui recipesGui) {
|
||||
recipesGui.show(focusFactory.createFocus(RecipeIngredientRole.OUTPUT, ingredient));
|
||||
} else if (ModList.get().isLoaded(ModIds.REI_PC)) {
|
||||
ViewSearchBuilder.builder().addRecipesFor(JEIPluginDetector.unwrapStack(ingredient)).open();
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> void showUsages(IFocusFactory focusFactory, ITypedIngredient<T> ingredient) {
|
||||
if (Minecraft.getInstance().screen instanceof IRecipesGui recipesGui) {
|
||||
// input + catalyst
|
||||
recipesGui.show(List.of(focusFactory.createFocus(RecipeIngredientRole.INPUT, ingredient), focusFactory.createFocus(RecipeIngredientRole.CATALYST, ingredient)));
|
||||
} else if (ModList.get().isLoaded(ModIds.REI_PC)) {
|
||||
ViewSearchBuilder.builder().addUsagesFor(JEIPluginDetector.unwrapStack(ingredient)).open();
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
interface RenderBlockFn {
|
||||
void renderBlock(BlockState block, PoseStack poseStack, MultiBufferSource.BufferSource buffers);
|
||||
}
|
||||
|
||||
private enum Dummy implements BlockAndTintGetter {
|
||||
INSTANCE;
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@
|
|||
|
||||
package thedarkcolour.exdeorum.compat.jei;
|
||||
|
||||
import com.mojang.blaze3d.platform.InputConstants;
|
||||
import mezz.jei.api.constants.VanillaTypes;
|
||||
import mezz.jei.api.gui.builder.IRecipeLayoutBuilder;
|
||||
import mezz.jei.api.gui.drawable.IDrawable;
|
||||
import mezz.jei.api.gui.ingredient.IRecipeSlotsView;
|
||||
|
|
@ -29,12 +31,17 @@ import mezz.jei.api.recipe.RecipeIngredientRole;
|
|||
import mezz.jei.api.recipe.RecipeType;
|
||||
import mezz.jei.api.recipe.category.IRecipeCategory;
|
||||
import mezz.jei.api.runtime.IIngredientManager;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import net.minecraftforge.client.RenderTypeHelper;
|
||||
import net.minecraftforge.client.model.data.ModelData;
|
||||
import thedarkcolour.exdeorum.data.TranslationKeys;
|
||||
import thedarkcolour.exdeorum.registry.EBlocks;
|
||||
import thedarkcolour.exdeorum.registry.EItems;
|
||||
|
|
@ -43,7 +50,7 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
public class CrookCategory implements IRecipeCategory<CrookJeiRecipe> {
|
||||
private static final Component REQUIRES_CERTAIN_STATE = Component.translatable(TranslationKeys.CROOK_CATEGORY_REQUIRES_STATE);
|
||||
private static final Component REQUIRES_CERTAIN_STATE = Component.translatable(TranslationKeys.CROOK_CATEGORY_REQUIRES_STATE).withStyle(ChatFormatting.GRAY);
|
||||
|
||||
private final IDrawable background;
|
||||
private final IDrawable icon;
|
||||
|
|
@ -93,32 +100,47 @@ public class CrookCategory implements IRecipeCategory<CrookJeiRecipe> {
|
|||
@Override
|
||||
public void setRecipe(IRecipeLayoutBuilder builder, CrookJeiRecipe recipe, IFocusGroup focuses) {
|
||||
recipe.addIngredients(builder);
|
||||
builder.addSlot(RecipeIngredientRole.OUTPUT, 80, 18).addItemStack(new ItemStack(recipe.result));
|
||||
builder.addSlot(RecipeIngredientRole.OUTPUT, 80, 18).addItemStack(new ItemStack(recipe.result)).addTooltipCallback((recipeSlotView, tooltip) -> {
|
||||
tooltip.add(SieveCategory.formatChance(recipe.chance));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(CrookJeiRecipe recipe, IRecipeSlotsView recipeSlotsView, GuiGraphics graphics, double mouseX, double mouseY) {
|
||||
this.timer.onDraw();
|
||||
|
||||
this.arrow.draw(graphics, 52, 18);
|
||||
this.arrow.draw(graphics, 50, 18);
|
||||
this.slot.draw(graphics, 79, 17);
|
||||
|
||||
BlockState state = this.timer.getCycledItem(recipe.states);
|
||||
if (state.is(EBlocks.INFESTED_LEAVES.get())) {
|
||||
state = Blocks.OAK_LEAVES.defaultBlockState();
|
||||
ClientJeiUtil.renderBlock(graphics, state, 28, 18, 10, 20f, (block, poseStack, buffers) -> {
|
||||
var blockRenderer = Minecraft.getInstance().getBlockRenderer();
|
||||
var bakedmodel = blockRenderer.getBlockModel(state);
|
||||
|
||||
for (var renderType : bakedmodel.getRenderTypes(state, RandomSource.create(42), ModelData.EMPTY)) {
|
||||
blockRenderer.getModelRenderer().renderModel(poseStack.last(), buffers.getBuffer(RenderTypeHelper.getEntityRenderType(renderType, false)), state, bakedmodel, 1f, 1f, 1f, 15728880, OverlayTexture.NO_OVERLAY, ModelData.EMPTY, renderType);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
ClientJeiUtil.renderBlock(graphics, state, 28, 18, 10, 20f, (block, poseStack, buffers) -> {
|
||||
Minecraft.getInstance().getBlockRenderer().renderSingleBlock(block, poseStack, buffers, 15728880, OverlayTexture.NO_OVERLAY);
|
||||
});
|
||||
}
|
||||
ClientJeiUtil.renderBlock(graphics, state, 28, 18, 10, 20F);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Component> getTooltipStrings(CrookJeiRecipe recipe, IRecipeSlotsView recipeSlotsView, double mouseX, double mouseY) {
|
||||
if (44.0 < mouseX && mouseX < 76.0 && 16 < mouseY && mouseY < 48) {
|
||||
if (12 < mouseX && mouseX < 44 && 10 < mouseY && mouseY < 42) {
|
||||
var block = this.timer.getCycledItem(recipe.states).getBlock();
|
||||
var modId = ForgeRegistries.BLOCKS.getKey(block).getNamespace();
|
||||
var modId = BuiltInRegistries.BLOCK.getKey(block).getNamespace();
|
||||
var tooltip = new ArrayList<Component>();
|
||||
tooltip.add(Component.translatable(block.getDescriptionId()));
|
||||
if (recipe.getClass() == CrookJeiRecipe.StatesRecipe.class) {
|
||||
if (recipe instanceof CrookJeiRecipe.StatesRecipe statesRecipe && !statesRecipe.requirements.isEmpty()) {
|
||||
tooltip.add(REQUIRES_CERTAIN_STATE);
|
||||
tooltip.addAll(statesRecipe.requirements);
|
||||
} else if (recipe instanceof CrookJeiRecipe.TagRecipe tagRecipe) {
|
||||
tooltip.add(Component.literal("#" + tagRecipe.tag.location()).withStyle(ChatFormatting.GRAY));
|
||||
}
|
||||
tooltip.add(Component.literal(this.modIdHelper.getFormattedModNameForModId(modId)));
|
||||
return tooltip;
|
||||
|
|
@ -126,4 +148,24 @@ public class CrookCategory implements IRecipeCategory<CrookJeiRecipe> {
|
|||
|
||||
return List.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleInput(CrookJeiRecipe recipe, double mouseX, double mouseY, InputConstants.Key input) {
|
||||
if (input.getType() == InputConstants.Type.MOUSE && (input.getValue() == InputConstants.MOUSE_BUTTON_LEFT || input.getValue() == InputConstants.MOUSE_BUTTON_RIGHT)) {
|
||||
if (12 < mouseX && mouseX < 44 && 10 < mouseY && mouseY < 42) {
|
||||
var block = this.timer.getCycledItem(recipe.states).getBlock();
|
||||
|
||||
ClientJeiUtil.checkTypedIngredient(this.ingredientManager, VanillaTypes.ITEM_STACK, new ItemStack(block.asItem()), ingredient -> {
|
||||
if (input.getValue() == InputConstants.MOUSE_BUTTON_LEFT) {
|
||||
ClientJeiUtil.showRecipes(this.focusFactory, ingredient);
|
||||
} else if (input.getValue() == InputConstants.MOUSE_BUTTON_RIGHT) {
|
||||
ClientJeiUtil.showUsages(this.focusFactory, ingredient);
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,22 +19,26 @@
|
|||
package thedarkcolour.exdeorum.compat.jei;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.gson.JsonObject;
|
||||
import mezz.jei.api.gui.builder.IRecipeLayoutBuilder;
|
||||
import mezz.jei.api.recipe.RecipeIngredientRole;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import thedarkcolour.exdeorum.recipe.BlockPredicate;
|
||||
import thedarkcolour.exdeorum.recipe.crook.CrookRecipe;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public sealed abstract class CrookJeiRecipe {
|
||||
public final List<BlockState> states;
|
||||
|
|
@ -51,7 +55,7 @@ public sealed abstract class CrookJeiRecipe {
|
|||
|
||||
static CrookJeiRecipe create(CrookRecipe recipe) {
|
||||
if (recipe.blockPredicate() instanceof BlockPredicate.BlockStatePredicate state) {
|
||||
return new StatesRecipe(state.possibleStates().collect(Collectors.toList()), recipe.result(), recipe.chance());
|
||||
return new StatesRecipe(state, state.possibleStates().filter(blockState -> !blockState.hasProperty(BlockStateProperties.WATERLOGGED) || !blockState.getValue(BlockStateProperties.WATERLOGGED)).toList(), recipe.result(), recipe.chance());
|
||||
} else if (recipe.blockPredicate() instanceof BlockPredicate.SingleBlockPredicate block) {
|
||||
return new BlockRecipe(block.block(), recipe.result(), recipe.chance());
|
||||
} else if (recipe.blockPredicate() instanceof BlockPredicate.TagPredicate tag) {
|
||||
|
|
@ -71,26 +75,38 @@ public sealed abstract class CrookJeiRecipe {
|
|||
|
||||
sealed static class StatesRecipe extends CrookJeiRecipe {
|
||||
private final List<ItemStack> itemIngredients;
|
||||
public final List<Component> requirements;
|
||||
|
||||
StatesRecipe(List<BlockState> states, Item result, float chance) {
|
||||
StatesRecipe(@Nullable BlockPredicate.BlockStatePredicate predicate, List<BlockState> states, Item result, float chance) {
|
||||
super(states, result, chance);
|
||||
ImmutableList.Builder<ItemStack> temp = ImmutableList.builder();
|
||||
ImmutableList.Builder<ItemStack> itemIngredients = ImmutableList.builder();
|
||||
|
||||
var blocks = new HashSet<Block>();
|
||||
|
||||
for (var state : states) {
|
||||
for (var state : this.states) {
|
||||
var block = state.getBlock();
|
||||
|
||||
if (blocks.add(block)) {
|
||||
var item = block.asItem();
|
||||
|
||||
if (item != Items.AIR) {
|
||||
temp.add(new ItemStack(item));
|
||||
itemIngredients.add(new ItemStack(item));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.itemIngredients = temp.build();
|
||||
this.itemIngredients = itemIngredients.build();
|
||||
|
||||
ImmutableList.Builder<Component> requirements = ImmutableList.builder();
|
||||
if (predicate != null) {
|
||||
var json = predicate.properties().serializeToJson();
|
||||
if (json instanceof JsonObject obj) {
|
||||
for (var entry : obj.entrySet()) {
|
||||
requirements.add(Component.literal(" " + entry.getKey() + "=" + entry.getValue().toString()).withStyle(ChatFormatting.GRAY));
|
||||
}
|
||||
}
|
||||
}
|
||||
this.requirements = requirements.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -105,7 +121,7 @@ public sealed abstract class CrookJeiRecipe {
|
|||
public final TagKey<Block> tag;
|
||||
|
||||
public TagRecipe(TagKey<Block> tag, List<BlockState> states, Item result, float chance) {
|
||||
super(states, result, chance);
|
||||
super(null, states, result, chance);
|
||||
this.tag = tag;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,9 +31,9 @@ import mezz.jei.api.recipe.RecipeIngredientRole;
|
|||
import mezz.jei.api.recipe.RecipeType;
|
||||
import mezz.jei.api.recipe.category.IRecipeCategory;
|
||||
import mezz.jei.api.runtime.IIngredientManager;
|
||||
import mezz.jei.api.runtime.IRecipesGui;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.TooltipFlag;
|
||||
|
|
@ -103,7 +103,9 @@ class CrucibleHeatSourcesCategory implements IRecipeCategory<CrucibleHeatSourceR
|
|||
|
||||
graphics.drawString(font, volumeLabel, 60 - font.width(volumeLabel) / 2, 5, 0xff808080, false);
|
||||
|
||||
ClientJeiUtil.renderBlock(graphics, recipe.blockState(), 60, 24, 10, 20F);
|
||||
ClientJeiUtil.renderBlock(graphics, recipe.blockState(), 60, 24, 10, 20F, (block, poseStack, buffers) -> {
|
||||
Minecraft.getInstance().getBlockRenderer().renderSingleBlock(block, poseStack, buffers, 15728880, OverlayTexture.NO_OVERLAY);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -113,7 +115,6 @@ class CrucibleHeatSourcesCategory implements IRecipeCategory<CrucibleHeatSourceR
|
|||
var tooltip = this.ingredientManager.getIngredientRenderer(recipe.ingredientType()).getTooltip(recipe.ingredient(), Minecraft.getInstance().options.advancedItemTooltips ? TooltipFlag.ADVANCED : TooltipFlag.NORMAL);
|
||||
return this.modIdHelper.addModNameToIngredientTooltip(tooltip, recipe.ingredient(), this.ingredientManager.getIngredientHelper(recipe.ingredientType()));
|
||||
} else {
|
||||
|
||||
var block = recipe.blockState().getBlock();
|
||||
var modId = ForgeRegistries.BLOCKS.getKey(block).getNamespace();
|
||||
return List.of(Component.translatable(block.getDescriptionId()), Component.literal(this.modIdHelper.getFormattedModNameForModId(modId)));
|
||||
|
|
@ -128,14 +129,11 @@ class CrucibleHeatSourcesCategory implements IRecipeCategory<CrucibleHeatSourceR
|
|||
if (input.getType() == InputConstants.Type.MOUSE && (input.getValue() == InputConstants.MOUSE_BUTTON_LEFT || input.getValue() == InputConstants.MOUSE_BUTTON_RIGHT)) {
|
||||
if (44.0 < mouseX && mouseX < 76.0 && 16 < mouseY && mouseY < 48) {
|
||||
if (recipe.ingredientType() != null) {
|
||||
this.ingredientManager.createTypedIngredient(recipe.ingredientType(), recipe.ingredient()).ifPresent(ingredient -> {
|
||||
if (Minecraft.getInstance().screen instanceof IRecipesGui recipesGui) {
|
||||
if (input.getValue() == InputConstants.MOUSE_BUTTON_LEFT) {
|
||||
recipesGui.show(this.focusFactory.createFocus(RecipeIngredientRole.OUTPUT, ingredient));
|
||||
} else {
|
||||
// INPUT + CATALYST
|
||||
recipesGui.show(List.of(this.focusFactory.createFocus(RecipeIngredientRole.CATALYST, ingredient), this.focusFactory.createFocus(RecipeIngredientRole.INPUT, ingredient)));
|
||||
}
|
||||
ClientJeiUtil.checkTypedIngredient(this.ingredientManager, recipe.ingredientType(), recipe.ingredient(), ingredient -> {
|
||||
if (input.getValue() == InputConstants.MOUSE_BUTTON_LEFT) {
|
||||
ClientJeiUtil.showRecipes(this.focusFactory, ingredient);
|
||||
} else if (input.getValue() == InputConstants.MOUSE_BUTTON_RIGHT) {
|
||||
ClientJeiUtil.showUsages(this.focusFactory, ingredient);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@ import net.minecraft.world.level.block.LiquidBlock;
|
|||
import net.minecraft.world.level.block.WallTorchBlock;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import thedarkcolour.exdeorum.ExDeorum;
|
||||
import thedarkcolour.exdeorum.blockentity.LavaCrucibleBlockEntity;
|
||||
import thedarkcolour.exdeorum.client.screen.MechanicalHammerScreen;
|
||||
import thedarkcolour.exdeorum.client.screen.MechanicalSieveScreen;
|
||||
import thedarkcolour.exdeorum.compat.CompatHelper;
|
||||
|
|
@ -55,7 +54,6 @@ import thedarkcolour.exdeorum.recipe.RecipeUtil;
|
|||
import thedarkcolour.exdeorum.recipe.barrel.BarrelCompostRecipe;
|
||||
import thedarkcolour.exdeorum.recipe.barrel.BarrelFluidMixingRecipe;
|
||||
import thedarkcolour.exdeorum.recipe.barrel.BarrelMixingRecipe;
|
||||
import thedarkcolour.exdeorum.recipe.crook.CrookRecipe;
|
||||
import thedarkcolour.exdeorum.recipe.crucible.CrucibleRecipe;
|
||||
import thedarkcolour.exdeorum.recipe.hammer.HammerRecipe;
|
||||
import thedarkcolour.exdeorum.registry.EBlocks;
|
||||
|
|
@ -202,7 +200,7 @@ public class ExDeorumJeiPlugin implements IModPlugin {
|
|||
|
||||
private static void addCrucibleHeatSources(IRecipeRegistration registration) {
|
||||
var values = new Object2IntOpenHashMap<Block>();
|
||||
for (var entry : LavaCrucibleBlockEntity.HEAT_REGISTRY.object2IntEntrySet()) {
|
||||
for (var entry : RecipeUtil.getHeatSources()) {
|
||||
var state = entry.getKey();
|
||||
var block = state.getBlock();
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import mezz.jei.api.recipe.category.IRecipeCategory;
|
|||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.storage.loot.providers.number.BinomialDistributionGenerator;
|
||||
import net.minecraft.world.level.storage.loot.providers.number.ConstantValue;
|
||||
|
|
@ -104,6 +105,13 @@ class SieveCategory implements IRecipeCategory<GroupedSieveRecipe> {
|
|||
}
|
||||
}
|
||||
|
||||
// Takes a decimal probability and returns a user-friendly percentage value
|
||||
// todo move into JeiUtil
|
||||
public static Component formatChance(double probability) {
|
||||
var chance = FORMATTER.format(probability * 100);
|
||||
return Component.translatable(TranslationKeys.SIEVE_RECIPE_CHANCE, chance).withStyle(ChatFormatting.GRAY);
|
||||
}
|
||||
|
||||
public static void addTooltips(IRecipeSlotBuilder slot, boolean byHandOnly, NumberProvider provider) {
|
||||
var tooltipLines = new ImmutableList.Builder<Component>();
|
||||
|
||||
|
|
@ -113,8 +121,8 @@ class SieveCategory implements IRecipeCategory<GroupedSieveRecipe> {
|
|||
}
|
||||
if (provider instanceof BinomialDistributionGenerator binomial) {
|
||||
if (binomial.n instanceof ConstantValue constant && constant.value == 1) {
|
||||
var chance = FORMATTER.format(RecipeUtil.getExpectedValue(binomial.p) * 100);
|
||||
tooltipLines.add(Component.translatable(TranslationKeys.SIEVE_RECIPE_CHANCE, chance).withStyle(ChatFormatting.GRAY));
|
||||
var chanceLabel = formatChance(RecipeUtil.getExpectedValue(binomial.p));
|
||||
tooltipLines.add(chanceLabel);
|
||||
} else {
|
||||
addAvgOutput(tooltipLines, RecipeUtil.getExpectedValue(provider));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,18 +19,29 @@
|
|||
package thedarkcolour.exdeorum.compat.kubejs;
|
||||
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import dev.latvian.mods.kubejs.bindings.event.ServerEvents;
|
||||
import dev.latvian.mods.kubejs.recipe.RecipesEventJS;
|
||||
import dev.latvian.mods.kubejs.recipe.ReplacementMatch;
|
||||
import dev.latvian.mods.kubejs.recipe.filter.RecipeFilter;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||
import dev.latvian.mods.kubejs.script.ScriptType;
|
||||
import dev.latvian.mods.rhino.util.HideFromJS;
|
||||
import net.minecraft.advancements.critereon.StatePropertiesPredicate;
|
||||
import net.minecraft.commands.arguments.blocks.BlockStateParser;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.util.StringRepresentable;
|
||||
import net.minecraft.world.item.crafting.RecipeType;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.Property;
|
||||
import net.minecraftforge.registries.RegistryObject;
|
||||
import thedarkcolour.exdeorum.ExDeorum;
|
||||
import thedarkcolour.exdeorum.blockentity.LavaCrucibleBlockEntity;
|
||||
import thedarkcolour.exdeorum.recipe.BlockPredicate;
|
||||
import thedarkcolour.exdeorum.recipe.crucible.FinishedCrucibleHeatRecipe;
|
||||
import thedarkcolour.exdeorum.registry.ERecipeTypes;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
class ExDeorumKubeJsBindings {
|
||||
static {
|
||||
|
|
@ -47,33 +58,53 @@ class ExDeorumKubeJsBindings {
|
|||
}
|
||||
|
||||
// This method previously accepted a BlockState, which made it impossible to call through KubeJS.
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public void setCrucibleHeatValueForState(String stateString, int value) {
|
||||
try {
|
||||
LavaCrucibleBlockEntity.KUBEJS_HEAT_VALUES.put(BlockStateParser.parseForBlock(BuiltInRegistries.BLOCK.asLookup(), stateString, false).blockState(), value);
|
||||
} catch (CommandSyntaxException exception) {
|
||||
// Throw a more appropriate exception.
|
||||
throw new IllegalArgumentException("Failed to parse BlockState string \"" + stateString + "\"");
|
||||
}
|
||||
}
|
||||
|
||||
public void setCrucibleHeatValueForBlock(Block block, int value) {
|
||||
for (var state : block.getStateDefinition().getPossibleStates()) {
|
||||
LavaCrucibleBlockEntity.KUBEJS_HEAT_VALUES.put(state, value);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeDefaultSieveRecipes(RecipesEventJS recipesEvent) {
|
||||
recipesEvent.remove(r -> {
|
||||
return r.kjs$getType().equals(ERecipeTypes.SIEVE.getId()) && r.kjs$getOrCreateId().getNamespace().equals(ExDeorum.ID);
|
||||
onRecipesEvent(event -> {
|
||||
try {
|
||||
var state = BlockStateParser.parseForBlock(BuiltInRegistries.BLOCK.asLookup(), stateString, false).blockState();
|
||||
var properties = StatePropertiesPredicate.Builder.properties();
|
||||
for (Property prop : state.getProperties()) {
|
||||
bypassTypeChecking(properties, prop, state);
|
||||
}
|
||||
event.custom(new FinishedCrucibleHeatRecipe(null, BlockPredicate.blockState(state.getBlock(), properties.build()), value).serializeRecipe());
|
||||
} catch (CommandSyntaxException exception) {
|
||||
// Throw a more appropriate exception.
|
||||
throw new IllegalArgumentException("Failed to parse BlockState string \"" + stateString + "\"");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// not the most elegant solution, but if it works, it works
|
||||
@HideFromJS
|
||||
private static <T extends Comparable<T>> void bypassTypeChecking(StatePropertiesPredicate.Builder properties, Property<T> prop, BlockState state) {
|
||||
properties.hasProperty(prop, prop.getName(state.getValue(prop)));
|
||||
}
|
||||
|
||||
@SuppressWarnings("DataFlowIssue")
|
||||
public void setCrucibleHeatValueForBlock(Block block, int value) {
|
||||
onRecipesEvent(event -> {
|
||||
event.custom(new FinishedCrucibleHeatRecipe(null, BlockPredicate.singleBlock(block), value).serializeRecipe());
|
||||
});
|
||||
}
|
||||
|
||||
public void removeDefaultSieveRecipes(RecipesEventJS recipesEvent) {
|
||||
removeDefaultRecipes(recipesEvent, ERecipeTypes.SIEVE);
|
||||
}
|
||||
|
||||
public void removeDefaultHeatSources() {
|
||||
var map = new Object2IntOpenHashMap<BlockState>();
|
||||
LavaCrucibleBlockEntity.putDefaults(map);
|
||||
for (var key : map.keySet()) {
|
||||
LavaCrucibleBlockEntity.KUBEJS_HEAT_VALUES.put(key, 0);
|
||||
}
|
||||
onRecipesEvent(event -> removeDefaultRecipes(event, ERecipeTypes.CRUCIBLE_HEAT_SOURCE));
|
||||
}
|
||||
|
||||
@HideFromJS
|
||||
private static void removeDefaultRecipes(RecipesEventJS event, RegistryObject<? extends RecipeType<?>> recipeType) {
|
||||
event.remove(r -> r.kjs$getType().equals(recipeType.getId()) && r.kjs$getOrCreateId().getNamespace().equals(ExDeorum.ID));
|
||||
}
|
||||
|
||||
@HideFromJS
|
||||
private static void onRecipesEvent(Consumer<RecipesEventJS> action) {
|
||||
ServerEvents.RECIPES.listenJava(ScriptType.SERVER, null, jsEvent -> {
|
||||
action.accept((RecipesEventJS) jsEvent);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,13 +19,9 @@
|
|||
package thedarkcolour.exdeorum.compat.top;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import mcjty.theoneprobe.api.CompoundText;
|
||||
import mcjty.theoneprobe.api.ElementAlignment;
|
||||
import mcjty.theoneprobe.api.IProbeHitData;
|
||||
import mcjty.theoneprobe.api.IProbeInfo;
|
||||
import mcjty.theoneprobe.api.IProbeInfoProvider;
|
||||
import mcjty.theoneprobe.api.ProbeMode;
|
||||
import mcjty.theoneprobe.api.TextStyleClass;
|
||||
import kroppeb.stareval.element.token.BinaryOperatorToken;
|
||||
import mcjty.theoneprobe.api.*;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
|
|
@ -37,6 +33,7 @@ import thedarkcolour.exdeorum.blockentity.AbstractCrucibleBlockEntity;
|
|||
import thedarkcolour.exdeorum.blockentity.BarrelBlockEntity;
|
||||
import thedarkcolour.exdeorum.blockentity.InfestedLeavesBlockEntity;
|
||||
import thedarkcolour.exdeorum.blockentity.SieveBlockEntity;
|
||||
import thedarkcolour.exdeorum.data.TranslationKeys;
|
||||
import thedarkcolour.exdeorum.registry.EBlocks;
|
||||
|
||||
public class ExDeorumInfoProvider implements IProbeInfoProvider {
|
||||
|
|
@ -61,7 +58,11 @@ public class ExDeorumInfoProvider implements IProbeInfoProvider {
|
|||
if (volume == 1000 || barrel.isBrewing()) {
|
||||
int progress = (int) (barrel.progress * 100.0f);
|
||||
|
||||
info.text(CompoundText.create().style(TextStyleClass.LABEL).text("Progress: ").style(TextStyleClass.WARNING).text(progress + "%"));
|
||||
if (progress == 100) {
|
||||
info.text(Component.translatable(TranslationKeys.INFESTED_LEAVES_FULLY_INFESTED).withStyle(ChatFormatting.GRAY));
|
||||
} else {
|
||||
info.text(CompoundText.create().style(TextStyleClass.LABEL).text("Progress: ").style(TextStyleClass.WARNING).text(progress + "%"));
|
||||
}
|
||||
} else if (volume > 0) {
|
||||
int volumePercent = (int) (volume / 10.0f);
|
||||
|
||||
|
|
|
|||
|
|
@ -136,7 +136,6 @@ public class EConfig {
|
|||
public final IntValue mechanicalHammerEnergyStorage;
|
||||
public final IntValue mechanicalHammerEnergyConsumption;
|
||||
public final IntValue sieveIntervalTicks;
|
||||
public final DoubleValue infestedLeavesStringChance;
|
||||
|
||||
public Server(ForgeConfigSpec.Builder builder) {
|
||||
builder.comment("Server configuration for Ex Deorum").push("server");
|
||||
|
|
@ -192,9 +191,6 @@ public class EConfig {
|
|||
this.sieveIntervalTicks = builder
|
||||
.comment("The minimum number of ticks a player must wait between two sifting operations. Only affects sifting by hand. 0 means no limit.")
|
||||
.defineInRange("sieve_interval", 1, 0, Integer.MAX_VALUE);
|
||||
this.infestedLeavesStringChance = builder
|
||||
.comment("The chance for infested leaves to drop string. 0 means infested leaves never drop string, 1 means infested leaves always drop string.")
|
||||
.defineInRange("infested_leaves_string_chance", 0.4, 0.0, 1.0);
|
||||
builder.pop();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ import net.minecraft.world.level.storage.loot.LootTable;
|
|||
import net.minecraft.world.level.storage.loot.entries.LootItem;
|
||||
import net.minecraft.world.level.storage.loot.providers.number.ConstantValue;
|
||||
import thedarkcolour.exdeorum.ExDeorum;
|
||||
import thedarkcolour.exdeorum.loot.InfestedStringFunction;
|
||||
import thedarkcolour.exdeorum.block.MechanicalHammerBlock;
|
||||
import thedarkcolour.exdeorum.loot.MachineLootFunction;
|
||||
import thedarkcolour.exdeorum.registry.EBlocks;
|
||||
import thedarkcolour.exdeorum.registry.EItems;
|
||||
|
|
@ -54,21 +54,16 @@ class BlockLoot extends BlockLootSubProvider {
|
|||
}
|
||||
});
|
||||
|
||||
add(EBlocks.INFESTED_LEAVES.get(), LootTable.lootTable()
|
||||
.withPool(LootPool.lootPool()
|
||||
.setRolls(ConstantValue.exactly(1))
|
||||
.add(LootItem.lootTableItem(Items.STRING)
|
||||
.apply(InfestedStringFunction.infestedString()))));
|
||||
// see createSingleItemTable() for reference
|
||||
add(EBlocks.MECHANICAL_SIEVE.get(), LootTable.lootTable()
|
||||
.withPool(applyExplosionCondition(EItems.MECHANICAL_SIEVE.get(), LootPool.lootPool()
|
||||
machineDrop(EBlocks.MECHANICAL_HAMMER.get());
|
||||
machineDrop(EBlocks.MECHANICAL_SIEVE.get());
|
||||
}
|
||||
|
||||
// see createSingleItemTable() for reference
|
||||
private void machineDrop(Block machine) {
|
||||
add(machine, LootTable.lootTable()
|
||||
.withPool(applyExplosionCondition(machine, LootPool.lootPool()
|
||||
.setRolls(ConstantValue.exactly(1.0F))
|
||||
.add(LootItem.lootTableItem(EItems.MECHANICAL_SIEVE.get())
|
||||
.apply(MachineLootFunction.machineLoot())))));
|
||||
add(EBlocks.MECHANICAL_HAMMER.get(), LootTable.lootTable()
|
||||
.withPool(applyExplosionCondition(EItems.MECHANICAL_HAMMER.get(), LootPool.lootPool()
|
||||
.setRolls(ConstantValue.exactly(1.0F))
|
||||
.add(LootItem.lootTableItem(EItems.MECHANICAL_HAMMER.get())
|
||||
.add(LootItem.lootTableItem(machine)
|
||||
.apply(MachineLootFunction.machineLoot())))));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@ class English {
|
|||
english.add(TranslationKeys.MECHANICAL_HAMMER_HAMMER_LABEL, "Hammer: ");
|
||||
english.add(TranslationKeys.ENERGY, "Energy");
|
||||
|
||||
english.add(TranslationKeys.INFESTED_LEAVES_FULLY_INFESTED, "Fully Infested");
|
||||
|
||||
english.add(TranslationKeys.ROOT_ADVANCEMENT_TITLE, "Don't Look Down...");
|
||||
english.add(TranslationKeys.ROOT_ADVANCEMENT_DESCRIPTION, "Spawn into a SkyBlock void world");
|
||||
english.add(TranslationKeys.CROOK_ADVANCEMENT_TITLE, "Give Him The Hook");
|
||||
|
|
@ -69,7 +71,7 @@ class English {
|
|||
english.add(TranslationKeys.CRUCIBLE_HEAT_SOURCE_CATEGORY_MULTIPLIER, "Melt Rate: %sx");
|
||||
english.add(TranslationKeys.HAMMER_CATEGORY_TITLE, "Hammer");
|
||||
english.add(TranslationKeys.CROOK_CATEGORY_TITLE, "Crook");
|
||||
english.add(TranslationKeys.CROOK_CATEGORY_REQUIRES_STATE, "Requires specific block state");
|
||||
english.add(TranslationKeys.CROOK_CATEGORY_REQUIRES_STATE, "Requires properties:");
|
||||
english.add(TranslationKeys.SIEVE_CATEGORY_TITLE, "Sieve");
|
||||
english.add(TranslationKeys.SIEVE_RECIPE_CHANCE, "Chance: %s%%");
|
||||
english.add(TranslationKeys.SIEVE_RECIPE_AVERAGE_OUTPUT, "Avg. Output: %s");
|
||||
|
|
|
|||
|
|
@ -30,6 +30,9 @@ public class TranslationKeys {
|
|||
public static final String MECHANICAL_HAMMER_HAMMER_LABEL = "item." + ExDeorum.ID + ".mechanical_hammer.hammer_label";
|
||||
public static final String ENERGY = "gui." + ExDeorum.ID + ".energy_label";
|
||||
|
||||
// Blocks
|
||||
public static final String INFESTED_LEAVES_FULLY_INFESTED = "block." + ExDeorum.ID + ".infested_leaves.fully_infested";
|
||||
|
||||
// Advancements
|
||||
public static final String ROOT_ADVANCEMENT_TITLE = "advancements." + ExDeorum.ID + ".core.root.title";
|
||||
public static final String ROOT_ADVANCEMENT_DESCRIPTION = "advancements." + ExDeorum.ID + ".core.root.description";
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
package thedarkcolour.exdeorum.data.recipe;
|
||||
|
||||
import net.minecraft.advancements.critereon.StatePropertiesPredicate;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.data.recipes.FinishedRecipe;
|
||||
import net.minecraft.data.recipes.RecipeCategory;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
|
@ -30,7 +31,9 @@ import net.minecraft.world.item.ItemStack;
|
|||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.item.crafting.Ingredient;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.CampfireBlock;
|
||||
import net.minecraft.world.level.material.Fluid;
|
||||
import net.minecraft.world.level.material.Fluids;
|
||||
import net.minecraft.world.level.storage.loot.providers.number.ConstantValue;
|
||||
|
|
@ -54,6 +57,7 @@ import thedarkcolour.exdeorum.recipe.barrel.FinishedBarrelFluidMixingRecipe;
|
|||
import thedarkcolour.exdeorum.recipe.barrel.FinishedBarrelMixingRecipe;
|
||||
import thedarkcolour.exdeorum.recipe.BlockPredicate;
|
||||
import thedarkcolour.exdeorum.recipe.crook.FinishedCrookRecipe;
|
||||
import thedarkcolour.exdeorum.recipe.crucible.FinishedCrucibleHeatRecipe;
|
||||
import thedarkcolour.exdeorum.recipe.crucible.FinishedCrucibleRecipe;
|
||||
import thedarkcolour.exdeorum.recipe.hammer.FinishedHammerRecipe;
|
||||
import thedarkcolour.exdeorum.registry.EBlocks;
|
||||
|
|
@ -80,6 +84,7 @@ public class Recipes {
|
|||
crucibleRecipes(writer);
|
||||
hammerRecipes(writer);
|
||||
crookRecipes(writer);
|
||||
crucibleHeatSources(writer);
|
||||
barrelCompostRecipes(writer);
|
||||
barrelMixingRecipes(writer);
|
||||
}
|
||||
|
|
@ -490,12 +495,37 @@ public class Recipes {
|
|||
crookRecipe(writer, "silkworm", BlockPredicate.blockTag(BlockTags.LEAVES), EItems.SILK_WORM.get(), 0.01f);
|
||||
var fullyInfestedLeaves = BlockPredicate.blockState(EBlocks.INFESTED_LEAVES.get(), StatePropertiesPredicate.Builder.properties().hasProperty(InfestedLeavesBlock.FULLY_INFESTED, true).build());
|
||||
crookRecipe(writer, "silkworm_bonus", fullyInfestedLeaves, EItems.SILK_WORM.get(), 0.01f);
|
||||
crookRecipe(writer, "string_roll_1", fullyInfestedLeaves, Items.STRING, 0.4f);
|
||||
crookRecipe(writer, "string_roll_2", fullyInfestedLeaves, Items.STRING, 0.1f);
|
||||
}
|
||||
|
||||
private static void crookRecipe(Consumer<FinishedRecipe> writer, String name, BlockPredicate blockPredicate, ItemLike result, float chance) {
|
||||
writer.accept(new FinishedCrookRecipe(new ResourceLocation(ExDeorum.ID, "crook/" + name), blockPredicate, result.asItem(), chance));
|
||||
}
|
||||
|
||||
private static void crucibleHeatSources(Consumer<FinishedRecipe> writer) {
|
||||
crucibleHeatSource(writer, Blocks.TORCH, 1);
|
||||
crucibleHeatSource(writer, Blocks.WALL_TORCH, 1);
|
||||
crucibleHeatSource(writer, Blocks.LANTERN, 1);
|
||||
crucibleHeatSource(writer, Blocks.SOUL_TORCH, 2);
|
||||
crucibleHeatSource(writer, Blocks.SOUL_WALL_TORCH, 2);
|
||||
crucibleHeatSource(writer, Blocks.SOUL_LANTERN, 2);
|
||||
crucibleHeatSource(writer, Blocks.LAVA, 3);
|
||||
crucibleHeatSource(writer, Blocks.FIRE, 5);
|
||||
crucibleHeatSource(writer, Blocks.SOUL_FIRE, 5);
|
||||
|
||||
crucibleHeatSource(writer, "lit_campfire", BlockPredicate.blockState(Blocks.CAMPFIRE, StatePropertiesPredicate.Builder.properties().hasProperty(CampfireBlock.LIT, true).build()), 2);
|
||||
crucibleHeatSource(writer, "lit_soul_campfire", BlockPredicate.blockState(Blocks.SOUL_CAMPFIRE, StatePropertiesPredicate.Builder.properties().hasProperty(CampfireBlock.LIT, true).build()), 2);
|
||||
}
|
||||
|
||||
private static void crucibleHeatSource(Consumer<FinishedRecipe> writer, Block block, int heatValue) {
|
||||
crucibleHeatSource(writer, BuiltInRegistries.BLOCK.getKey(block).getPath(), BlockPredicate.singleBlock(block), heatValue);
|
||||
}
|
||||
|
||||
private static void crucibleHeatSource(Consumer<FinishedRecipe> writer, String name, BlockPredicate blockPredicate, int heatValue) {
|
||||
writer.accept(new FinishedCrucibleHeatRecipe(new ResourceLocation(ExDeorum.ID, "crucible_heat_source/" + name), blockPredicate, heatValue));
|
||||
}
|
||||
|
||||
private static void barrelCompostRecipes(Consumer<FinishedRecipe> writer) {
|
||||
// plants
|
||||
barrelCompost(writer, "saplings", ingredient(ItemTags.SAPLINGS), 125);
|
||||
|
|
|
|||
|
|
@ -242,7 +242,6 @@ public final class EventHandler {
|
|||
event.addListener((prepBarrier, resourceManager, prepProfiler, reloadProfiler, backgroundExecutor, gameExecutor) -> {
|
||||
return prepBarrier.wait(Unit.INSTANCE).thenRunAsync(() -> {
|
||||
RecipeUtil.reload(recipes);
|
||||
LavaCrucibleBlockEntity.putDefaultHeatValues();
|
||||
}, gameExecutor);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,84 +0,0 @@
|
|||
/*
|
||||
* 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.loot;
|
||||
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonObject;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.storage.loot.LootContext;
|
||||
import net.minecraft.world.level.storage.loot.functions.LootItemConditionalFunction;
|
||||
import net.minecraft.world.level.storage.loot.functions.LootItemFunctionType;
|
||||
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
|
||||
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition;
|
||||
import thedarkcolour.exdeorum.block.InfestedLeavesBlock;
|
||||
import thedarkcolour.exdeorum.blockentity.InfestedLeavesBlockEntity;
|
||||
import thedarkcolour.exdeorum.config.EConfig;
|
||||
import thedarkcolour.exdeorum.registry.ELootFunctions;
|
||||
|
||||
// Sets the correct amount based on the progress of the infested leaves
|
||||
public class InfestedStringFunction extends LootItemConditionalFunction {
|
||||
protected InfestedStringFunction(LootItemCondition[] conditions) {
|
||||
super(conditions);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ItemStack run(ItemStack stack, LootContext context) {
|
||||
var te = context.getParamOrNull(LootContextParams.BLOCK_ENTITY);
|
||||
var state = context.getParamOrNull(LootContextParams.BLOCK_STATE);
|
||||
|
||||
if (state != null && state.getValue(InfestedLeavesBlock.FULLY_INFESTED)) {
|
||||
if (te instanceof InfestedLeavesBlockEntity leaves) {
|
||||
var progress = leaves.getProgress();
|
||||
var rand = context.getRandom();
|
||||
var count = 0;
|
||||
var chance = EConfig.SERVER.infestedLeavesStringChance.get();
|
||||
|
||||
if (rand.nextFloat() < progress * chance) {
|
||||
if (rand.nextFloat() < progress * chance / 4f) {
|
||||
++count;
|
||||
}
|
||||
++count;
|
||||
}
|
||||
|
||||
if (count > 0) {
|
||||
stack.setCount(count);
|
||||
return stack;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LootItemFunctionType getType() {
|
||||
return ELootFunctions.INFESTED_STRING.get();
|
||||
}
|
||||
|
||||
public static LootItemConditionalFunction.Builder<?> infestedString() {
|
||||
return LootItemConditionalFunction.simpleBuilder(InfestedStringFunction::new);
|
||||
}
|
||||
|
||||
public static class LootSerializer extends LootItemConditionalFunction.Serializer<InfestedStringFunction> {
|
||||
@Override
|
||||
public InfestedStringFunction deserialize(JsonObject json, JsonDeserializationContext ctx, LootItemCondition[] conditions) {
|
||||
return new InfestedStringFunction(conditions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -31,6 +31,7 @@ import net.minecraft.world.level.block.Blocks;
|
|||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
|
@ -69,7 +70,7 @@ public sealed interface BlockPredicate extends Predicate<BlockState> {
|
|||
if (block == Blocks.AIR) return null;
|
||||
|
||||
if (json.has("state")) {
|
||||
return new BlockStatePredicate(block, StatePropertiesPredicate.fromJson(json.get("block_state")));
|
||||
return new BlockStatePredicate(block, StatePropertiesPredicate.fromJson(json.get("state")));
|
||||
} else {
|
||||
return new SingleBlockPredicate(block);
|
||||
}
|
||||
|
|
@ -142,6 +143,15 @@ public sealed interface BlockPredicate extends Predicate<BlockState> {
|
|||
public Stream<BlockState> possibleStates() {
|
||||
return this.block.getStateDefinition().getPossibleStates().stream().filter(this.properties::matches);
|
||||
}
|
||||
|
||||
// Although slow, this is useful for testing
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
BlockStatePredicate that = (BlockStatePredicate) o;
|
||||
return Objects.equals(block, that.block) && Objects.equals(properties.serializeToJson(), that.properties.serializeToJson());
|
||||
}
|
||||
}
|
||||
|
||||
record SingleBlockPredicate(Block block) implements BlockPredicate {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,9 @@ package thedarkcolour.exdeorum.recipe;
|
|||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectSet;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
|
@ -46,15 +48,13 @@ import net.minecraftforge.common.crafting.CraftingHelper;
|
|||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import thedarkcolour.exdeorum.ExDeorum;
|
||||
import thedarkcolour.exdeorum.compat.PreferredOres;
|
||||
import thedarkcolour.exdeorum.item.HammerItem;
|
||||
import thedarkcolour.exdeorum.recipe.barrel.BarrelCompostRecipe;
|
||||
import thedarkcolour.exdeorum.recipe.barrel.BarrelFluidMixingRecipe;
|
||||
import thedarkcolour.exdeorum.recipe.barrel.BarrelMixingRecipe;
|
||||
import thedarkcolour.exdeorum.recipe.cache.BarrelFluidMixingRecipeCache;
|
||||
import thedarkcolour.exdeorum.recipe.cache.CrookRecipeCache;
|
||||
import thedarkcolour.exdeorum.recipe.cache.SieveRecipeCache;
|
||||
import thedarkcolour.exdeorum.recipe.cache.SingleIngredientRecipeCache;
|
||||
import thedarkcolour.exdeorum.recipe.cache.*;
|
||||
import thedarkcolour.exdeorum.recipe.crook.CrookRecipe;
|
||||
import thedarkcolour.exdeorum.recipe.crucible.CrucibleRecipe;
|
||||
import thedarkcolour.exdeorum.recipe.hammer.HammerRecipe;
|
||||
|
|
@ -80,6 +80,7 @@ public final class RecipeUtil {
|
|||
private static SieveRecipeCache sieveRecipeCache;
|
||||
private static BarrelFluidMixingRecipeCache barrelFluidMixingRecipeCache;
|
||||
private static CrookRecipeCache crookRecipeCache;
|
||||
private static CrucibleHeatRecipeCache crucibleHeatRecipeCache;
|
||||
|
||||
public static void reload(RecipeManager recipes) {
|
||||
barrelCompostRecipeCache = new SingleIngredientRecipeCache<>(recipes, ERecipeTypes.BARREL_COMPOST);
|
||||
|
|
@ -89,6 +90,7 @@ public final class RecipeUtil {
|
|||
sieveRecipeCache = new SieveRecipeCache(recipes);
|
||||
barrelFluidMixingRecipeCache = new BarrelFluidMixingRecipeCache(recipes);
|
||||
crookRecipeCache = new CrookRecipeCache(recipes);
|
||||
crucibleHeatRecipeCache = new CrucibleHeatRecipeCache(recipes);
|
||||
HammerItem.refreshValidBlocks();
|
||||
}
|
||||
|
||||
|
|
@ -100,6 +102,7 @@ public final class RecipeUtil {
|
|||
sieveRecipeCache = null;
|
||||
barrelFluidMixingRecipeCache = null;
|
||||
crookRecipeCache = null;
|
||||
crucibleHeatRecipeCache = null;
|
||||
}
|
||||
|
||||
public static List<SieveRecipe> getSieveRecipes(Item mesh, ItemStack item) {
|
||||
|
|
@ -311,6 +314,26 @@ public final class RecipeUtil {
|
|||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static BlockPredicate readBlockPredicate(ResourceLocation recipeId, JsonObject json) {
|
||||
BlockPredicate blockPredicate = BlockPredicate.fromJson(json.getAsJsonObject("block_predicate"));
|
||||
|
||||
if (blockPredicate == null) {
|
||||
ExDeorum.LOGGER.error("Invalid block_predicate for recipe {}, refer to Ex Deorum documentation for syntax: {}", recipeId, json.getAsJsonObject("block_predicate"));
|
||||
}
|
||||
return blockPredicate;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static BlockPredicate readBlockPredicateNetwork(ResourceLocation recipeId, FriendlyByteBuf buffer) {
|
||||
BlockPredicate blockPredicate = BlockPredicate.fromNetwork(buffer);
|
||||
|
||||
if (blockPredicate == null) {
|
||||
ExDeorum.LOGGER.error("Failed to read block_predicate from network for recipe {}", recipeId);
|
||||
}
|
||||
return blockPredicate;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static boolean isTagEmpty(TagKey<Item> tag) {
|
||||
return BuiltInRegistries.ITEM.getTag(tag).map(set -> !set.iterator().hasNext()).orElse(PreferredOres.getPreferredOre(tag) == Items.AIR);
|
||||
|
|
@ -323,4 +346,12 @@ public final class RecipeUtil {
|
|||
public static List<CrookRecipe> getCrookRecipes(BlockState state) {
|
||||
return crookRecipeCache.getRecipes(state);
|
||||
}
|
||||
|
||||
public static int getHeatValue(BlockState state) {
|
||||
return crucibleHeatRecipeCache.getValue(state);
|
||||
}
|
||||
|
||||
public static ObjectSet<Object2IntMap.Entry<BlockState>> getHeatSources() {
|
||||
return crucibleHeatRecipeCache.getEntries();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
61
src/main/java/thedarkcolour/exdeorum/recipe/cache/CrucibleHeatRecipeCache.java
vendored
Normal file
61
src/main/java/thedarkcolour/exdeorum/recipe/cache/CrucibleHeatRecipeCache.java
vendored
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* 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.recipe.cache;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectSet;
|
||||
import net.minecraft.world.item.crafting.RecipeManager;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import thedarkcolour.exdeorum.registry.ERecipeTypes;
|
||||
|
||||
public class CrucibleHeatRecipeCache {
|
||||
private RecipeManager recipeManager;
|
||||
@Nullable
|
||||
private Object2IntMap<BlockState> recipes;
|
||||
|
||||
public CrucibleHeatRecipeCache(RecipeManager recipeManager) {
|
||||
this.recipeManager = recipeManager;
|
||||
}
|
||||
|
||||
public int getValue(BlockState state) {
|
||||
if (this.recipes == null) {
|
||||
buildRecipes();
|
||||
}
|
||||
return this.recipes.getInt(state);
|
||||
}
|
||||
|
||||
private void buildRecipes() {
|
||||
this.recipes = new Object2IntOpenHashMap<>();
|
||||
|
||||
for (var recipe : this.recipeManager.byType(ERecipeTypes.CRUCIBLE_HEAT_SOURCE.get()).values()) {
|
||||
recipe.blockPredicate().possibleStates().forEach(state -> recipes.put(state, recipe.heatValue()));
|
||||
}
|
||||
|
||||
this.recipeManager = null;
|
||||
}
|
||||
|
||||
public ObjectSet<Object2IntMap.Entry<BlockState>> getEntries() {
|
||||
if (this.recipes == null) {
|
||||
buildRecipes();
|
||||
}
|
||||
return this.recipes.object2IntEntrySet();
|
||||
}
|
||||
}
|
||||
|
|
@ -31,7 +31,6 @@ import net.minecraft.world.item.crafting.Recipe;
|
|||
import net.minecraft.world.item.crafting.RecipeSerializer;
|
||||
import net.minecraft.world.item.crafting.RecipeType;
|
||||
import net.minecraft.world.level.Level;
|
||||
import thedarkcolour.exdeorum.ExDeorum;
|
||||
import thedarkcolour.exdeorum.recipe.BlockPredicate;
|
||||
import thedarkcolour.exdeorum.recipe.RecipeUtil;
|
||||
import thedarkcolour.exdeorum.registry.ERecipeSerializers;
|
||||
|
|
@ -77,26 +76,21 @@ public record CrookRecipe(ResourceLocation id, BlockPredicate blockPredicate, It
|
|||
public static class Serializer implements RecipeSerializer<CrookRecipe> {
|
||||
@Override
|
||||
public CrookRecipe fromJson(ResourceLocation id, JsonObject json) {
|
||||
BlockPredicate blockPredicate = BlockPredicate.fromJson(json.getAsJsonObject("block_predicate"));
|
||||
BlockPredicate blockPredicate = RecipeUtil.readBlockPredicate(id, json);
|
||||
if (blockPredicate == null) return null;
|
||||
|
||||
if (blockPredicate == null) {
|
||||
ExDeorum.LOGGER.error("Invalid block_predicate for recipe {}, refer to Ex Deorum documentation for syntax: {}", id, json.getAsJsonObject("block_predicate"));
|
||||
return null;
|
||||
}
|
||||
Item result = RecipeUtil.readItem(json, "result");
|
||||
float chance = json.get("chance").getAsFloat();
|
||||
|
||||
|
||||
return new CrookRecipe(id, blockPredicate, result, chance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CrookRecipe fromNetwork(ResourceLocation id, FriendlyByteBuf buffer) {
|
||||
BlockPredicate blockPredicate = BlockPredicate.fromNetwork(buffer);
|
||||
BlockPredicate blockPredicate = RecipeUtil.readBlockPredicateNetwork(id, buffer);
|
||||
if (blockPredicate == null) return null;
|
||||
|
||||
if (blockPredicate == null) {
|
||||
ExDeorum.LOGGER.error("Failed to read block_predicate from network for recipe {}", id);
|
||||
return null;
|
||||
}
|
||||
Item result = buffer.readById(BuiltInRegistries.ITEM);
|
||||
if (result == null || result == Items.AIR) {
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* 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.recipe.crucible;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.Recipe;
|
||||
import net.minecraft.world.item.crafting.RecipeSerializer;
|
||||
import net.minecraft.world.item.crafting.RecipeType;
|
||||
import net.minecraft.world.level.Level;
|
||||
import thedarkcolour.exdeorum.recipe.BlockPredicate;
|
||||
import thedarkcolour.exdeorum.recipe.RecipeUtil;
|
||||
import thedarkcolour.exdeorum.registry.ERecipeSerializers;
|
||||
import thedarkcolour.exdeorum.registry.ERecipeTypes;
|
||||
|
||||
public record CrucibleHeatRecipe(ResourceLocation id, BlockPredicate blockPredicate, int heatValue) implements Recipe<Container> {
|
||||
@Override
|
||||
public boolean matches(Container pContainer, Level pLevel) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack assemble(Container pContainer, RegistryAccess pRegistryAccess) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canCraftInDimensions(int pWidth, int pHeight) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getResultItem(RegistryAccess pRegistryAccess) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeSerializer<?> getSerializer() {
|
||||
return ERecipeSerializers.CRUCIBLE_HEAT_SOURCE.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeType<?> getType() {
|
||||
return ERecipeTypes.CRUCIBLE_HEAT_SOURCE.get();
|
||||
}
|
||||
|
||||
public static class Serializer implements RecipeSerializer<CrucibleHeatRecipe> {
|
||||
@Override
|
||||
public CrucibleHeatRecipe fromJson(ResourceLocation id, JsonObject json) {
|
||||
BlockPredicate blockPredicate = RecipeUtil.readBlockPredicate(id, json);
|
||||
if (blockPredicate == null) return null;
|
||||
int heatValue = json.get("heat_value").getAsInt();
|
||||
return new CrucibleHeatRecipe(id, blockPredicate, heatValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CrucibleHeatRecipe fromNetwork(ResourceLocation id, FriendlyByteBuf buffer) {
|
||||
BlockPredicate blockPredicate = RecipeUtil.readBlockPredicateNetwork(id, buffer);
|
||||
if (blockPredicate == null) return null;
|
||||
int heatValue = buffer.readVarInt();
|
||||
return new CrucibleHeatRecipe(id, blockPredicate, heatValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toNetwork(FriendlyByteBuf buffer, CrucibleHeatRecipe recipe) {
|
||||
recipe.blockPredicate.toNetwork(buffer);
|
||||
buffer.writeVarInt(recipe.heatValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* 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.recipe.crucible;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.crafting.RecipeSerializer;
|
||||
import thedarkcolour.exdeorum.recipe.BlockPredicate;
|
||||
import thedarkcolour.exdeorum.recipe.EFinishedRecipe;
|
||||
import thedarkcolour.exdeorum.registry.ERecipeSerializers;
|
||||
|
||||
public class FinishedCrucibleHeatRecipe implements EFinishedRecipe {
|
||||
private final ResourceLocation id;
|
||||
private final BlockPredicate blockPredicate;
|
||||
private final int heatValue;
|
||||
|
||||
public FinishedCrucibleHeatRecipe(ResourceLocation id, BlockPredicate blockPredicate, int heatValue) {
|
||||
this.id = id;
|
||||
this.blockPredicate = blockPredicate;
|
||||
this.heatValue = heatValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeRecipeData(JsonObject json) {
|
||||
json.add("block_predicate", this.blockPredicate.toJson());
|
||||
json.addProperty("heat_value", this. heatValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeSerializer<?> getType() {
|
||||
return ERecipeSerializers.CRUCIBLE_HEAT_SOURCE.get();
|
||||
}
|
||||
}
|
||||
|
|
@ -44,7 +44,6 @@ public class FinishedCrucibleRecipe implements EFinishedRecipe {
|
|||
this.fluidStack = fluidStack;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void serializeRecipeData(JsonObject json) {
|
||||
json.add("ingredient", this.ingredient.toJson());
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ public class EBlocks {
|
|||
public static final RegistryObject<WaterCrucibleBlock> MAPLE_CRUCIBLE = registerWaterCrucible("maple_crucible");
|
||||
|
||||
// Misc
|
||||
public static final RegistryObject<InfestedLeavesBlock> INFESTED_LEAVES = BLOCKS.register("infested_leaves", () -> new InfestedLeavesBlock(copy(Blocks.OAK_LEAVES)));
|
||||
public static final RegistryObject<InfestedLeavesBlock> INFESTED_LEAVES = BLOCKS.register("infested_leaves", () -> new InfestedLeavesBlock(copy(Blocks.OAK_LEAVES).noLootTable()));
|
||||
public static final RegistryObject<LiquidBlock> WITCH_WATER = BLOCKS.register("witch_water", () -> new WitchWaterBlock(EFluids.WITCH_WATER, copy(Blocks.WATER).mapColor(MapColor.COLOR_PURPLE)));
|
||||
public static final RegistryObject<EndCakeBlock> END_CAKE = BLOCKS.register("end_cake", () -> new EndCakeBlock(of().noLootTable().mapColor(MapColor.COLOR_BLACK).forceSolidOn().strength(0.5F).sound(SoundType.WOOL).pushReaction(PushReaction.BLOCK)));
|
||||
|
||||
|
|
|
|||
|
|
@ -23,12 +23,10 @@ import net.minecraft.world.level.storage.loot.functions.LootItemFunctionType;
|
|||
import net.minecraftforge.registries.DeferredRegister;
|
||||
import net.minecraftforge.registries.RegistryObject;
|
||||
import thedarkcolour.exdeorum.ExDeorum;
|
||||
import thedarkcolour.exdeorum.loot.InfestedStringFunction;
|
||||
import thedarkcolour.exdeorum.loot.MachineLootFunction;
|
||||
|
||||
public class ELootFunctions {
|
||||
public static final DeferredRegister<LootItemFunctionType> LOOT_FUNCTIONS = DeferredRegister.create(Registries.LOOT_FUNCTION_TYPE, ExDeorum.ID);
|
||||
|
||||
public static final RegistryObject<LootItemFunctionType> INFESTED_STRING = LOOT_FUNCTIONS.register("infested_string", () -> new LootItemFunctionType(new InfestedStringFunction.LootSerializer()));
|
||||
public static final RegistryObject<LootItemFunctionType> MACHINE = LOOT_FUNCTIONS.register("machine", () -> new LootItemFunctionType(new MachineLootFunction.LootSerializer()));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import thedarkcolour.exdeorum.recipe.barrel.BarrelCompostRecipe;
|
|||
import thedarkcolour.exdeorum.recipe.barrel.BarrelFluidMixingRecipe;
|
||||
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.HammerRecipe;
|
||||
import thedarkcolour.exdeorum.recipe.sieve.SieveRecipe;
|
||||
|
|
@ -41,6 +42,7 @@ public class ERecipeSerializers {
|
|||
|
||||
public static final RegistryObject<RecipeSerializer<HammerRecipe>> HAMMER = RECIPE_SERIALIZERS.register("hammer", HammerRecipe.Serializer::new);
|
||||
public static final RegistryObject<RecipeSerializer<CrookRecipe>> CROOK = RECIPE_SERIALIZERS.register("crook", CrookRecipe.Serializer::new);
|
||||
public static final RegistryObject<RecipeSerializer<CrucibleHeatRecipe>> CRUCIBLE_HEAT_SOURCE = RECIPE_SERIALIZERS.register("crucible_heat_source", CrucibleHeatRecipe.Serializer::new);
|
||||
|
||||
public static final RegistryObject<RecipeSerializer<CrucibleRecipe>> LAVA_CRUCIBLE = RECIPE_SERIALIZERS.register("lava_crucible", () -> new CrucibleRecipe.Serializer(ERecipeTypes.LAVA_CRUCIBLE.get()));
|
||||
public static final RegistryObject<RecipeSerializer<CrucibleRecipe>> WATER_CRUCIBLE = RECIPE_SERIALIZERS.register("water_crucible", () -> new CrucibleRecipe.Serializer(ERecipeTypes.WATER_CRUCIBLE.get()));
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import thedarkcolour.exdeorum.recipe.barrel.BarrelCompostRecipe;
|
|||
import thedarkcolour.exdeorum.recipe.barrel.BarrelFluidMixingRecipe;
|
||||
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.HammerRecipe;
|
||||
import thedarkcolour.exdeorum.recipe.sieve.SieveRecipe;
|
||||
|
|
@ -43,6 +44,7 @@ public class ERecipeTypes {
|
|||
|
||||
public static final RegistryObject<RecipeType<HammerRecipe>> HAMMER = RECIPE_TYPES.register("hammer", () -> RecipeType.simple(ERecipeTypes.HAMMER.getId()));
|
||||
public static final RegistryObject<RecipeType<CrookRecipe>> CROOK = RECIPE_TYPES.register("crook", () -> RecipeType.simple(ERecipeTypes.CROOK.getId()));
|
||||
public static final RegistryObject<RecipeType<CrucibleHeatRecipe>> CRUCIBLE_HEAT_SOURCE = RECIPE_TYPES.register("crucible_heat_source", () -> RecipeType.simple(ERecipeTypes.CRUCIBLE_HEAT_SOURCE.getId()));
|
||||
|
||||
public static final RegistryObject<RecipeType<SieveRecipe>> SIEVE = RECIPE_TYPES.register("sieve", () -> RecipeType.simple(ERecipeTypes.SIEVE.getId()));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@
|
|||
|
||||
package thedarkcolour.exdeorum.recipe;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import net.minecraft.SharedConstants;
|
||||
import net.minecraft.advancements.critereon.StatePropertiesPredicate;
|
||||
|
|
@ -30,6 +32,8 @@ import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
|||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class BlockPredicateTest {
|
||||
|
|
@ -39,6 +43,23 @@ class BlockPredicateTest {
|
|||
Bootstrap.bootStrap();
|
||||
}
|
||||
|
||||
@Test
|
||||
void jsonTest() {
|
||||
var testPredicate = """
|
||||
{
|
||||
"block": "minecraft:oak_wood",
|
||||
"state": {
|
||||
"axis": "y"
|
||||
}
|
||||
}
|
||||
""";
|
||||
var json = JsonParser.parseString(testPredicate);
|
||||
var expected = BlockPredicate.blockState(Blocks.OAK_WOOD, StatePropertiesPredicate.Builder.properties().hasProperty(BlockStateProperties.AXIS, Direction.Axis.Y).build());
|
||||
var actual = BlockPredicate.fromJson((JsonObject) json);
|
||||
assertNotNull(actual);
|
||||
assertEquals(expected.possibleStates().collect(Collectors.toSet()), actual.possibleStates().collect(Collectors.toSet()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void networkTest() {
|
||||
var buffer = new FriendlyByteBuf(Unpooled.buffer());
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* 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.recipe;
|
||||
|
||||
import io.netty.buffer.Unpooled;
|
||||
import net.minecraft.SharedConstants;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.server.Bootstrap;
|
||||
import net.minecraft.tags.BlockTags;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.item.crafting.Recipe;
|
||||
import net.minecraft.world.item.crafting.RecipeSerializer;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import thedarkcolour.exdeorum.recipe.crook.CrookRecipe;
|
||||
import thedarkcolour.exdeorum.recipe.crucible.CrucibleHeatRecipe;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
// Tests JSON and network serialization/deserialization methods of all recipes to ensure everything works
|
||||
public class RecipeSerializationTests {
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
SharedConstants.tryDetectVersion();
|
||||
Bootstrap.bootStrap();
|
||||
}
|
||||
|
||||
@Test
|
||||
void crucibleHeatSourceNetwork() {
|
||||
testNetwork(new CrucibleHeatRecipe(null, BlockPredicate.blockTag(BlockTags.DIRT), 3), new CrucibleHeatRecipe.Serializer());
|
||||
}
|
||||
|
||||
@Test
|
||||
void crucibleHeatSourceJson() {
|
||||
fail();
|
||||
}
|
||||
|
||||
@Test
|
||||
void crookNetwork() {
|
||||
testNetwork(new CrookRecipe(null, BlockPredicate.blockTag(BlockTags.DIRT), Items.DIAMOND, 0.0025f), new CrookRecipe.Serializer());
|
||||
}
|
||||
|
||||
// Takes a recipe, uses its serializer to write it to a buffer, then reads it
|
||||
// back and checks if the recipe it got is the same as the one originally written
|
||||
private static <T extends Recipe<?>> void testNetwork(T recipe, RecipeSerializer<T> serializer) {
|
||||
var id = recipe.getId();
|
||||
var buffer = new FriendlyByteBuf(Unpooled.buffer());
|
||||
serializer.toNetwork(buffer, recipe);
|
||||
assertEquals(recipe, serializer.fromNetwork(id, buffer));
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user