summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main/java/lv/enes/mc/eris_alchemy/EMC.java36
-rw-r--r--src/main/java/lv/enes/mc/eris_alchemy/EmcStorage.java17
-rw-r--r--src/main/java/lv/enes/mc/eris_alchemy/ErisAlchemyRegistry.java48
-rw-r--r--src/main/java/lv/enes/mc/eris_alchemy/block/AlchemicalChestBlock.java10
-rw-r--r--src/main/java/lv/enes/mc/eris_alchemy/block/ChestLikeBlock.java6
-rw-r--r--src/main/java/lv/enes/mc/eris_alchemy/block/EnergyCondenserBlock.java56
-rw-r--r--src/main/java/lv/enes/mc/eris_alchemy/block/entity/AlchemicalChestEntity.java (renamed from src/main/java/lv/enes/mc/eris_alchemy/block/entity/AlchemicalChestBlockEntity.java)15
-rw-r--r--src/main/java/lv/enes/mc/eris_alchemy/block/entity/ChestLikeEntity.java (renamed from src/main/java/lv/enes/mc/eris_alchemy/block/entity/ChestLikeBlockEntity.java)27
-rw-r--r--src/main/java/lv/enes/mc/eris_alchemy/block/entity/EnergyCondenserEntity.java143
-rw-r--r--src/main/java/lv/enes/mc/eris_alchemy/client/ChestLikeScreen.java4
-rw-r--r--src/main/java/lv/enes/mc/eris_alchemy/client/EnergyCondenserScreen.java46
-rw-r--r--src/main/java/lv/enes/mc/eris_alchemy/client/ErisAlchemyClient.java10
-rw-r--r--src/main/java/lv/enes/mc/eris_alchemy/client/ErisAlchemyClientRegistry.java11
-rw-r--r--src/main/java/lv/enes/mc/eris_alchemy/client/ErisAlchemyMaterials.java5
-rw-r--r--src/main/java/lv/enes/mc/eris_alchemy/menu/AlchemicalChestMenu.java20
-rw-r--r--src/main/java/lv/enes/mc/eris_alchemy/menu/ChestLikeMenu.java (renamed from src/main/java/lv/enes/mc/eris_alchemy/menu/ChestLikeBlockMenu.java)42
-rw-r--r--src/main/java/lv/enes/mc/eris_alchemy/menu/EnergyCondenserMenu.java60
-rw-r--r--src/main/java/lv/enes/mc/eris_alchemy/mixin/ContainerOpenersCounterMixin.java56
-rw-r--r--src/main/java/lv/enes/mc/eris_alchemy/mixin/client/SheetsMixin.java7
-rw-r--r--src/main/java/lv/enes/mc/eris_alchemy/utils/ContainerOpenersCounterUtil.java20
-rw-r--r--src/main/java/lv/enes/mc/eris_alchemy/utils/SyncedValue.java115
-rw-r--r--src/main/resources/assets/eris_alchemy/blockstates/energy_condenser.json7
-rw-r--r--src/main/resources/assets/eris_alchemy/lang/en_us.json2
-rw-r--r--src/main/resources/assets/eris_alchemy/models/block/energy_condenser.json5
-rw-r--r--src/main/resources/assets/eris_alchemy/models/item/energy_condenser.json6
-rw-r--r--src/main/resources/assets/eris_alchemy/patchouli_books/guide_book/en_us/entries/root/covalence_dusts.json1
-rw-r--r--src/main/resources/assets/eris_alchemy/patchouli_books/guide_book/en_us/entries/root/energy_condenser.json14
-rw-r--r--src/main/resources/assets/eris_alchemy/patchouli_books/guide_book/en_us/entries/root/guide_book.json1
-rw-r--r--src/main/resources/assets/eris_alchemy/textures/entity/chest/energy_condenser.pngbin0 -> 2649 bytes
-rw-r--r--src/main/resources/assets/eris_alchemy/textures/gui/container/energy_condenser.pngbin0 -> 1331 bytes
-rw-r--r--src/main/resources/data/eris_alchemy/loot_tables/blocks/energy_condenser.json22
-rw-r--r--src/main/resources/data/eris_alchemy/recipes/energy_condenser.json22
-rw-r--r--src/main/resources/data/minecraft/tags/blocks/mineable/pickaxe.json3
-rw-r--r--src/main/resources/eris_alchemy.mixins.json1
-rw-r--r--src/main/resources/quilt.mod.json7
35 files changed, 765 insertions, 80 deletions
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/EMC.java b/src/main/java/lv/enes/mc/eris_alchemy/EMC.java
index e34d28f..3ff33ca 100644
--- a/src/main/java/lv/enes/mc/eris_alchemy/EMC.java
+++ b/src/main/java/lv/enes/mc/eris_alchemy/EMC.java
@@ -16,6 +16,7 @@ import net.minecraft.world.level.Level;
16import net.minecraft.world.level.block.Block; 16import net.minecraft.world.level.block.Block;
17import vazkii.patchouli.common.item.PatchouliItems; 17import vazkii.patchouli.common.item.PatchouliItems;
18 18
19import java.text.DecimalFormat;
19import java.util.*; 20import java.util.*;
20import java.util.stream.Stream; 21import java.util.stream.Stream;
21 22
@@ -62,6 +63,11 @@ public class EMC {
62 private static final EMC defaultInstance = new EMC(null); 63 private static final EMC defaultInstance = new EMC(null);
63 private static final Map<Level, EMC> instances = Collections.synchronizedMap(new WeakHashMap<>()); 64 private static final Map<Level, EMC> instances = Collections.synchronizedMap(new WeakHashMap<>());
64 65
66 private static final DecimalFormat formatter = new DecimalFormat("0");
67 static {
68 formatter.setMaximumFractionDigits(1);
69 }
70
65 public static EMC getInstance(Level world) { 71 public static EMC getInstance(Level world) {
66 if (world == null) { 72 if (world == null) {
67 return defaultInstance; 73 return defaultInstance;
@@ -76,6 +82,10 @@ public class EMC {
76 return instance; 82 return instance;
77 } 83 }
78 84
85 public static String formatEmc(double value) {
86 return formatter.format(value);
87 }
88
79 private final Map<Item, Double> data; 89 private final Map<Item, Double> data;
80 90
81 private EMC(@Nullable Level world) { 91 private EMC(@Nullable Level world) {
@@ -91,10 +101,9 @@ public class EMC {
91 .forEach(holder -> data.putIfAbsent(holder.value().asItem(), emcValue)) 101 .forEach(holder -> data.putIfAbsent(holder.value().asItem(), emcValue))
92 ); 102 );
93 103
94 ErisAlchemy.LOGGER.info("Getting recipes..."); 104 ErisAlchemy.LOGGER.info("Calculating EMC values...");
95 var recipes = getRecipes(world); 105 var recipes = getRecipes(world);
96 var configured = new HashSet<>(data.keySet()); 106 var configured = new HashSet<>(data.keySet());
97 ErisAlchemy.LOGGER.info("Calculating EMC values...");
98 BuiltInRegistries.ITEM.forEach(item -> { 107 BuiltInRegistries.ITEM.forEach(item -> {
99 configEmc(recipes, configured, item); 108 configEmc(recipes, configured, item);
100 if (world != null && !data.containsKey(item)) { 109 if (world != null && !data.containsKey(item)) {
@@ -103,11 +112,30 @@ public class EMC {
103 }); 112 });
104 } 113 }
105 114
106 public OptionalDouble get(Item item) { 115 public OptionalDouble get(ItemStack stack) {
116 if (stack.isEmpty()) {
117 return OptionalDouble.empty();
118 }
119
120 var item = stack.getItem();
107 var value = data.get(item); 121 var value = data.get(item);
108 if (value == null || value <= 0) { 122 if (value == null || value <= 0) {
109 return OptionalDouble.empty(); 123 return OptionalDouble.empty();
110 } 124 }
125
126 EmcStorage storage = null;
127 if (item instanceof EmcStorage emcStorage) {
128 storage = emcStorage;
129 } else if (item instanceof BlockItem blockItem) {
130 if (blockItem.getBlock() instanceof EmcStorage emcStorage) {
131 storage = emcStorage;
132 }
133 }
134
135 if (storage != null) {
136 value += storage.getStoredEmc(stack);
137 }
138
111 return OptionalDouble.of(value); 139 return OptionalDouble.of(value);
112 } 140 }
113 141
@@ -134,7 +162,7 @@ public class EMC {
134 } 162 }
135 163
136 private OptionalDouble configEmc(List<SimplifiedRecipe> recipes, Set<Item> configured, Item item) { 164 private OptionalDouble configEmc(List<SimplifiedRecipe> recipes, Set<Item> configured, Item item) {
137 var res = get(item); 165 var res = get(item.getDefaultInstance());
138 if (res.isPresent() || configured.contains(item)) { 166 if (res.isPresent() || configured.contains(item)) {
139 return res; 167 return res;
140 } 168 }
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/EmcStorage.java b/src/main/java/lv/enes/mc/eris_alchemy/EmcStorage.java
new file mode 100644
index 0000000..427a887
--- /dev/null
+++ b/src/main/java/lv/enes/mc/eris_alchemy/EmcStorage.java
@@ -0,0 +1,17 @@
1package lv.enes.mc.eris_alchemy;
2
3import net.minecraft.nbt.CompoundTag;
4import net.minecraft.world.item.BlockItem;
5import net.minecraft.world.item.ItemStack;
6
7public interface EmcStorage {
8 double getStoredEmc(ItemStack stack, CompoundTag blockEntityData);
9
10 default double getStoredEmc(ItemStack stack) {
11 var blockEntityData = BlockItem.getBlockEntityData(stack);
12 if (blockEntityData == null) {
13 return 0;
14 }
15 return getStoredEmc(stack, blockEntityData);
16 }
17}
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/ErisAlchemyRegistry.java b/src/main/java/lv/enes/mc/eris_alchemy/ErisAlchemyRegistry.java
index c02a1e6..592eb5e 100644
--- a/src/main/java/lv/enes/mc/eris_alchemy/ErisAlchemyRegistry.java
+++ b/src/main/java/lv/enes/mc/eris_alchemy/ErisAlchemyRegistry.java
@@ -1,9 +1,13 @@
1package lv.enes.mc.eris_alchemy; 1package lv.enes.mc.eris_alchemy;
2 2
3import lv.enes.mc.eris_alchemy.block.AlchemicalChestBlock; 3import lv.enes.mc.eris_alchemy.block.AlchemicalChestBlock;
4import lv.enes.mc.eris_alchemy.block.entity.AlchemicalChestBlockEntity; 4import lv.enes.mc.eris_alchemy.block.EnergyCondenserBlock;
5import lv.enes.mc.eris_alchemy.block.entity.AlchemicalChestEntity;
6import lv.enes.mc.eris_alchemy.block.entity.EnergyCondenserEntity;
5import lv.enes.mc.eris_alchemy.menu.AlchemicalChestMenu; 7import lv.enes.mc.eris_alchemy.menu.AlchemicalChestMenu;
8import lv.enes.mc.eris_alchemy.menu.EnergyCondenserMenu;
6import lv.enes.mc.eris_alchemy.recipe.CovalenceRepair; 9import lv.enes.mc.eris_alchemy.recipe.CovalenceRepair;
10import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerType;
7import net.minecraft.core.registries.BuiltInRegistries; 11import net.minecraft.core.registries.BuiltInRegistries;
8import net.minecraft.resources.ResourceLocation; 12import net.minecraft.resources.ResourceLocation;
9import net.minecraft.world.flag.FeatureFlags; 13import net.minecraft.world.flag.FeatureFlags;
@@ -35,9 +39,15 @@ public final class ErisAlchemyRegistry {
35 39
36 private static final Map<ResourceLocation, BlockEntityType<?>> data = new LinkedHashMap<>(); 40 private static final Map<ResourceLocation, BlockEntityType<?>> data = new LinkedHashMap<>();
37 41
38 public static final BlockEntityType<AlchemicalChestBlockEntity> ALCHEMICAL_CHEST = register( 42 public static final BlockEntityType<AlchemicalChestEntity> ALCHEMICAL_CHEST = register(
39 "alchemical_chest", 43 "alchemical_chest",
40 QuiltBlockEntityTypeBuilder.create(AlchemicalChestBlockEntity::new, Blocks.ALCHEMICAL_CHEST) 44 QuiltBlockEntityTypeBuilder.create(AlchemicalChestEntity::new, Blocks.ALCHEMICAL_CHEST)
45 .build()
46 );
47
48 public static final BlockEntityType<EnergyCondenserEntity> ENERGY_CONDENSER = register(
49 "energy_condenser",
50 QuiltBlockEntityTypeBuilder.create(EnergyCondenserEntity::new, Blocks.ENERGY_CONDENSER)
41 .build() 51 .build()
42 ); 52 );
43 53
@@ -61,6 +71,11 @@ public final class ErisAlchemyRegistry {
61 new AlchemicalChestBlock(QuiltBlockSettings.copy(ENDER_CHEST)) 71 new AlchemicalChestBlock(QuiltBlockSettings.copy(ENDER_CHEST))
62 ); 72 );
63 73
74 public static final EnergyCondenserBlock ENERGY_CONDENSER = register(
75 "energy_condenser",
76 new EnergyCondenserBlock(QuiltBlockSettings.copy(ENDER_CHEST))
77 );
78
64 public static void consume(BiConsumer<? super ResourceLocation, ? super Block> consumer) { 79 public static void consume(BiConsumer<? super ResourceLocation, ? super Block> consumer) {
65 data.forEach(consumer); 80 data.forEach(consumer);
66 } 81 }
@@ -78,6 +93,9 @@ public final class ErisAlchemyRegistry {
78 93
79 public static final Item ALCHEMICAL_CHEST = 94 public static final Item ALCHEMICAL_CHEST =
80 register(Blocks.ALCHEMICAL_CHEST, new QuiltItemSettings().rarity(Rarity.RARE)); 95 register(Blocks.ALCHEMICAL_CHEST, new QuiltItemSettings().rarity(Rarity.RARE));
96 @SuppressWarnings("unused")
97 public static final Item ENERGY_CONDENSER =
98 register(Blocks.ENERGY_CONDENSER, new QuiltItemSettings().rarity(Rarity.EPIC));
81 public static final Item LOW_COVALENCE_DUST = 99 public static final Item LOW_COVALENCE_DUST =
82 register("low_covalence_dust", new Item(new QuiltItemSettings().rarity(Rarity.COMMON))); 100 register("low_covalence_dust", new Item(new QuiltItemSettings().rarity(Rarity.COMMON)));
83 @SuppressWarnings("unused") 101 @SuppressWarnings("unused")
@@ -112,6 +130,8 @@ public final class ErisAlchemyRegistry {
112 130
113 public static final MenuType<AlchemicalChestMenu> ALCHEMICAL_CHEST = 131 public static final MenuType<AlchemicalChestMenu> ALCHEMICAL_CHEST =
114 register("alchemy_chest", AlchemicalChestMenu::new); 132 register("alchemy_chest", AlchemicalChestMenu::new);
133 public static final ExtendedScreenHandlerType<EnergyCondenserMenu> ENERGY_CONDENSER =
134 registerExt("energy_condenser", EnergyCondenserMenu::new);
115 135
116 public static void consume(BiConsumer<? super ResourceLocation, ? super MenuType<?>> consumer) { 136 public static void consume(BiConsumer<? super ResourceLocation, ? super MenuType<?>> consumer) {
117 data.forEach(consumer); 137 data.forEach(consumer);
@@ -121,12 +141,32 @@ public final class ErisAlchemyRegistry {
121 String id, 141 String id,
122 MenuType.MenuSupplier<T> supplier 142 MenuType.MenuSupplier<T> supplier
123 ) { 143 ) {
124 var menuType = new MenuType<>(supplier, FeatureFlags.VANILLA_SET); 144 return registerCommon(id, new MenuType<>(supplier, FeatureFlags.VANILLA_SET));
145 }
146
147 private static <T extends AbstractContainerMenu> ExtendedScreenHandlerType<T> registerExt(
148 String id,
149 ExtendedScreenHandlerType.ExtendedFactory<T> supplier
150 ) {
151 return registerCommon(id, new ExtendedScreenHandlerType<>(supplier));
152 }
153
154 private static <M extends AbstractContainerMenu, T extends MenuType<? extends M>> T registerCommon(
155 String id,
156 T menuType
157 ) {
125 data.put(new ResourceLocation(ErisAlchemy.ID, id), menuType); 158 data.put(new ResourceLocation(ErisAlchemy.ID, id), menuType);
126 return menuType; 159 return menuType;
127 } 160 }
128 } 161 }
129 162
163 public static final class NetworkingConstants {
164 private NetworkingConstants() {}
165
166 public static final ResourceLocation UPDATE_SYNCED_VALUE
167 = new ResourceLocation(ErisAlchemy.ID, "update_synced_value");
168 }
169
130 public static final class RecipeSerializers { 170 public static final class RecipeSerializers {
131 private RecipeSerializers() {} 171 private RecipeSerializers() {}
132 172
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/block/AlchemicalChestBlock.java b/src/main/java/lv/enes/mc/eris_alchemy/block/AlchemicalChestBlock.java
index d50ee77..eb7cb6e 100644
--- a/src/main/java/lv/enes/mc/eris_alchemy/block/AlchemicalChestBlock.java
+++ b/src/main/java/lv/enes/mc/eris_alchemy/block/AlchemicalChestBlock.java
@@ -3,15 +3,15 @@ package lv.enes.mc.eris_alchemy.block;
3import jakarta.annotation.Nonnull; 3import jakarta.annotation.Nonnull;
4import jakarta.annotation.Nullable; 4import jakarta.annotation.Nullable;
5import lv.enes.mc.eris_alchemy.ErisAlchemyRegistry; 5import lv.enes.mc.eris_alchemy.ErisAlchemyRegistry;
6import lv.enes.mc.eris_alchemy.block.entity.AlchemicalChestBlockEntity; 6import lv.enes.mc.eris_alchemy.block.entity.AlchemicalChestEntity;
7import net.minecraft.core.BlockPos; 7import net.minecraft.core.BlockPos;
8import net.minecraft.network.chat.Component; 8import net.minecraft.network.chat.Component;
9import net.minecraft.world.level.block.entity.BlockEntity; 9import net.minecraft.world.level.block.entity.BlockEntity;
10import net.minecraft.world.level.block.state.BlockState; 10import net.minecraft.world.level.block.state.BlockState;
11 11
12public class AlchemicalChestBlock extends ChestLikeBlock<AlchemicalChestBlockEntity> 12public class AlchemicalChestBlock extends ChestLikeBlock<AlchemicalChestEntity> {
13{ 13 public static final Component CONTAINER_TITLE
14 public static final Component CONTAINER_TITLE = Component.translatable("container.eris_alchemy.alchemical_chest"); 14 = Component.translatable("container.eris_alchemy.alchemical_chest");
15 15
16 public AlchemicalChestBlock(Properties properties) { 16 public AlchemicalChestBlock(Properties properties) {
17 super(properties, () -> ErisAlchemyRegistry.BlockEntities.ALCHEMICAL_CHEST); 17 super(properties, () -> ErisAlchemyRegistry.BlockEntities.ALCHEMICAL_CHEST);
@@ -26,6 +26,6 @@ public class AlchemicalChestBlock extends ChestLikeBlock<AlchemicalChestBlockEnt
26 @Nullable 26 @Nullable
27 @Override 27 @Override
28 public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { 28 public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
29 return new AlchemicalChestBlockEntity(pos, state); 29 return new AlchemicalChestEntity(pos, state);
30 } 30 }
31} 31}
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/block/ChestLikeBlock.java b/src/main/java/lv/enes/mc/eris_alchemy/block/ChestLikeBlock.java
index e50563a..ade24fb 100644
--- a/src/main/java/lv/enes/mc/eris_alchemy/block/ChestLikeBlock.java
+++ b/src/main/java/lv/enes/mc/eris_alchemy/block/ChestLikeBlock.java
@@ -1,7 +1,7 @@
1package lv.enes.mc.eris_alchemy.block; 1package lv.enes.mc.eris_alchemy.block;
2 2
3import jakarta.annotation.Nonnull; 3import jakarta.annotation.Nonnull;
4import lv.enes.mc.eris_alchemy.block.entity.ChestLikeBlockEntity; 4import lv.enes.mc.eris_alchemy.block.entity.ChestLikeEntity;
5import net.minecraft.core.BlockPos; 5import net.minecraft.core.BlockPos;
6import net.minecraft.core.Direction; 6import net.minecraft.core.Direction;
7import net.minecraft.network.chat.Component; 7import net.minecraft.network.chat.Component;
@@ -33,7 +33,7 @@ import net.minecraft.world.phys.shapes.VoxelShape;
33 33
34import java.util.function.Supplier; 34import java.util.function.Supplier;
35 35
36public abstract class ChestLikeBlock<E extends ChestLikeBlockEntity> 36public abstract class ChestLikeBlock<E extends ChestLikeEntity>
37 extends AbstractChestBlock<E> 37 extends AbstractChestBlock<E>
38 implements SimpleWaterloggedBlock 38 implements SimpleWaterloggedBlock
39{ 39{
@@ -85,7 +85,7 @@ public abstract class ChestLikeBlock<E extends ChestLikeBlockEntity>
85 85
86 @Override 86 @Override
87 public MenuProvider getMenuProvider(BlockState state, Level world, BlockPos pos) { 87 public MenuProvider getMenuProvider(BlockState state, Level world, BlockPos pos) {
88 if (world.getBlockEntity(pos) instanceof ChestLikeBlockEntity entity) { 88 if (world.getBlockEntity(pos) instanceof ChestLikeEntity entity) {
89 return new SimpleMenuProvider(entity, getContainerTitle()); 89 return new SimpleMenuProvider(entity, getContainerTitle());
90 } 90 }
91 return null; 91 return null;
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/block/EnergyCondenserBlock.java b/src/main/java/lv/enes/mc/eris_alchemy/block/EnergyCondenserBlock.java
new file mode 100644
index 0000000..86ac061
--- /dev/null
+++ b/src/main/java/lv/enes/mc/eris_alchemy/block/EnergyCondenserBlock.java
@@ -0,0 +1,56 @@
1package lv.enes.mc.eris_alchemy.block;
2
3import jakarta.annotation.Nonnull;
4import jakarta.annotation.Nullable;
5import lv.enes.mc.eris_alchemy.EMC;
6import lv.enes.mc.eris_alchemy.EmcStorage;
7import lv.enes.mc.eris_alchemy.ErisAlchemyRegistry;
8import lv.enes.mc.eris_alchemy.block.entity.EnergyCondenserEntity;
9import net.minecraft.core.BlockPos;
10import net.minecraft.nbt.CompoundTag;
11import net.minecraft.network.chat.Component;
12import net.minecraft.world.item.ItemStack;
13import net.minecraft.world.item.TooltipFlag;
14import net.minecraft.world.level.BlockGetter;
15import net.minecraft.world.level.block.entity.BlockEntity;
16import net.minecraft.world.level.block.state.BlockState;
17
18import java.util.List;
19
20public class EnergyCondenserBlock extends ChestLikeBlock<EnergyCondenserEntity> implements EmcStorage {
21 public static final Component CONTAINER_TITLE
22 = Component.translatable("container.eris_alchemy.energy_condenser");
23
24 public EnergyCondenserBlock(Properties properties) {
25 super(properties, () -> ErisAlchemyRegistry.BlockEntities.ENERGY_CONDENSER);
26 }
27
28 @Override
29 public void appendHoverText(
30 ItemStack stack,
31 @Nullable BlockGetter world,
32 List<Component> tooltip,
33 TooltipFlag options
34 ) {
35 if (getStoredEmc(stack) >= 0.1) {
36 tooltip.add(Component.literal("Stored EMC: %s".formatted(EMC.formatEmc(getStoredEmc(stack)))));
37 }
38 }
39
40 @Override
41 @Nonnull
42 protected Component getContainerTitle() {
43 return CONTAINER_TITLE;
44 }
45
46 @Override
47 public double getStoredEmc(ItemStack stack, CompoundTag blockEntityData) {
48 return blockEntityData.getDouble("stored_emc");
49 }
50
51 @Nullable
52 @Override
53 public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
54 return new EnergyCondenserEntity(pos, state);
55 }
56}
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/block/entity/AlchemicalChestBlockEntity.java b/src/main/java/lv/enes/mc/eris_alchemy/block/entity/AlchemicalChestEntity.java
index bac49b6..38ed902 100644
--- a/src/main/java/lv/enes/mc/eris_alchemy/block/entity/AlchemicalChestBlockEntity.java
+++ b/src/main/java/lv/enes/mc/eris_alchemy/block/entity/AlchemicalChestEntity.java
@@ -3,37 +3,30 @@ package lv.enes.mc.eris_alchemy.block.entity;
3import jakarta.annotation.Nonnull; 3import jakarta.annotation.Nonnull;
4import lv.enes.mc.eris_alchemy.ErisAlchemyRegistry; 4import lv.enes.mc.eris_alchemy.ErisAlchemyRegistry;
5import lv.enes.mc.eris_alchemy.menu.AlchemicalChestMenu; 5import lv.enes.mc.eris_alchemy.menu.AlchemicalChestMenu;
6import lv.enes.mc.eris_alchemy.menu.ChestLikeBlockMenu; 6import lv.enes.mc.eris_alchemy.menu.ChestLikeMenu;
7import net.minecraft.core.BlockPos; 7import net.minecraft.core.BlockPos;
8import net.minecraft.core.NonNullList; 8import net.minecraft.core.NonNullList;
9import net.minecraft.network.chat.Component;
10import net.minecraft.world.entity.player.Inventory; 9import net.minecraft.world.entity.player.Inventory;
11import net.minecraft.world.item.ItemStack; 10import net.minecraft.world.item.ItemStack;
12import net.minecraft.world.level.block.Block; 11import net.minecraft.world.level.block.Block;
13import net.minecraft.world.level.block.state.BlockState; 12import net.minecraft.world.level.block.state.BlockState;
14 13
15public class AlchemicalChestBlockEntity extends ChestLikeBlockEntity { 14public class AlchemicalChestEntity extends ChestLikeEntity {
16 private final static int WIDTH = 13; 15 private final static int WIDTH = 13;
17 private final static int HEIGHT = 8; 16 private final static int HEIGHT = 8;
18 17
19 private final NonNullList<ItemStack> items = NonNullList.withSize(WIDTH * HEIGHT, ItemStack.EMPTY); 18 private final NonNullList<ItemStack> items = NonNullList.withSize(WIDTH * HEIGHT, ItemStack.EMPTY);
20 19
21 public AlchemicalChestBlockEntity(BlockPos pos, BlockState state) { 20 public AlchemicalChestEntity(BlockPos pos, BlockState state) {
22 super(ErisAlchemyRegistry.BlockEntities.ALCHEMICAL_CHEST, pos, state); 21 super(ErisAlchemyRegistry.BlockEntities.ALCHEMICAL_CHEST, pos, state);
23 } 22 }
24 23
25 @Nonnull 24 @Nonnull
26 @Override 25 @Override
27 protected ChestLikeBlockMenu createMenu(int syncId, Inventory playerInventory) { 26 protected ChestLikeMenu createMenu(int syncId, Inventory playerInventory) {
28 return new AlchemicalChestMenu(syncId, playerInventory, this); 27 return new AlchemicalChestMenu(syncId, playerInventory, this);
29 } 28 }
30 29
31 @Nonnull
32 @Override
33 protected Component getDefaultName() {
34 return Component.translatable("container.eris_alchemy.alchemical_chest");
35 }
36
37 @Override 30 @Override
38 protected NonNullList<ItemStack> getItems() { 31 protected NonNullList<ItemStack> getItems() {
39 return items; 32 return items;
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/block/entity/ChestLikeBlockEntity.java b/src/main/java/lv/enes/mc/eris_alchemy/block/entity/ChestLikeEntity.java
index 48b3ad7..362b054 100644
--- a/src/main/java/lv/enes/mc/eris_alchemy/block/entity/ChestLikeBlockEntity.java
+++ b/src/main/java/lv/enes/mc/eris_alchemy/block/entity/ChestLikeEntity.java
@@ -2,10 +2,11 @@ package lv.enes.mc.eris_alchemy.block.entity;
2 2
3import jakarta.annotation.Nonnull; 3import jakarta.annotation.Nonnull;
4import jakarta.annotation.Nullable; 4import jakarta.annotation.Nullable;
5import lv.enes.mc.eris_alchemy.menu.ChestLikeBlockMenu; 5import lv.enes.mc.eris_alchemy.menu.ChestLikeMenu;
6import net.minecraft.core.BlockPos; 6import net.minecraft.core.BlockPos;
7import net.minecraft.core.NonNullList; 7import net.minecraft.core.NonNullList;
8import net.minecraft.nbt.CompoundTag; 8import net.minecraft.nbt.CompoundTag;
9import net.minecraft.network.chat.Component;
9import net.minecraft.sounds.SoundEvents; 10import net.minecraft.sounds.SoundEvents;
10import net.minecraft.sounds.SoundSource; 11import net.minecraft.sounds.SoundSource;
11import net.minecraft.world.Container; 12import net.minecraft.world.Container;
@@ -17,19 +18,19 @@ import net.minecraft.world.level.block.Block;
17import net.minecraft.world.level.block.entity.*; 18import net.minecraft.world.level.block.entity.*;
18import net.minecraft.world.level.block.state.BlockState; 19import net.minecraft.world.level.block.state.BlockState;
19 20
20public abstract class ChestLikeBlockEntity extends BaseContainerBlockEntity implements LidBlockEntity { 21public abstract class ChestLikeEntity extends BaseContainerBlockEntity implements LidBlockEntity {
21 protected static final int EVENT_INTERACTED = 1; 22 protected static final int EVENT_INTERACTED = 1;
22 23
23 protected final ChestLidController lidController = new ChestLidController(); 24 protected final ChestLidController lidController = new ChestLidController();
24 protected final ContainerOpenersCounter openersCounter = new ContainerOpenersCounter() { 25 protected final ContainerOpenersCounter openersCounter = new ContainerOpenersCounter() {
25 @Override 26 @Override
26 protected void onOpen(Level world, BlockPos pos, BlockState state) { 27 protected void onOpen(Level world, BlockPos pos, BlockState state) {
27 ChestLikeBlockEntity.this.onOpen(world, pos); 28 ChestLikeEntity.this.onOpen(world, pos);
28 } 29 }
29 30
30 @Override 31 @Override
31 protected void onClose(Level world, BlockPos pos, BlockState state) { 32 protected void onClose(Level world, BlockPos pos, BlockState state) {
32 ChestLikeBlockEntity.this.onClose(world, pos); 33 ChestLikeEntity.this.onClose(world, pos);
33 } 34 }
34 35
35 @Override 36 @Override
@@ -39,15 +40,15 @@ public abstract class ChestLikeBlockEntity extends BaseContainerBlockEntity impl
39 40
40 @Override 41 @Override
41 protected boolean isOwnContainer(Player player) { 42 protected boolean isOwnContainer(Player player) {
42 if (player.containerMenu instanceof ChestLikeBlockMenu menu) { 43 if (player.containerMenu instanceof ChestLikeMenu menu) {
43 return menu.getContainer() == ChestLikeBlockEntity.this; 44 return menu.getContainer() == ChestLikeEntity.this;
44 } 45 }
45 return false; 46 return false;
46 } 47 }
47 }; 48 };
48 49
49 public ChestLikeBlockEntity( 50 public ChestLikeEntity(
50 BlockEntityType<? extends ChestLikeBlockEntity> type, 51 BlockEntityType<? extends ChestLikeEntity> type,
51 BlockPos pos, 52 BlockPos pos,
52 BlockState state 53 BlockState state
53 ) { 54 ) {
@@ -69,6 +70,12 @@ public abstract class ChestLikeBlockEntity extends BaseContainerBlockEntity impl
69 70
70 @Nonnull 71 @Nonnull
71 @Override 72 @Override
73 protected Component getDefaultName() {
74 return getBlockState().getBlock().getName();
75 }
76
77 @Nonnull
78 @Override
72 public ItemStack getItem(int slot) { 79 public ItemStack getItem(int slot) {
73 return getItems().get(slot); 80 return getItems().get(slot);
74 } 81 }
@@ -134,7 +141,7 @@ public abstract class ChestLikeBlockEntity extends BaseContainerBlockEntity impl
134 public ItemStack removeItem(int slot, int amount) { 141 public ItemStack removeItem(int slot, int amount) {
135 var stack = ContainerHelper.removeItem(getItems(), slot, amount); 142 var stack = ContainerHelper.removeItem(getItems(), slot, amount);
136 if (!stack.isEmpty()) { 143 if (!stack.isEmpty()) {
137 this.setChanged(); 144 setChanged();
138 } 145 }
139 return stack; 146 return stack;
140 } 147 }
@@ -157,7 +164,7 @@ public abstract class ChestLikeBlockEntity extends BaseContainerBlockEntity impl
157 if (stack.getCount() > getMaxStackSize()) { 164 if (stack.getCount() > getMaxStackSize()) {
158 stack.setCount(getMaxStackSize()); 165 stack.setCount(getMaxStackSize());
159 } 166 }
160 this.setChanged(); 167 setChanged();
161 } 168 }
162 169
163 @Override 170 @Override
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/block/entity/EnergyCondenserEntity.java b/src/main/java/lv/enes/mc/eris_alchemy/block/entity/EnergyCondenserEntity.java
new file mode 100644
index 0000000..dfe07a4
--- /dev/null
+++ b/src/main/java/lv/enes/mc/eris_alchemy/block/entity/EnergyCondenserEntity.java
@@ -0,0 +1,143 @@
1package lv.enes.mc.eris_alchemy.block.entity;
2
3import jakarta.annotation.Nonnull;
4import lv.enes.mc.eris_alchemy.EMC;
5import lv.enes.mc.eris_alchemy.ErisAlchemyRegistry;
6import lv.enes.mc.eris_alchemy.menu.ChestLikeMenu;
7import lv.enes.mc.eris_alchemy.menu.EnergyCondenserMenu;
8import lv.enes.mc.eris_alchemy.utils.ContainerOpenersCounterUtil;
9import lv.enes.mc.eris_alchemy.utils.SyncedValue.SyncedDouble;
10import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory;
11import net.minecraft.core.BlockPos;
12import net.minecraft.core.NonNullList;
13import net.minecraft.nbt.CompoundTag;
14import net.minecraft.network.FriendlyByteBuf;
15import net.minecraft.server.level.ServerPlayer;
16import net.minecraft.world.entity.player.Inventory;
17import net.minecraft.world.item.ItemStack;
18import net.minecraft.world.level.Level;
19import net.minecraft.world.level.block.Block;
20import net.minecraft.world.level.block.state.BlockState;
21
22import java.util.stream.IntStream;
23
24public class EnergyCondenserEntity extends ChestLikeEntity implements ExtendedScreenHandlerFactory {
25 private final static int WIDTH = 13;
26 private final static int HEIGHT = 7;
27
28 private final NonNullList<ItemStack> items = NonNullList.withSize(WIDTH * HEIGHT + 1, ItemStack.EMPTY);
29
30 public final SyncedDouble storedEmc = new SyncedDouble(0);
31
32 public EnergyCondenserEntity(BlockPos pos, BlockState state) {
33 super(ErisAlchemyRegistry.BlockEntities.ENERGY_CONDENSER, pos, state);
34 }
35
36 @Nonnull
37 @Override
38 protected ChestLikeMenu createMenu(int syncId, Inventory playerInventory) {
39 return new EnergyCondenserMenu(syncId, playerInventory, this);
40 }
41
42 @Override
43 protected NonNullList<ItemStack> getItems() {
44 return items;
45 }
46
47 @Override
48 protected Block getParent() {
49 return ErisAlchemyRegistry.Blocks.ENERGY_CONDENSER;
50 }
51
52 public double getStoredEmc() {
53 return storedEmc.getValue();
54 }
55
56 public SyncedDouble getStoredEmcSyncer() {
57 return storedEmc;
58 }
59
60 @Override
61 public void load(CompoundTag nbt) {
62 super.load(nbt);
63 storedEmc.setValue(nbt.getDouble("stored_emc"));
64 }
65
66 @Override
67 protected void saveAdditional(CompoundTag nbt) {
68 super.saveAdditional(nbt);
69 nbt.putDouble("stored_emc", storedEmc.getValue());
70 }
71
72 public void setStoredEmc(double storedEmc) {
73 this.storedEmc.setValue(storedEmc);
74 setChanged();
75 }
76
77 @Override
78 public void tick(Level world, BlockPos pos, BlockState state) {
79 super.tick(world, pos, state);
80 EMC.getInstance(world).get(items.get(0)).ifPresent(cost -> {
81 tryConsumeEmc(world, cost);
82 tryCloneTemplate(cost);
83 });
84
85 this.storedEmc.syncIfChanged(ContainerOpenersCounterUtil.getOpeners(openersCounter));
86 }
87
88 @Override
89 public void writeScreenOpeningData(ServerPlayer player, FriendlyByteBuf buf) {
90 storedEmc.serialize(buf);
91 }
92
93 private void tryCloneTemplate(double cost) {
94 if (cost > getStoredEmc()) {
95 return;
96 }
97
98 var template = items.get(0);
99
100 items.stream()
101 .skip(1) // skip template
102 .filter(stack -> ItemStack.isSameItemSameTags(template, stack))
103 .filter(stack -> stack.getCount() < getMaxStackSize() && stack.getCount() < stack.getMaxStackSize())
104 .findFirst()
105 .ifPresentOrElse(
106 stack -> {
107 stack.setCount(stack.getCount() + 1);
108 setStoredEmc(getStoredEmc() - cost);
109 setChanged();
110 },
111 () -> IntStream.range(1, items.size())
112 .filter(i -> items.get(i).isEmpty())
113 .findFirst()
114 .ifPresent(emptySlot -> {
115 items.set(emptySlot, template.copyWithCount(1));
116 setStoredEmc(getStoredEmc() - cost);
117 setChanged();
118 })
119 );
120 }
121
122 private void tryConsumeEmc(Level world, double cost) {
123 if (cost <= getStoredEmc()) {
124 return;
125 }
126
127 var emc = EMC.getInstance(world);
128 var template = items.get(0);
129 var sacrifice = items.stream()
130 .skip(1) // skip the template
131 .filter(stack -> !ItemStack.isSameItemSameTags(template, stack))
132 .flatMap(stack -> emc.get(stack)
133 .stream()
134 .mapToObj(emcValue -> new StackEmcPair(stack, emcValue)))
135 .findFirst();
136 sacrifice.ifPresent(pair -> {
137 pair.stack.setCount(pair.stack.getCount() - 1);
138 setStoredEmc(getStoredEmc() + pair.emc());
139 });
140 }
141
142 private record StackEmcPair(ItemStack stack, double emc) {}
143}
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/client/ChestLikeScreen.java b/src/main/java/lv/enes/mc/eris_alchemy/client/ChestLikeScreen.java
index c98b356..b8967b1 100644
--- a/src/main/java/lv/enes/mc/eris_alchemy/client/ChestLikeScreen.java
+++ b/src/main/java/lv/enes/mc/eris_alchemy/client/ChestLikeScreen.java
@@ -1,13 +1,13 @@
1package lv.enes.mc.eris_alchemy.client; 1package lv.enes.mc.eris_alchemy.client;
2 2
3import lv.enes.mc.eris_alchemy.menu.ChestLikeBlockMenu; 3import lv.enes.mc.eris_alchemy.menu.ChestLikeMenu;
4import net.minecraft.client.gui.GuiGraphics; 4import net.minecraft.client.gui.GuiGraphics;
5import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; 5import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
6import net.minecraft.network.chat.Component; 6import net.minecraft.network.chat.Component;
7import net.minecraft.resources.ResourceLocation; 7import net.minecraft.resources.ResourceLocation;
8import net.minecraft.world.entity.player.Inventory; 8import net.minecraft.world.entity.player.Inventory;
9 9
10public abstract class ChestLikeScreen<M extends ChestLikeBlockMenu> extends AbstractContainerScreen<M> { 10public abstract class ChestLikeScreen<M extends ChestLikeMenu> extends AbstractContainerScreen<M> {
11 public ChestLikeScreen(M menu, Inventory inventory, Component title) { 11 public ChestLikeScreen(M menu, Inventory inventory, Component title) {
12 super(menu, inventory, title); 12 super(menu, inventory, title);
13 13
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/client/EnergyCondenserScreen.java b/src/main/java/lv/enes/mc/eris_alchemy/client/EnergyCondenserScreen.java
new file mode 100644
index 0000000..b6762c8
--- /dev/null
+++ b/src/main/java/lv/enes/mc/eris_alchemy/client/EnergyCondenserScreen.java
@@ -0,0 +1,46 @@
1package lv.enes.mc.eris_alchemy.client;
2
3import lv.enes.mc.eris_alchemy.EMC;
4import lv.enes.mc.eris_alchemy.ErisAlchemy;
5import lv.enes.mc.eris_alchemy.menu.EnergyCondenserMenu;
6import net.minecraft.client.gui.GuiGraphics;
7import net.minecraft.network.chat.Component;
8import net.minecraft.resources.ResourceLocation;
9import net.minecraft.world.entity.player.Inventory;
10
11public class EnergyCondenserScreen extends ChestLikeScreen<EnergyCondenserMenu> {
12 public static final ResourceLocation TEXTURE =
13 new ResourceLocation(ErisAlchemy.ID, "textures/gui/container/energy_condenser.png");
14
15 public static final int TEXTURE_WIDTH = 248;
16 public static final int TEXTURE_HEIGHT = 237;
17
18 public EnergyCondenserScreen(EnergyCondenserMenu menu, Inventory inventory, Component title) {
19 super(menu, inventory, title);
20 }
21
22 @Override
23 protected ResourceLocation getTexture() {
24 return TEXTURE;
25 }
26
27 @Override
28 protected int getTextureWidth() {
29 return TEXTURE_WIDTH;
30 }
31
32 @Override
33 protected int getTextureHeight() {
34 return TEXTURE_HEIGHT;
35 }
36
37 @Override
38 protected void renderLabels(GuiGraphics graphics, int mouseX, int mouseY) {
39 graphics.drawString(font, EMC.formatEmc(menu.getStoredEmc()), 28, 6, 0xFFFFFF);
40 }
41
42 @Override
43 protected boolean shouldRenderLabels() {
44 return false;
45 }
46}
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/client/ErisAlchemyClient.java b/src/main/java/lv/enes/mc/eris_alchemy/client/ErisAlchemyClient.java
index 86cc467..a69d2e1 100644
--- a/src/main/java/lv/enes/mc/eris_alchemy/client/ErisAlchemyClient.java
+++ b/src/main/java/lv/enes/mc/eris_alchemy/client/ErisAlchemyClient.java
@@ -9,8 +9,6 @@ import org.quiltmc.loader.api.ModContainer;
9import org.quiltmc.qsl.base.api.entrypoint.client.ClientModInitializer; 9import org.quiltmc.qsl.base.api.entrypoint.client.ClientModInitializer;
10import org.quiltmc.qsl.tooltip.api.client.ItemTooltipCallback; 10import org.quiltmc.qsl.tooltip.api.client.ItemTooltipCallback;
11 11
12import java.text.DecimalFormat;
13
14@SuppressWarnings("unused") 12@SuppressWarnings("unused")
15public class ErisAlchemyClient implements ClientModInitializer { 13public class ErisAlchemyClient implements ClientModInitializer {
16 @Override 14 @Override
@@ -19,14 +17,10 @@ public class ErisAlchemyClient implements ClientModInitializer {
19 ErisAlchemyClientRegistry.ItemRenderers.consume(BuiltinItemRendererRegistry.INSTANCE::register); 17 ErisAlchemyClientRegistry.ItemRenderers.consume(BuiltinItemRendererRegistry.INSTANCE::register);
20 ErisAlchemyClientRegistry.MenuScreens.consume(MenuScreens::register); 18 ErisAlchemyClientRegistry.MenuScreens.consume(MenuScreens::register);
21 19
22 // MenuScreens.register(ErisAlchemyRegistry.Menus.ALCHEMICAL_CHEST, AlchemicalChestScreen::new);
23
24 var doubleFormat = new DecimalFormat("0");
25 doubleFormat.setMaximumFractionDigits(1);
26 ItemTooltipCallback.EVENT.register((stack, player, context, tooltip) -> { 20 ItemTooltipCallback.EVENT.register((stack, player, context, tooltip) -> {
27 var world = player == null ? null : player.level(); 21 var world = player == null ? null : player.level();
28 var emc = EMC.getInstance(world).get(stack.getItem()); 22 var emc = EMC.getInstance(world).get(stack);
29 emc.ifPresent(value -> tooltip.add(Component.literal("EMC %s".formatted(doubleFormat.format(value))))); 23 emc.ifPresent(value -> tooltip.add(Component.literal("EMC %s".formatted(EMC.formatEmc(value)))));
30 }); 24 });
31 } 25 }
32} 26}
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/client/ErisAlchemyClientRegistry.java b/src/main/java/lv/enes/mc/eris_alchemy/client/ErisAlchemyClientRegistry.java
index 3680fd5..30c6690 100644
--- a/src/main/java/lv/enes/mc/eris_alchemy/client/ErisAlchemyClientRegistry.java
+++ b/src/main/java/lv/enes/mc/eris_alchemy/client/ErisAlchemyClientRegistry.java
@@ -1,6 +1,7 @@
1package lv.enes.mc.eris_alchemy.client; 1package lv.enes.mc.eris_alchemy.client;
2 2
3import lv.enes.mc.eris_alchemy.block.entity.AlchemicalChestBlockEntity; 3import lv.enes.mc.eris_alchemy.block.entity.AlchemicalChestEntity;
4import lv.enes.mc.eris_alchemy.block.entity.EnergyCondenserEntity;
4import net.fabricmc.fabric.api.client.rendering.v1.BuiltinItemRendererRegistry.DynamicItemRenderer; 5import net.fabricmc.fabric.api.client.rendering.v1.BuiltinItemRendererRegistry.DynamicItemRenderer;
5import net.minecraft.client.gui.screens.MenuScreens.ScreenConstructor; 6import net.minecraft.client.gui.screens.MenuScreens.ScreenConstructor;
6import net.minecraft.client.gui.screens.Screen; 7import net.minecraft.client.gui.screens.Screen;
@@ -54,6 +55,7 @@ public final class ErisAlchemyClientRegistry {
54 55
55 static { 56 static {
56 register(BlockEntities.ALCHEMICAL_CHEST, ChestRenderer::new); 57 register(BlockEntities.ALCHEMICAL_CHEST, ChestRenderer::new);
58 register(BlockEntities.ENERGY_CONDENSER, ChestRenderer::new);
57 } 59 }
58 } 60 }
59 61
@@ -73,7 +75,11 @@ public final class ErisAlchemyClientRegistry {
73 static { 75 static {
74 register( 76 register(
75 Items.ALCHEMICAL_CHEST, 77 Items.ALCHEMICAL_CHEST,
76 new ChestItemRenderer<>(Blocks.ALCHEMICAL_CHEST, AlchemicalChestBlockEntity::new)::renderByItem 78 new ChestItemRenderer<>(Blocks.ALCHEMICAL_CHEST, AlchemicalChestEntity::new)::renderByItem
79 );
80 register(
81 Items.ENERGY_CONDENSER,
82 new ChestItemRenderer<>(Blocks.ENERGY_CONDENSER, EnergyCondenserEntity::new)::renderByItem
77 ); 83 );
78 } 84 }
79 } 85 }
@@ -111,6 +117,7 @@ public final class ErisAlchemyClientRegistry {
111 117
112 static { 118 static {
113 register(Menus.ALCHEMICAL_CHEST, AlchemicalChestScreen::new); 119 register(Menus.ALCHEMICAL_CHEST, AlchemicalChestScreen::new);
120 register(Menus.ENERGY_CONDENSER, EnergyCondenserScreen::new);
114 } 121 }
115 } 122 }
116} 123}
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/client/ErisAlchemyMaterials.java b/src/main/java/lv/enes/mc/eris_alchemy/client/ErisAlchemyMaterials.java
index 15d9209..686d83f 100644
--- a/src/main/java/lv/enes/mc/eris_alchemy/client/ErisAlchemyMaterials.java
+++ b/src/main/java/lv/enes/mc/eris_alchemy/client/ErisAlchemyMaterials.java
@@ -11,5 +11,10 @@ public final class ErisAlchemyMaterials {
11 new ResourceLocation(ErisAlchemy.ID, "entity/chest/alchemical_chest") 11 new ResourceLocation(ErisAlchemy.ID, "entity/chest/alchemical_chest")
12 ); 12 );
13 13
14 public static final Material ENERGY_CONDENSER = new Material(
15 Sheets.CHEST_SHEET,
16 new ResourceLocation(ErisAlchemy.ID, "entity/chest/energy_condenser")
17 );
18
14 private ErisAlchemyMaterials() {} 19 private ErisAlchemyMaterials() {}
15} 20}
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/menu/AlchemicalChestMenu.java b/src/main/java/lv/enes/mc/eris_alchemy/menu/AlchemicalChestMenu.java
index 1dc3364..35db476 100644
--- a/src/main/java/lv/enes/mc/eris_alchemy/menu/AlchemicalChestMenu.java
+++ b/src/main/java/lv/enes/mc/eris_alchemy/menu/AlchemicalChestMenu.java
@@ -6,7 +6,7 @@ import net.minecraft.world.SimpleContainer;
6import net.minecraft.world.entity.player.Inventory; 6import net.minecraft.world.entity.player.Inventory;
7import net.minecraft.world.inventory.Slot; 7import net.minecraft.world.inventory.Slot;
8 8
9public class AlchemicalChestMenu extends ChestLikeBlockMenu { 9public class AlchemicalChestMenu extends ChestLikeMenu {
10 private static final int WIDTH = 13; 10 private static final int WIDTH = 13;
11 private static final int HEIGHT = 8; 11 private static final int HEIGHT = 8;
12 12
@@ -24,25 +24,13 @@ public class AlchemicalChestMenu extends ChestLikeBlockMenu {
24 var y_off = 8; 24 var y_off = 8;
25 25
26 for (var y = 0; y < HEIGHT; y++) { 26 for (var y = 0; y < HEIGHT; y++) {
27 for (var x = 0; x < WIDTH; x++ ) { 27 for (var x = 0; x < WIDTH; x++) {
28 addSlot(new Slot(container, y * WIDTH + x, x_off + x * 18, y_off + y * 18)); 28 addSlot(new Slot(container, y * WIDTH + x, x_off + x * 18, y_off + y * 18));
29 } 29 }
30 } 30 }
31 31
32 x_off = 44; 32 addPlayerInventorySlots(playerInventory, 44, 155);
33 y_off = 155; 33 addPlayerHotbarSlots(playerInventory, 44, 213);
34
35 for (var y = 0; y < 3; y++) {
36 for (var x = 0; x < 9; x++) {
37 addSlot(new Slot(playerInventory, y * 9 + x + 9, x_off + x * 18, y_off + y * 18));
38 }
39 }
40
41 y_off = 213;
42
43 for (var x = 0; x < 9; x++) {
44 addSlot(new Slot(playerInventory, x, x_off + x * 18, y_off));
45 }
46 } 34 }
47 35
48 @Override 36 @Override
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/menu/ChestLikeBlockMenu.java b/src/main/java/lv/enes/mc/eris_alchemy/menu/ChestLikeMenu.java
index 897abe9..e561f0d 100644
--- a/src/main/java/lv/enes/mc/eris_alchemy/menu/ChestLikeBlockMenu.java
+++ b/src/main/java/lv/enes/mc/eris_alchemy/menu/ChestLikeMenu.java
@@ -6,13 +6,14 @@ import net.minecraft.world.entity.player.Inventory;
6import net.minecraft.world.entity.player.Player; 6import net.minecraft.world.entity.player.Player;
7import net.minecraft.world.inventory.AbstractContainerMenu; 7import net.minecraft.world.inventory.AbstractContainerMenu;
8import net.minecraft.world.inventory.MenuType; 8import net.minecraft.world.inventory.MenuType;
9import net.minecraft.world.inventory.Slot;
9import net.minecraft.world.item.ItemStack; 10import net.minecraft.world.item.ItemStack;
10 11
11public abstract class ChestLikeBlockMenu extends AbstractContainerMenu { 12public abstract class ChestLikeMenu extends AbstractContainerMenu {
12 protected final Container container; 13 protected final Container container;
13 14
14 public ChestLikeBlockMenu( 15 public ChestLikeMenu(
15 MenuType<? extends ChestLikeBlockMenu> type, 16 MenuType<? extends ChestLikeMenu> type,
16 int syncId, 17 int syncId,
17 Inventory playerInventory, 18 Inventory playerInventory,
18 Container container 19 Container container
@@ -27,10 +28,42 @@ public abstract class ChestLikeBlockMenu extends AbstractContainerMenu {
27 protected abstract void addSlots(Inventory playerInventory); 28 protected abstract void addSlots(Inventory playerInventory);
28 protected abstract int getRequiredSize(); 29 protected abstract int getRequiredSize();
29 30
31 protected void addPlayerInventorySlots(Inventory playerInventory, int xOff, int yOff) {
32 for (var y = 0; y < 3; y++) {
33 for (var x = 0; x < 9; x++) {
34 addSlot(new Slot(playerInventory, y * 9 + x + 9, xOff + x * 18, yOff + y * 18));
35 }
36 }
37 }
38
39 protected void addPlayerHotbarSlots(Inventory playerInventory, int xOff, int yOff) {
40 for (var x = 0; x < 9; x++) {
41 addSlot(new Slot(playerInventory, x, xOff + x * 18, yOff));
42 }
43 }
44
30 public Container getContainer() { 45 public Container getContainer() {
31 return container; 46 return container;
32 } 47 }
33 48
49 protected int getQuickMoveStart() {
50 return 0;
51 }
52
53 protected int getQuickMoveEnd() {
54 return container.getContainerSize();
55 }
56
57 @Override
58 public void broadcastChanges() {
59 super.broadcastChanges();
60 }
61
62 @Override
63 public void broadcastFullState() {
64 super.broadcastFullState();
65 }
66
34 @Nonnull 67 @Nonnull
35 @Override 68 @Override
36 public ItemStack quickMoveStack(Player player, int fromIndex) { 69 public ItemStack quickMoveStack(Player player, int fromIndex) {
@@ -44,10 +77,11 @@ public abstract class ChestLikeBlockMenu extends AbstractContainerMenu {
44 newStack = originalStack.copy(); 77 newStack = originalStack.copy();
45 78
46 if (fromIndex < container.getContainerSize()) { 79 if (fromIndex < container.getContainerSize()) {
80 // In container, else player inv
47 if (!moveItemStackTo(originalStack, container.getContainerSize(), slots.size(), true)) { 81 if (!moveItemStackTo(originalStack, container.getContainerSize(), slots.size(), true)) {
48 return ItemStack.EMPTY; 82 return ItemStack.EMPTY;
49 } 83 }
50 } else if (!moveItemStackTo(originalStack, 0, container.getContainerSize(), false)) { 84 } else if (!moveItemStackTo(originalStack, getQuickMoveStart(), getQuickMoveEnd(), false)) {
51 return ItemStack.EMPTY; 85 return ItemStack.EMPTY;
52 } 86 }
53 87
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/menu/EnergyCondenserMenu.java b/src/main/java/lv/enes/mc/eris_alchemy/menu/EnergyCondenserMenu.java
new file mode 100644
index 0000000..bdba77b
--- /dev/null
+++ b/src/main/java/lv/enes/mc/eris_alchemy/menu/EnergyCondenserMenu.java
@@ -0,0 +1,60 @@
1package lv.enes.mc.eris_alchemy.menu;
2
3import lv.enes.mc.eris_alchemy.ErisAlchemyRegistry;
4import lv.enes.mc.eris_alchemy.block.entity.EnergyCondenserEntity;
5import lv.enes.mc.eris_alchemy.utils.SyncedValue.SyncedDouble;
6import net.minecraft.network.FriendlyByteBuf;
7import net.minecraft.world.Container;
8import net.minecraft.world.SimpleContainer;
9import net.minecraft.world.entity.player.Inventory;
10import net.minecraft.world.inventory.Slot;
11
12public class EnergyCondenserMenu extends ChestLikeMenu {
13 private static final int WIDTH = 13;
14 private static final int HEIGHT = 7;
15
16 private final SyncedDouble storedEmc;
17
18 public EnergyCondenserMenu(int syncId, Inventory playerInventory, FriendlyByteBuf buf) {
19 this(syncId, playerInventory, new SimpleContainer(WIDTH * HEIGHT + 1), SyncedDouble.deserialize(buf));
20 }
21
22 public EnergyCondenserMenu(int syncId, Inventory playerInventory, EnergyCondenserEntity entity) {
23 this(syncId, playerInventory, entity, entity.getStoredEmcSyncer());
24 }
25
26 public EnergyCondenserMenu(int syncId, Inventory playerInventory, Container container, SyncedDouble storedEmc) {
27 super(ErisAlchemyRegistry.Menus.ENERGY_CONDENSER, syncId, playerInventory, container);
28 this.storedEmc = storedEmc;
29 }
30
31 @Override
32 protected void addSlots(Inventory playerInventory) {
33 addSlot(new Slot(container, 0, 8, 7));
34
35 var xOff = 8;
36 var yOff = 28;
37 for (var y = 0; y < HEIGHT; y++) {
38 for (var x = 0; x < WIDTH; x++) {
39 addSlot(new Slot(container, y * WIDTH + x + 1, xOff + x * 18, yOff + y * 18));
40 }
41 }
42
43 addPlayerInventorySlots(playerInventory, 44, 157);
44 addPlayerHotbarSlots(playerInventory, 44, 213);
45 }
46
47 @Override
48 protected int getQuickMoveStart() {
49 return 1;
50 }
51
52 @Override
53 protected int getRequiredSize() {
54 return WIDTH * HEIGHT + 1;
55 }
56
57 public double getStoredEmc() {
58 return storedEmc.getValue();
59 }
60}
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/mixin/ContainerOpenersCounterMixin.java b/src/main/java/lv/enes/mc/eris_alchemy/mixin/ContainerOpenersCounterMixin.java
new file mode 100644
index 0000000..13b8669
--- /dev/null
+++ b/src/main/java/lv/enes/mc/eris_alchemy/mixin/ContainerOpenersCounterMixin.java
@@ -0,0 +1,56 @@
1package lv.enes.mc.eris_alchemy.mixin;
2
3import jakarta.annotation.Nonnull;
4import lv.enes.mc.eris_alchemy.utils.ContainerOpenersCounterUtil;
5import net.minecraft.core.BlockPos;
6import net.minecraft.server.level.ServerPlayer;
7import net.minecraft.world.entity.player.Player;
8import net.minecraft.world.level.Level;
9import net.minecraft.world.level.block.entity.ContainerOpenersCounter;
10import net.minecraft.world.level.block.state.BlockState;
11import net.minecraft.world.level.entity.EntityTypeTest;
12import net.minecraft.world.phys.AABB;
13import org.spongepowered.asm.mixin.Mixin;
14import org.spongepowered.asm.mixin.Shadow;
15import org.spongepowered.asm.mixin.Unique;
16import org.spongepowered.asm.mixin.injection.At;
17import org.spongepowered.asm.mixin.injection.Inject;
18import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
19
20import java.util.List;
21import java.util.Map;
22import java.util.WeakHashMap;
23
24@Mixin(ContainerOpenersCounter.class)
25public abstract class ContainerOpenersCounterMixin
26 implements ContainerOpenersCounterUtil.ContainerOpenersCounterSuper {
27 @Shadow protected abstract boolean isOwnContainer(Player player);
28
29 @Unique
30 private final static Map<ContainerOpenersCounterMixin, List<ServerPlayer>> openers = new WeakHashMap<>();
31
32 @Inject(method = "recheckOpeners", at = @At("RETURN"))
33 public void onRecheckOpeners(Level world, BlockPos pos, BlockState state, CallbackInfo ci) {
34 int x = pos.getX();
35 int y = pos.getY();
36 int z = pos.getZ();
37 var boundingBox = new AABB(
38 x - 5.0, y - 5.0, z - 5.0,
39 x + 5.0, y + 5.0, z + 5.0
40 );
41 var players = world.getEntities(EntityTypeTest.forClass(ServerPlayer.class), boundingBox, this::isOwnContainer);
42 if (openers.containsKey(this)) {
43 var list = openers.get(this);
44 list.clear();
45 list.addAll(players);
46 } else {
47 openers.put(this, players);
48 }
49 }
50
51 @Nonnull
52 @Override
53 public List<ServerPlayer> lv_enes_mc$getOpeners() {
54 return openers.getOrDefault(this, List.of());
55 }
56}
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/mixin/client/SheetsMixin.java b/src/main/java/lv/enes/mc/eris_alchemy/mixin/client/SheetsMixin.java
index 46f7720..145a68c 100644
--- a/src/main/java/lv/enes/mc/eris_alchemy/mixin/client/SheetsMixin.java
+++ b/src/main/java/lv/enes/mc/eris_alchemy/mixin/client/SheetsMixin.java
@@ -1,7 +1,8 @@
1package lv.enes.mc.eris_alchemy.mixin.client; 1package lv.enes.mc.eris_alchemy.mixin.client;
2 2
3import lv.enes.mc.eris_alchemy.block.entity.EnergyCondenserEntity;
3import lv.enes.mc.eris_alchemy.client.ErisAlchemyMaterials; 4import lv.enes.mc.eris_alchemy.client.ErisAlchemyMaterials;
4import lv.enes.mc.eris_alchemy.block.entity.AlchemicalChestBlockEntity; 5import lv.enes.mc.eris_alchemy.block.entity.AlchemicalChestEntity;
5import net.minecraft.client.renderer.Sheets; 6import net.minecraft.client.renderer.Sheets;
6import net.minecraft.client.resources.model.Material; 7import net.minecraft.client.resources.model.Material;
7import net.minecraft.world.level.block.entity.BlockEntity; 8import net.minecraft.world.level.block.entity.BlockEntity;
@@ -24,8 +25,10 @@ public abstract class SheetsMixin {
24 boolean christmas, 25 boolean christmas,
25 CallbackInfoReturnable<Material> cir 26 CallbackInfoReturnable<Material> cir
26 ) { 27 ) {
27 if (entity instanceof AlchemicalChestBlockEntity) { 28 if (entity instanceof AlchemicalChestEntity) {
28 cir.setReturnValue(ErisAlchemyMaterials.ALCHEMICAL_CHEST); 29 cir.setReturnValue(ErisAlchemyMaterials.ALCHEMICAL_CHEST);
30 } else if (entity instanceof EnergyCondenserEntity) {
31 cir.setReturnValue(ErisAlchemyMaterials.ENERGY_CONDENSER);
29 } 32 }
30 } 33 }
31} 34}
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/utils/ContainerOpenersCounterUtil.java b/src/main/java/lv/enes/mc/eris_alchemy/utils/ContainerOpenersCounterUtil.java
new file mode 100644
index 0000000..abedce7
--- /dev/null
+++ b/src/main/java/lv/enes/mc/eris_alchemy/utils/ContainerOpenersCounterUtil.java
@@ -0,0 +1,20 @@
1package lv.enes.mc.eris_alchemy.utils;
2
3import jakarta.annotation.Nonnull;
4import net.minecraft.server.level.ServerPlayer;
5import net.minecraft.world.level.block.entity.ContainerOpenersCounter;
6
7import java.util.List;
8
9public final class ContainerOpenersCounterUtil {
10 private ContainerOpenersCounterUtil() {}
11
12 /** @see lv.enes.mc.eris_alchemy.mixin.ContainerOpenersCounterMixin */
13 public interface ContainerOpenersCounterSuper {
14 @Nonnull List<ServerPlayer> lv_enes_mc$getOpeners();
15 }
16
17 public static List<ServerPlayer> getOpeners(ContainerOpenersCounter cop) {
18 return ((ContainerOpenersCounterSuper)cop).lv_enes_mc$getOpeners();
19 }
20}
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/utils/SyncedValue.java b/src/main/java/lv/enes/mc/eris_alchemy/utils/SyncedValue.java
new file mode 100644
index 0000000..c7e52bf
--- /dev/null
+++ b/src/main/java/lv/enes/mc/eris_alchemy/utils/SyncedValue.java
@@ -0,0 +1,115 @@
1package lv.enes.mc.eris_alchemy.utils;
2
3import jakarta.annotation.Nonnull;
4import lv.enes.mc.eris_alchemy.ErisAlchemyRegistry;
5import net.fabricmc.api.EnvType;
6import net.minecraft.network.FriendlyByteBuf;
7import net.minecraft.server.level.ServerPlayer;
8import org.quiltmc.loader.api.minecraft.MinecraftQuiltLoader;
9import org.quiltmc.qsl.networking.api.PacketByteBufs;
10import org.quiltmc.qsl.networking.api.ServerPlayNetworking;
11import org.quiltmc.qsl.networking.api.client.ClientPlayNetworking;
12
13import java.lang.ref.WeakReference;
14import java.util.Collection;
15import java.util.HashMap;
16import java.util.Map;
17
18public sealed abstract class SyncedValue<E> {
19 private final static Map<Long, WeakReference<SyncedValue<?>>> values = new HashMap<>();
20
21 private final long id;
22 private boolean changed = true;
23 private E value;
24
25 public SyncedValue(E value) {
26 this(genId(), value);
27 }
28
29 public SyncedValue(long id, E value) {
30 this.id = id;
31 this.value = value;
32
33 values.put(this.id, new WeakReference<>(this));
34 }
35
36 protected abstract @Nonnull E read(FriendlyByteBuf buf);
37 protected abstract void write(FriendlyByteBuf buf, @Nonnull E value);
38
39 public void serialize(FriendlyByteBuf buf) {
40 buf.writeLongLE(id);
41 write(buf, value);
42 }
43
44 public E getValue() {
45 return value;
46 }
47
48 public void setValue(E value) {
49 this.value = value;
50 this.changed = true;
51 }
52
53 public void syncIfChanged(Collection<ServerPlayer> players) {
54 if (!changed) {
55 return;
56 }
57 var buf = PacketByteBufs.create();
58 serialize(buf);
59 ServerPlayNetworking.send(players, ErisAlchemyRegistry.NetworkingConstants.UPDATE_SYNCED_VALUE, buf);
60 changed = false;
61 }
62
63 private void readData(FriendlyByteBuf buf) {
64 this.changed = false;
65 this.value = read(buf);
66 }
67
68 private static long nextId = 0;
69 private static long genId() {
70 return nextId++;
71 }
72
73 static {
74 if (MinecraftQuiltLoader.getEnvironmentType() == EnvType.CLIENT) {
75 ClientPlayNetworking.registerGlobalReceiver(
76 ErisAlchemyRegistry.NetworkingConstants.UPDATE_SYNCED_VALUE,
77 (client, handler, buf, responseSender) -> {
78 var id = buf.readLongLE();
79 var ref = values.get(id);
80 var holder = ref == null ? null : ref.get();
81 if (holder != null) {
82 holder.readData(buf);
83 }
84 }
85 );
86 }
87 }
88
89 public static final class SyncedDouble extends SyncedValue<Double> {
90 public SyncedDouble(double value) {
91 super(value);
92 }
93
94 public SyncedDouble(long id, double value) {
95 super(id, value);
96 }
97
98 public static SyncedDouble deserialize(FriendlyByteBuf buf) {
99 var id = buf.readLongLE();
100 var value = buf.readDoubleLE();
101 return new SyncedDouble(id, value);
102 }
103
104 @Nonnull
105 @Override
106 protected Double read(FriendlyByteBuf buf) {
107 return buf.readDoubleLE();
108 }
109
110 @Override
111 protected void write(FriendlyByteBuf buf, @Nonnull Double value) {
112 buf.writeDoubleLE(value);
113 }
114 }
115}
diff --git a/src/main/resources/assets/eris_alchemy/blockstates/energy_condenser.json b/src/main/resources/assets/eris_alchemy/blockstates/energy_condenser.json
new file mode 100644
index 0000000..a6fc12f
--- /dev/null
+++ b/src/main/resources/assets/eris_alchemy/blockstates/energy_condenser.json
@@ -0,0 +1,7 @@
1{
2 "variants": {
3 "": {
4 "model": "eris_alchemy:block/energy_condenser"
5 }
6 }
7} \ No newline at end of file
diff --git a/src/main/resources/assets/eris_alchemy/lang/en_us.json b/src/main/resources/assets/eris_alchemy/lang/en_us.json
index ed007dd..c399a68 100644
--- a/src/main/resources/assets/eris_alchemy/lang/en_us.json
+++ b/src/main/resources/assets/eris_alchemy/lang/en_us.json
@@ -1,11 +1,13 @@
1{ 1{
2 "block.eris_alchemy.alchemical_chest": "Alchemical Chest", 2 "block.eris_alchemy.alchemical_chest": "Alchemical Chest",
3 "block.eris_alchemy.energy_condenser": "Energy Condenser",
3 4
4 "book.eris_alchemy.title": "Eris Alchemy", 5 "book.eris_alchemy.title": "Eris Alchemy",
5 "book.eris_alchemy.subtitle": "the Official Guide", 6 "book.eris_alchemy.subtitle": "the Official Guide",
6 "book.eris_alchemy.landing_text": "Welcome to Alchemy!", 7 "book.eris_alchemy.landing_text": "Welcome to Alchemy!",
7 8
8 "container.eris_alchemy.alchemical_chest": "Alchemical Chest", 9 "container.eris_alchemy.alchemical_chest": "Alchemical Chest",
10 "container.eris_alchemy.energy_condenser": "Energy Condenser",
9 11
10 "item.eris_alchemy.low_covalence_dust": "Low Covalence Dust", 12 "item.eris_alchemy.low_covalence_dust": "Low Covalence Dust",
11 "item.eris_alchemy.medium_covalence_dust": "Medium Covalence Dust", 13 "item.eris_alchemy.medium_covalence_dust": "Medium Covalence Dust",
diff --git a/src/main/resources/assets/eris_alchemy/models/block/energy_condenser.json b/src/main/resources/assets/eris_alchemy/models/block/energy_condenser.json
new file mode 100644
index 0000000..84acbec
--- /dev/null
+++ b/src/main/resources/assets/eris_alchemy/models/block/energy_condenser.json
@@ -0,0 +1,5 @@
1{
2 "textures": {
3 "particle": "minecraft:block/stone"
4 }
5} \ No newline at end of file
diff --git a/src/main/resources/assets/eris_alchemy/models/item/energy_condenser.json b/src/main/resources/assets/eris_alchemy/models/item/energy_condenser.json
new file mode 100644
index 0000000..62b3156
--- /dev/null
+++ b/src/main/resources/assets/eris_alchemy/models/item/energy_condenser.json
@@ -0,0 +1,6 @@
1{
2 "parent": "item/chest",
3 "textures": {
4 "particle": "block/stone"
5 }
6} \ No newline at end of file
diff --git a/src/main/resources/assets/eris_alchemy/patchouli_books/guide_book/en_us/entries/root/covalence_dusts.json b/src/main/resources/assets/eris_alchemy/patchouli_books/guide_book/en_us/entries/root/covalence_dusts.json
index a55ae50..6000bdc 100644
--- a/src/main/resources/assets/eris_alchemy/patchouli_books/guide_book/en_us/entries/root/covalence_dusts.json
+++ b/src/main/resources/assets/eris_alchemy/patchouli_books/guide_book/en_us/entries/root/covalence_dusts.json
@@ -4,7 +4,6 @@
4 "category": "eris_alchemy:root", 4 "category": "eris_alchemy:root",
5 "pages": [{ 5 "pages": [{
6 "type": "patchouli:spotlight", 6 "type": "patchouli:spotlight",
7 "title": "Covalence Dusts",
8 "item": "eris_alchemy:low_covalence_dust,eris_alchemy:medium_covalence_dust,eris_alchemy:high_covalence_dust", 7 "item": "eris_alchemy:low_covalence_dust,eris_alchemy:medium_covalence_dust,eris_alchemy:high_covalence_dust",
9 "link_recipe": true, 8 "link_recipe": true,
10 "text": "$(thing)Covalence dusts$() are the most basic items you create in Eris Alchemy." 9 "text": "$(thing)Covalence dusts$() are the most basic items you create in Eris Alchemy."
diff --git a/src/main/resources/assets/eris_alchemy/patchouli_books/guide_book/en_us/entries/root/energy_condenser.json b/src/main/resources/assets/eris_alchemy/patchouli_books/guide_book/en_us/entries/root/energy_condenser.json
new file mode 100644
index 0000000..cea3e75
--- /dev/null
+++ b/src/main/resources/assets/eris_alchemy/patchouli_books/guide_book/en_us/entries/root/energy_condenser.json
@@ -0,0 +1,14 @@
1{
2 "name": "Energy Condenser",
3 "icon": "eris_alchemy:energy_condenser",
4 "category": "eris_alchemy:root",
5 "pages": [{
6 "type": "patchouli:spotlight",
7 "item": "eris_alchemy:energy_condenser",
8 "link_recipe": true,
9 "text": "$(item)Energy Condenser$() has a slightly smaller chest space than $(item)Alchemical Chest$() but it transforms items placed into it into the template item (placed in the upper left slot)."
10 }, {
11 "type": "patchouli:crafting",
12 "recipe": "eris_alchemy:energy_condenser"
13 }]
14} \ No newline at end of file
diff --git a/src/main/resources/assets/eris_alchemy/patchouli_books/guide_book/en_us/entries/root/guide_book.json b/src/main/resources/assets/eris_alchemy/patchouli_books/guide_book/en_us/entries/root/guide_book.json
index b501b0b..ba0812b 100644
--- a/src/main/resources/assets/eris_alchemy/patchouli_books/guide_book/en_us/entries/root/guide_book.json
+++ b/src/main/resources/assets/eris_alchemy/patchouli_books/guide_book/en_us/entries/root/guide_book.json
@@ -4,7 +4,6 @@
4 "category": "eris_alchemy:root", 4 "category": "eris_alchemy:root",
5 "pages": [{ 5 "pages": [{
6 "type": "patchouli:spotlight", 6 "type": "patchouli:spotlight",
7 "title": "Guide Book",
8 "item": "patchouli:guide_book{'patchouli:book':'eris_alchemy:guide_book'}", 7 "item": "patchouli:guide_book{'patchouli:book':'eris_alchemy:guide_book'}",
9 "link_recipe": true, 8 "link_recipe": true,
10 "text": "The Eris Alchemy $(item)Guide Book$() should be already in your inventory for obvious reasons, but if you ever lose it you can recreate it with this crafting recipe." 9 "text": "The Eris Alchemy $(item)Guide Book$() should be already in your inventory for obvious reasons, but if you ever lose it you can recreate it with this crafting recipe."
diff --git a/src/main/resources/assets/eris_alchemy/textures/entity/chest/energy_condenser.png b/src/main/resources/assets/eris_alchemy/textures/entity/chest/energy_condenser.png
new file mode 100644
index 0000000..4501c59
--- /dev/null
+++ b/src/main/resources/assets/eris_alchemy/textures/entity/chest/energy_condenser.png
Binary files differ
diff --git a/src/main/resources/assets/eris_alchemy/textures/gui/container/energy_condenser.png b/src/main/resources/assets/eris_alchemy/textures/gui/container/energy_condenser.png
new file mode 100644
index 0000000..d075bed
--- /dev/null
+++ b/src/main/resources/assets/eris_alchemy/textures/gui/container/energy_condenser.png
Binary files differ
diff --git a/src/main/resources/data/eris_alchemy/loot_tables/blocks/energy_condenser.json b/src/main/resources/data/eris_alchemy/loot_tables/blocks/energy_condenser.json
new file mode 100644
index 0000000..07e2f55
--- /dev/null
+++ b/src/main/resources/data/eris_alchemy/loot_tables/blocks/energy_condenser.json
@@ -0,0 +1,22 @@
1{
2 "type": "minecraft:block",
3 "pools": [{
4 "rolls": 1,
5 "entries": [{
6 "type": "minecraft:item",
7 "name": "eris_alchemy:energy_condenser",
8 "functions": [{
9 "function": "minecraft:copy_nbt",
10 "source": "block_entity",
11 "ops": [{
12 "op": "replace",
13 "source": "stored_emc",
14 "target": "BlockEntityTag.stored_emc"
15 }]
16 }]
17 }],
18 "conditions": [{
19 "condition": "minecraft:survives_explosion"
20 }]
21 }]
22} \ No newline at end of file
diff --git a/src/main/resources/data/eris_alchemy/recipes/energy_condenser.json b/src/main/resources/data/eris_alchemy/recipes/energy_condenser.json
new file mode 100644
index 0000000..55c04bf
--- /dev/null
+++ b/src/main/resources/data/eris_alchemy/recipes/energy_condenser.json
@@ -0,0 +1,22 @@
1{
2 "type": "crafting_shaped",
3 "pattern": [
4 "ODO",
5 "DCD",
6 "ODO"
7 ],
8 "key": {
9 "O": {
10 "item": "obsidian"
11 },
12 "D": {
13 "item": "diamond"
14 },
15 "C": {
16 "item": "eris_alchemy:alchemical_chest"
17 }
18 },
19 "result": {
20 "item": "eris_alchemy:energy_condenser"
21 }
22} \ No newline at end of file
diff --git a/src/main/resources/data/minecraft/tags/blocks/mineable/pickaxe.json b/src/main/resources/data/minecraft/tags/blocks/mineable/pickaxe.json
index 27c0b6d..958cc31 100644
--- a/src/main/resources/data/minecraft/tags/blocks/mineable/pickaxe.json
+++ b/src/main/resources/data/minecraft/tags/blocks/mineable/pickaxe.json
@@ -1,6 +1,7 @@
1{ 1{
2 "replace": false, 2 "replace": false,
3 "values": [ 3 "values": [
4 "eris_alchemy:alchemical_chest" 4 "eris_alchemy:alchemical_chest",
5 "eris_alchemy:energy_condenser"
5 ] 6 ]
6} \ No newline at end of file 7} \ No newline at end of file
diff --git a/src/main/resources/eris_alchemy.mixins.json b/src/main/resources/eris_alchemy.mixins.json
index 36cb47f..fb52b89 100644
--- a/src/main/resources/eris_alchemy.mixins.json
+++ b/src/main/resources/eris_alchemy.mixins.json
@@ -7,6 +7,7 @@
7 "client.SheetsMixin" 7 "client.SheetsMixin"
8 ], 8 ],
9 "mixins": [ 9 "mixins": [
10 "ContainerOpenersCounterMixin",
10 "CoralBlockMixin", 11 "CoralBlockMixin",
11 "CoralFanBlockMixin", 12 "CoralFanBlockMixin",
12 "CoralPlantBlockMixin", 13 "CoralPlantBlockMixin",
diff --git a/src/main/resources/quilt.mod.json b/src/main/resources/quilt.mod.json
index 5b6373a..4e5a88d 100644
--- a/src/main/resources/quilt.mod.json
+++ b/src/main/resources/quilt.mod.json
@@ -6,15 +6,10 @@
6 "version": "${version}", 6 "version": "${version}",
7 "metadata": { 7 "metadata": {
8 "name": "Eris Alchemy", 8 "name": "Eris Alchemy",
9 "description": "Adds the condensing chest from EE2.", 9 "description": "Adds the energy condenser (and a bit more) from EE2.",
10 "contributors": { 10 "contributors": {
11 "Eris": "Owner" 11 "Eris": "Owner"
12 }, 12 },
13 "contact": {
14 "homepage": "https://TODO",
15 "issues": "https://TODO",
16 "sources": "https://TODO"
17 },
18 "icon": "assets/eris_alchemy/icon.png" 13 "icon": "assets/eris_alchemy/icon.png"
19 }, 14 },
20 "intermediate_mappings": "net.fabricmc:intermediary", 15 "intermediate_mappings": "net.fabricmc:intermediary",