diff options
Diffstat (limited to 'src/main/java')
25 files changed, 820 insertions, 50 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 4f2c5e4..b8d5557 100644 --- a/src/main/java/lv/enes/mc/eris_alchemy/EMC.java +++ b/src/main/java/lv/enes/mc/eris_alchemy/EMC.java | |||
| @@ -1,10 +1,8 @@ | |||
| 1 | package lv.enes.mc.eris_alchemy; | 1 | package lv.enes.mc.eris_alchemy; |
| 2 | 2 | ||
| 3 | import jakarta.annotation.Nullable; | 3 | import jakarta.annotation.Nullable; |
| 4 | import lv.enes.mc.eris_alchemy.utils.CoralUtils; | 4 | import lv.enes.mc.eris_alchemy.utils.*; |
| 5 | import lv.enes.mc.eris_alchemy.utils.DyeUtils; | ||
| 6 | import lv.enes.mc.eris_alchemy.utils.ItemUtils; | 5 | import lv.enes.mc.eris_alchemy.utils.ItemUtils; |
| 7 | import lv.enes.mc.eris_alchemy.utils.RecipeUtils; | ||
| 8 | import net.minecraft.core.RegistryAccess; | 6 | import net.minecraft.core.RegistryAccess; |
| 9 | import net.minecraft.core.registries.BuiltInRegistries; | 7 | import net.minecraft.core.registries.BuiltInRegistries; |
| 10 | import net.minecraft.tags.BlockTags; | 8 | import net.minecraft.tags.BlockTags; |
| @@ -116,7 +114,7 @@ public class EMC { | |||
| 116 | private List<SimplifiedRecipe> getRecipes(@Nullable Level world) { | 114 | private List<SimplifiedRecipe> getRecipes(@Nullable Level world) { |
| 117 | Stream<SimplifiedRecipe> recipes = Stream.concat( | 115 | Stream<SimplifiedRecipe> recipes = Stream.concat( |
| 118 | FAKE_RECIPES.stream(), | 116 | FAKE_RECIPES.stream(), |
| 119 | SubAxe.getStrippables() | 117 | AxeUtils.getStrippables() |
| 120 | .entrySet() | 118 | .entrySet() |
| 121 | .stream() | 119 | .stream() |
| 122 | .map(entry -> new SimplifiedRecipe(entry.getValue(), Ingredient.of(entry.getKey()))) | 120 | .map(entry -> new SimplifiedRecipe(entry.getValue(), Ingredient.of(entry.getKey()))) |
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/ErisAlchemy.java b/src/main/java/lv/enes/mc/eris_alchemy/ErisAlchemy.java index fe7e40d..83cef8c 100644 --- a/src/main/java/lv/enes/mc/eris_alchemy/ErisAlchemy.java +++ b/src/main/java/lv/enes/mc/eris_alchemy/ErisAlchemy.java | |||
| @@ -1,39 +1,29 @@ | |||
| 1 | package lv.enes.mc.eris_alchemy; | 1 | package lv.enes.mc.eris_alchemy; |
| 2 | 2 | ||
| 3 | import lv.enes.mc.eris_alchemy.block.ErisAlchemyBlocks; | ||
| 4 | import lv.enes.mc.eris_alchemy.block.entity.ErisAlchemyBlockEntities; | ||
| 5 | import lv.enes.mc.eris_alchemy.menu.ErisAlchemyMenus; | ||
| 6 | import lv.enes.mc.eris_alchemy.recipe.ErisAlchemyRecipeSerializers; | ||
| 3 | import net.fabricmc.fabric.api.itemgroup.v1.FabricItemGroup; | 7 | import net.fabricmc.fabric.api.itemgroup.v1.FabricItemGroup; |
| 4 | import net.minecraft.core.Registry; | 8 | import net.minecraft.core.Registry; |
| 5 | import net.minecraft.core.registries.BuiltInRegistries; | 9 | import net.minecraft.core.registries.BuiltInRegistries; |
| 6 | import net.minecraft.network.chat.Component; | 10 | import net.minecraft.network.chat.Component; |
| 7 | import net.minecraft.resources.ResourceLocation; | 11 | import net.minecraft.resources.ResourceLocation; |
| 8 | import net.minecraft.world.item.CreativeModeTab; | 12 | import net.minecraft.world.item.CreativeModeTab; |
| 9 | import net.minecraft.world.item.Item; | ||
| 10 | import net.minecraft.world.item.ItemStack; | 13 | import net.minecraft.world.item.ItemStack; |
| 11 | import net.minecraft.world.item.Rarity; | ||
| 12 | import org.quiltmc.loader.api.ModContainer; | 14 | import org.quiltmc.loader.api.ModContainer; |
| 13 | import org.quiltmc.qsl.base.api.entrypoint.ModInitializer; | 15 | import org.quiltmc.qsl.base.api.entrypoint.ModInitializer; |
| 14 | import org.quiltmc.qsl.item.setting.api.QuiltItemSettings; | ||
| 15 | import org.quiltmc.qsl.tooltip.api.client.ItemTooltipCallback; | ||
| 16 | import org.slf4j.Logger; | 16 | import org.slf4j.Logger; |
| 17 | import org.slf4j.LoggerFactory; | 17 | import org.slf4j.LoggerFactory; |
| 18 | 18 | ||
| 19 | import java.text.DecimalFormat; | ||
| 20 | |||
| 21 | public class ErisAlchemy implements ModInitializer { | 19 | public class ErisAlchemy implements ModInitializer { |
| 22 | public static final String ID = "eris_alchemy"; | 20 | public static final String ID = "eris_alchemy"; |
| 23 | public static final Logger LOGGER = LoggerFactory.getLogger(ID); | 21 | public static final Logger LOGGER = LoggerFactory.getLogger(ID); |
| 24 | 22 | ||
| 25 | public static final Item LOW_COVALENCE_DUST = new Item(new QuiltItemSettings().rarity(Rarity.COMMON)); | ||
| 26 | public static final Item MEDIUM_COVALENCE_DUST = new Item(new QuiltItemSettings().rarity(Rarity.UNCOMMON)); | ||
| 27 | public static final Item HIGH_COVALENCE_DUST = new Item(new QuiltItemSettings().rarity(Rarity.RARE)); | ||
| 28 | |||
| 29 | public static final CreativeModeTab ITEM_GROUP = FabricItemGroup.builder() | 23 | public static final CreativeModeTab ITEM_GROUP = FabricItemGroup.builder() |
| 30 | .icon(() -> new ItemStack(LOW_COVALENCE_DUST)) | 24 | .icon(() -> new ItemStack(ErisAlchemyItems.LOW_COVALENCE_DUST)) |
| 31 | .title(Component.translatable("itemGroup.eris_alchemy.item_group")) | 25 | .title(Component.translatable("itemGroup.eris_alchemy.item_group")) |
| 32 | .displayItems((context, entries) -> { | 26 | .displayItems((context, entries) -> ErisAlchemyItems.consumeItems((id, item) -> entries.accept(item))) |
| 33 | entries.accept(LOW_COVALENCE_DUST); | ||
| 34 | entries.accept(MEDIUM_COVALENCE_DUST); | ||
| 35 | entries.accept(HIGH_COVALENCE_DUST); | ||
| 36 | }) | ||
| 37 | .build(); | 27 | .build(); |
| 38 | 28 | ||
| 39 | @Override | 29 | @Override |
| @@ -45,19 +35,10 @@ public class ErisAlchemy implements ModInitializer { | |||
| 45 | 35 | ||
| 46 | Registry.register(BuiltInRegistries.CREATIVE_MODE_TAB, new ResourceLocation(ID, "item_group"), ITEM_GROUP); | 36 | Registry.register(BuiltInRegistries.CREATIVE_MODE_TAB, new ResourceLocation(ID, "item_group"), ITEM_GROUP); |
| 47 | 37 | ||
| 48 | Registry.register(BuiltInRegistries.ITEM, new ResourceLocation(ID, "low_covalence_dust"), LOW_COVALENCE_DUST); | 38 | ErisAlchemyBlocks.consumeBlocks((id, block) -> Registry.register(BuiltInRegistries.BLOCK, id, block)); |
| 49 | Registry.register(BuiltInRegistries.ITEM, new ResourceLocation(ID, "medium_covalence_dust"), MEDIUM_COVALENCE_DUST); | 39 | ErisAlchemyBlockEntities.consumeBlockEntities((id, block) -> Registry.register(BuiltInRegistries.BLOCK_ENTITY_TYPE, id, block)); |
| 50 | Registry.register(BuiltInRegistries.ITEM, new ResourceLocation(ID, "high_covalence_dust"), HIGH_COVALENCE_DUST); | 40 | ErisAlchemyItems.consumeItems((id, item) -> Registry.register(BuiltInRegistries.ITEM, id, item)); |
| 51 | 41 | ErisAlchemyMenus.consumeMenus((id, menu) -> Registry.register(BuiltInRegistries.MENU, id, menu)); | |
| 52 | Registry.register(BuiltInRegistries.RECIPE_SERIALIZER, CovalenceRepair.Serializer.ID, CovalenceRepair.Serializer.INSTANCE); | 42 | ErisAlchemyRecipeSerializers.consumeSerializers((id, serializer) -> Registry.register(BuiltInRegistries.RECIPE_SERIALIZER, id, serializer)); |
| 53 | |||
| 54 | var doubleFormat = new DecimalFormat("0"); | ||
| 55 | doubleFormat.setMaximumFractionDigits(1); | ||
| 56 | |||
| 57 | ItemTooltipCallback.EVENT.register((stack, player, context, tooltip) -> { | ||
| 58 | var world = player == null ? null : player.level(); | ||
| 59 | var emc = EMC.getInstance(world).get(stack.getItem()); | ||
| 60 | emc.ifPresent(value -> tooltip.add(Component.literal("EMC %s".formatted(doubleFormat.format(value))))); | ||
| 61 | }); | ||
| 62 | } | 43 | } |
| 63 | } | 44 | } |
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/ErisAlchemyItems.java b/src/main/java/lv/enes/mc/eris_alchemy/ErisAlchemyItems.java new file mode 100644 index 0000000..21bcc7f --- /dev/null +++ b/src/main/java/lv/enes/mc/eris_alchemy/ErisAlchemyItems.java | |||
| @@ -0,0 +1,44 @@ | |||
| 1 | package lv.enes.mc.eris_alchemy; | ||
| 2 | |||
| 3 | import lv.enes.mc.eris_alchemy.block.ErisAlchemyBlocks; | ||
| 4 | import net.minecraft.core.registries.BuiltInRegistries; | ||
| 5 | import net.minecraft.resources.ResourceLocation; | ||
| 6 | import net.minecraft.world.item.BlockItem; | ||
| 7 | import net.minecraft.world.item.Item; | ||
| 8 | import net.minecraft.world.item.Rarity; | ||
| 9 | import net.minecraft.world.level.block.Block; | ||
| 10 | import org.quiltmc.qsl.item.setting.api.QuiltItemSettings; | ||
| 11 | |||
| 12 | import java.util.LinkedHashMap; | ||
| 13 | import java.util.Map; | ||
| 14 | import java.util.function.BiConsumer; | ||
| 15 | |||
| 16 | public final class ErisAlchemyItems { | ||
| 17 | private static final Map<ResourceLocation, Item> items = new LinkedHashMap<>(); | ||
| 18 | |||
| 19 | public static final Item ALCHEMICAL_CHEST = register(ErisAlchemyBlocks.ALCHEMICAL_CHEST, new QuiltItemSettings().rarity(Rarity.RARE)); | ||
| 20 | public static final Item LOW_COVALENCE_DUST = register("low_covalence_dust", new Item(new QuiltItemSettings().rarity(Rarity.COMMON))); | ||
| 21 | @SuppressWarnings("unused") | ||
| 22 | public static final Item MEDIUM_COVALENCE_DUST = register("medium_covalence_dust", new Item(new QuiltItemSettings().rarity(Rarity.UNCOMMON))); | ||
| 23 | @SuppressWarnings("unused") | ||
| 24 | public static final Item HIGH_COVALENCE_DUST = register("high_covalence_dust", new Item(new QuiltItemSettings().rarity(Rarity.RARE))); | ||
| 25 | |||
| 26 | public static void consumeItems(BiConsumer<? super ResourceLocation, ? super Item> consumer) { | ||
| 27 | items.forEach(consumer); | ||
| 28 | } | ||
| 29 | |||
| 30 | private static BlockItem register(Block block, QuiltItemSettings settings) { | ||
| 31 | return register(BuiltInRegistries.BLOCK.getKey(block), new BlockItem(block, settings)); | ||
| 32 | } | ||
| 33 | |||
| 34 | private static <T extends Item> T register(String id, T item) { | ||
| 35 | return register(new ResourceLocation(ErisAlchemy.ID, id), item); | ||
| 36 | } | ||
| 37 | |||
| 38 | private static <T extends Item> T register(ResourceLocation id, T item) { | ||
| 39 | items.putIfAbsent(id, item); | ||
| 40 | return item; | ||
| 41 | } | ||
| 42 | |||
| 43 | private ErisAlchemyItems() {} | ||
| 44 | } | ||
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 new file mode 100644 index 0000000..c013df6 --- /dev/null +++ b/src/main/java/lv/enes/mc/eris_alchemy/block/AlchemicalChestBlock.java | |||
| @@ -0,0 +1,162 @@ | |||
| 1 | package lv.enes.mc.eris_alchemy.block; | ||
| 2 | |||
| 3 | import jakarta.annotation.Nonnull; | ||
| 4 | import jakarta.annotation.Nullable; | ||
| 5 | import lv.enes.mc.eris_alchemy.block.entity.AlchemicalChestBlockEntity; | ||
| 6 | import lv.enes.mc.eris_alchemy.block.entity.ErisAlchemyBlockEntities; | ||
| 7 | import lv.enes.mc.eris_alchemy.menu.AlchemicalChestMenu; | ||
| 8 | import net.minecraft.core.BlockPos; | ||
| 9 | import net.minecraft.core.Direction; | ||
| 10 | import net.minecraft.network.chat.Component; | ||
| 11 | import net.minecraft.world.*; | ||
| 12 | import net.minecraft.world.entity.monster.piglin.PiglinAi; | ||
| 13 | import net.minecraft.world.entity.player.Player; | ||
| 14 | import net.minecraft.world.item.context.BlockPlaceContext; | ||
| 15 | import net.minecraft.world.level.BlockGetter; | ||
| 16 | import net.minecraft.world.level.Level; | ||
| 17 | import net.minecraft.world.level.block.*; | ||
| 18 | import net.minecraft.world.level.block.entity.BlockEntity; | ||
| 19 | import net.minecraft.world.level.block.entity.BlockEntityTicker; | ||
| 20 | import net.minecraft.world.level.block.entity.BlockEntityType; | ||
| 21 | import net.minecraft.world.level.block.entity.ChestBlockEntity; | ||
| 22 | import net.minecraft.world.level.block.state.BlockState; | ||
| 23 | import net.minecraft.world.level.block.state.StateDefinition; | ||
| 24 | import net.minecraft.world.level.block.state.properties.BlockStateProperties; | ||
| 25 | import net.minecraft.world.level.block.state.properties.DirectionProperty; | ||
| 26 | import net.minecraft.world.level.pathfinder.PathComputationType; | ||
| 27 | import net.minecraft.world.phys.BlockHitResult; | ||
| 28 | import net.minecraft.world.phys.shapes.CollisionContext; | ||
| 29 | import net.minecraft.world.phys.shapes.VoxelShape; | ||
| 30 | |||
| 31 | public class AlchemicalChestBlock extends AbstractChestBlock<AlchemicalChestBlockEntity> { | ||
| 32 | public static final Component CONTAINER_TITLE = Component.translatable("container.eris_alchemy.alchemical_chest"); | ||
| 33 | public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING; | ||
| 34 | public static final VoxelShape SHAPE = Block.box(1.0, 0.0, 1.0, 15.0, 14.0, 15.0); | ||
| 35 | |||
| 36 | public static Container getContainer(Level world, BlockPos pos) { | ||
| 37 | if (world.getBlockEntity(pos) instanceof AlchemicalChestBlockEntity container) { | ||
| 38 | return container; | ||
| 39 | } | ||
| 40 | return null; | ||
| 41 | } | ||
| 42 | |||
| 43 | public AlchemicalChestBlock(Properties properties) { | ||
| 44 | super(properties, () -> ErisAlchemyBlockEntities.ALCHEMICAL_CHEST); | ||
| 45 | registerDefaultState(getStateDefinition().any() | ||
| 46 | .setValue(FACING, Direction.NORTH) | ||
| 47 | ); | ||
| 48 | } | ||
| 49 | |||
| 50 | @Nonnull | ||
| 51 | @Override | ||
| 52 | public DoubleBlockCombiner.NeighborCombineResult<? extends ChestBlockEntity> combine(BlockState state, Level world, BlockPos pos, boolean ignoreBlocked) { | ||
| 53 | return DoubleBlockCombiner.Combiner::acceptNone; | ||
| 54 | } | ||
| 55 | |||
| 56 | @Override | ||
| 57 | protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) { | ||
| 58 | builder.add(FACING); | ||
| 59 | } | ||
| 60 | |||
| 61 | @SuppressWarnings("deprecation") | ||
| 62 | @Override | ||
| 63 | public int getAnalogOutputSignal(BlockState state, Level world, BlockPos pos) { | ||
| 64 | return AlchemicalChestMenu.getRedstoneSignalFromContainer(getContainer(world, pos)); | ||
| 65 | } | ||
| 66 | |||
| 67 | @Override | ||
| 68 | public MenuProvider getMenuProvider(BlockState state, Level world, BlockPos pos) { | ||
| 69 | if (world.getBlockEntity(pos) instanceof AlchemicalChestBlockEntity entity) { | ||
| 70 | return new SimpleMenuProvider(entity, CONTAINER_TITLE); | ||
| 71 | } | ||
| 72 | return null; | ||
| 73 | } | ||
| 74 | |||
| 75 | @Nonnull | ||
| 76 | @Override | ||
| 77 | public RenderShape getRenderShape(BlockState state) { | ||
| 78 | return RenderShape.ENTITYBLOCK_ANIMATED; | ||
| 79 | } | ||
| 80 | |||
| 81 | @SuppressWarnings("deprecation") | ||
| 82 | @Nonnull | ||
| 83 | @Override | ||
| 84 | public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext ctx) { | ||
| 85 | return SHAPE; | ||
| 86 | } | ||
| 87 | |||
| 88 | @Override | ||
| 89 | public BlockState getStateForPlacement(BlockPlaceContext ctx) { | ||
| 90 | return defaultBlockState() | ||
| 91 | .setValue(FACING, ctx.getHorizontalDirection().getOpposite()); | ||
| 92 | } | ||
| 93 | |||
| 94 | @Override | ||
| 95 | public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level ignoredWorld, BlockState ignoredState, BlockEntityType<T> type) { | ||
| 96 | return createTickerHelper(type, blockEntityType.get(), (world, pos, state, entity) -> entity.tick(world, pos, state)); | ||
| 97 | } | ||
| 98 | |||
| 99 | @SuppressWarnings("deprecation") | ||
| 100 | @Override | ||
| 101 | public boolean hasAnalogOutputSignal(BlockState state) { | ||
| 102 | return true; | ||
| 103 | } | ||
| 104 | |||
| 105 | @SuppressWarnings("deprecation") | ||
| 106 | @Override | ||
| 107 | public boolean isPathfindable(BlockState state, BlockGetter world, BlockPos pos, PathComputationType type) { | ||
| 108 | return false; | ||
| 109 | } | ||
| 110 | |||
| 111 | @SuppressWarnings("deprecation") | ||
| 112 | @Nonnull | ||
| 113 | @Override | ||
| 114 | public BlockState mirror(BlockState state, Mirror mirror) { | ||
| 115 | return state.rotate(mirror.getRotation(state.getValue(FACING))); | ||
| 116 | } | ||
| 117 | |||
| 118 | @Nullable | ||
| 119 | @Override | ||
| 120 | public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { | ||
| 121 | return new AlchemicalChestBlockEntity(pos, state); | ||
| 122 | } | ||
| 123 | |||
| 124 | @SuppressWarnings("deprecation") | ||
| 125 | @Override | ||
| 126 | public void onRemove(BlockState state, Level world, BlockPos pos, BlockState newState, boolean moved) { | ||
| 127 | if (!state.is(newState.getBlock())) { | ||
| 128 | var entity = world.getBlockEntity(pos); | ||
| 129 | if (entity instanceof Container container) { | ||
| 130 | Containers.dropContents(world, pos, container); | ||
| 131 | world.updateNeighbourForOutputSignal(pos, this); | ||
| 132 | } | ||
| 133 | |||
| 134 | super.onRemove(state, world, pos, newState, moved); | ||
| 135 | } | ||
| 136 | } | ||
| 137 | |||
| 138 | @SuppressWarnings("deprecation") | ||
| 139 | @Nonnull | ||
| 140 | @Override | ||
| 141 | public BlockState rotate(BlockState state, Rotation rotation) { | ||
| 142 | return state.setValue(FACING, rotation.rotate(state.getValue(FACING))); | ||
| 143 | } | ||
| 144 | |||
| 145 | @SuppressWarnings("deprecation") | ||
| 146 | @Nonnull | ||
| 147 | @Override | ||
| 148 | public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { | ||
| 149 | if (world.isClientSide) { | ||
| 150 | return InteractionResult.SUCCESS; | ||
| 151 | } | ||
| 152 | |||
| 153 | var provider = getMenuProvider(state, world, pos); | ||
| 154 | if (provider != null) { | ||
| 155 | player.openMenu(provider); | ||
| 156 | // player.awardStat(getOpenChestStat); | ||
| 157 | PiglinAi.angerNearbyPiglins(player, true); | ||
| 158 | } | ||
| 159 | |||
| 160 | return InteractionResult.CONSUME; | ||
| 161 | } | ||
| 162 | } | ||
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/block/ErisAlchemyBlocks.java b/src/main/java/lv/enes/mc/eris_alchemy/block/ErisAlchemyBlocks.java new file mode 100644 index 0000000..6966681 --- /dev/null +++ b/src/main/java/lv/enes/mc/eris_alchemy/block/ErisAlchemyBlocks.java | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | package lv.enes.mc.eris_alchemy.block; | ||
| 2 | |||
| 3 | import lv.enes.mc.eris_alchemy.ErisAlchemy; | ||
| 4 | import net.minecraft.resources.ResourceLocation; | ||
| 5 | import net.minecraft.world.level.block.Block; | ||
| 6 | import net.minecraft.world.level.block.Blocks; | ||
| 7 | import org.quiltmc.qsl.block.extensions.api.QuiltBlockSettings; | ||
| 8 | |||
| 9 | import java.util.LinkedHashMap; | ||
| 10 | import java.util.Map; | ||
| 11 | import java.util.function.BiConsumer; | ||
| 12 | |||
| 13 | public final class ErisAlchemyBlocks { | ||
| 14 | private static final Map<ResourceLocation, Block> blocks = new LinkedHashMap<>(); | ||
| 15 | |||
| 16 | public static final AlchemicalChestBlock ALCHEMICAL_CHEST = register("alchemical_chest", new AlchemicalChestBlock(QuiltBlockSettings.copy(Blocks.ENDER_CHEST))); | ||
| 17 | |||
| 18 | public static void consumeBlocks(BiConsumer<? super ResourceLocation, ? super Block> consumer) { | ||
| 19 | blocks.forEach(consumer); | ||
| 20 | } | ||
| 21 | |||
| 22 | private static <T extends Block> T register(String id, T block) { | ||
| 23 | blocks.putIfAbsent(new ResourceLocation(ErisAlchemy.ID, id), block); | ||
| 24 | return block; | ||
| 25 | } | ||
| 26 | |||
| 27 | private ErisAlchemyBlocks() {} | ||
| 28 | |||
| 29 | } | ||
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/AlchemicalChestBlockEntity.java new file mode 100644 index 0000000..9c9942f --- /dev/null +++ b/src/main/java/lv/enes/mc/eris_alchemy/block/entity/AlchemicalChestBlockEntity.java | |||
| @@ -0,0 +1,198 @@ | |||
| 1 | package lv.enes.mc.eris_alchemy.block.entity; | ||
| 2 | |||
| 3 | import jakarta.annotation.Nonnull; | ||
| 4 | import lv.enes.mc.eris_alchemy.block.ErisAlchemyBlocks; | ||
| 5 | import lv.enes.mc.eris_alchemy.menu.AlchemicalChestMenu; | ||
| 6 | import net.minecraft.core.BlockPos; | ||
| 7 | import net.minecraft.core.NonNullList; | ||
| 8 | import net.minecraft.nbt.CompoundTag; | ||
| 9 | import net.minecraft.network.chat.Component; | ||
| 10 | import net.minecraft.sounds.SoundEvents; | ||
| 11 | import net.minecraft.sounds.SoundSource; | ||
| 12 | import net.minecraft.world.Container; | ||
| 13 | import net.minecraft.world.ContainerHelper; | ||
| 14 | import net.minecraft.world.entity.player.Inventory; | ||
| 15 | import net.minecraft.world.entity.player.Player; | ||
| 16 | import net.minecraft.world.inventory.AbstractContainerMenu; | ||
| 17 | import net.minecraft.world.item.ItemStack; | ||
| 18 | import net.minecraft.world.level.Level; | ||
| 19 | import net.minecraft.world.level.block.entity.BaseContainerBlockEntity; | ||
| 20 | import net.minecraft.world.level.block.entity.ChestLidController; | ||
| 21 | import net.minecraft.world.level.block.entity.ContainerOpenersCounter; | ||
| 22 | import net.minecraft.world.level.block.entity.LidBlockEntity; | ||
| 23 | import net.minecraft.world.level.block.state.BlockState; | ||
| 24 | |||
| 25 | public class AlchemicalChestBlockEntity extends BaseContainerBlockEntity implements LidBlockEntity { | ||
| 26 | private final static int WIDTH = 13; | ||
| 27 | private final static int HEIGHT = 8; | ||
| 28 | |||
| 29 | private final static int EVENT = 1; | ||
| 30 | |||
| 31 | private final NonNullList<ItemStack> items = NonNullList.withSize(WIDTH * HEIGHT, ItemStack.EMPTY); | ||
| 32 | private final ChestLidController lidController = new ChestLidController(); | ||
| 33 | private final ContainerOpenersCounter openersCounter = new ContainerOpenersCounter() { | ||
| 34 | @Override | ||
| 35 | protected void onOpen(Level world, BlockPos pos, BlockState state) { | ||
| 36 | // TODO: Sound effects? | ||
| 37 | world.playSound( | ||
| 38 | null, | ||
| 39 | pos.getX() + 0.5, | ||
| 40 | pos.getY() + 0.5, | ||
| 41 | pos.getZ() + 0.5, | ||
| 42 | SoundEvents.ENDER_CHEST_OPEN, | ||
| 43 | SoundSource.BLOCKS, | ||
| 44 | 0.5f, | ||
| 45 | world.random.nextFloat() * 0.1f + 0.9f | ||
| 46 | ); | ||
| 47 | } | ||
| 48 | |||
| 49 | @Override | ||
| 50 | protected void onClose(Level world, BlockPos pos, BlockState state) { | ||
| 51 | // TODO: Sound effects? | ||
| 52 | world.playSound( | ||
| 53 | null, | ||
| 54 | pos.getX() + 0.5, | ||
| 55 | pos.getY() + 0.5, | ||
| 56 | pos.getZ() + 0.5, | ||
| 57 | SoundEvents.ENDER_CHEST_CLOSE, | ||
| 58 | SoundSource.BLOCKS, | ||
| 59 | 0.5f, | ||
| 60 | world.random.nextFloat() * 0.1f + 0.9f | ||
| 61 | ); | ||
| 62 | } | ||
| 63 | |||
| 64 | @Override | ||
| 65 | protected void openerCountChanged(Level world, BlockPos pos, BlockState state, int oldViewerCount, int newViewerCount) { | ||
| 66 | world.blockEvent(worldPosition, ErisAlchemyBlocks.ALCHEMICAL_CHEST, EVENT, newViewerCount); | ||
| 67 | } | ||
| 68 | |||
| 69 | @Override | ||
| 70 | protected boolean isOwnContainer(Player player) { | ||
| 71 | if (player.containerMenu instanceof AlchemicalChestMenu menu) { | ||
| 72 | return menu.getContainer() == AlchemicalChestBlockEntity.this; | ||
| 73 | } | ||
| 74 | return false; | ||
| 75 | } | ||
| 76 | }; | ||
| 77 | |||
| 78 | public AlchemicalChestBlockEntity(BlockPos pos, BlockState state) { | ||
| 79 | super(ErisAlchemyBlockEntities.ALCHEMICAL_CHEST, pos, state); | ||
| 80 | } | ||
| 81 | |||
| 82 | @Override | ||
| 83 | public void clearContent() { | ||
| 84 | items.clear(); | ||
| 85 | } | ||
| 86 | |||
| 87 | @Nonnull | ||
| 88 | @Override | ||
| 89 | protected AbstractContainerMenu createMenu(int syncId, Inventory playerInventory) { | ||
| 90 | return new AlchemicalChestMenu(syncId, playerInventory, this); | ||
| 91 | } | ||
| 92 | |||
| 93 | @Override | ||
| 94 | public int getContainerSize() { | ||
| 95 | return items.size(); | ||
| 96 | } | ||
| 97 | |||
| 98 | @Nonnull | ||
| 99 | @Override | ||
| 100 | protected Component getDefaultName() { | ||
| 101 | return Component.translatable("container.eris_alchemy.alchemical_chest"); | ||
| 102 | } | ||
| 103 | |||
| 104 | @Nonnull | ||
| 105 | @Override | ||
| 106 | public ItemStack getItem(int slot) { | ||
| 107 | return items.get(slot); | ||
| 108 | } | ||
| 109 | |||
| 110 | @Override | ||
| 111 | public float getOpenNess(float tickDelta) { | ||
| 112 | return lidController.getOpenness(tickDelta); | ||
| 113 | } | ||
| 114 | |||
| 115 | @Override | ||
| 116 | public boolean isEmpty() { | ||
| 117 | return items.stream().allMatch(ItemStack::isEmpty); | ||
| 118 | } | ||
| 119 | |||
| 120 | @Override | ||
| 121 | public void load(CompoundTag nbt) { | ||
| 122 | super.load(nbt); | ||
| 123 | ContainerHelper.loadAllItems(nbt, items); | ||
| 124 | } | ||
| 125 | |||
| 126 | private void recheckOpen() { | ||
| 127 | if (!remove) { | ||
| 128 | openersCounter.recheckOpeners(getLevel(), getBlockPos(), getBlockState()); | ||
| 129 | } | ||
| 130 | } | ||
| 131 | |||
| 132 | @Nonnull | ||
| 133 | @Override | ||
| 134 | public ItemStack removeItem(int slot, int amount) { | ||
| 135 | var stack = ContainerHelper.removeItem(items, slot, amount); | ||
| 136 | if (!stack.isEmpty()) { | ||
| 137 | this.setChanged(); | ||
| 138 | } | ||
| 139 | return stack; | ||
| 140 | } | ||
| 141 | |||
| 142 | @Nonnull | ||
| 143 | @Override | ||
| 144 | public ItemStack removeItemNoUpdate(int slot) { | ||
| 145 | return ContainerHelper.takeItem(items, slot); | ||
| 146 | } | ||
| 147 | |||
| 148 | @Override | ||
| 149 | protected void saveAdditional(CompoundTag nbt) { | ||
| 150 | super.saveAdditional(nbt); | ||
| 151 | ContainerHelper.saveAllItems(nbt, items); | ||
| 152 | } | ||
| 153 | |||
| 154 | @Override | ||
| 155 | public void setItem(int slot, ItemStack stack) { | ||
| 156 | items.set(slot, stack); | ||
| 157 | if (stack.getCount() > getMaxStackSize()) { | ||
| 158 | stack.setCount(getMaxStackSize()); | ||
| 159 | } | ||
| 160 | this.setChanged(); | ||
| 161 | } | ||
| 162 | |||
| 163 | @Override | ||
| 164 | public void startOpen(Player player) { | ||
| 165 | if (!remove && !player.isSpectator()) { | ||
| 166 | openersCounter.incrementOpeners(player, getLevel(), getBlockPos(), getBlockState()); | ||
| 167 | } | ||
| 168 | } | ||
| 169 | |||
| 170 | @Override | ||
| 171 | public boolean stillValid(Player player) { | ||
| 172 | return Container.stillValidBlockEntity(this, player); | ||
| 173 | } | ||
| 174 | |||
| 175 | @Override | ||
| 176 | public void stopOpen(Player player) { | ||
| 177 | if (!remove && !player.isSpectator()) { | ||
| 178 | openersCounter.decrementOpeners(player, getLevel(), getBlockPos(), getBlockState()); | ||
| 179 | } | ||
| 180 | } | ||
| 181 | |||
| 182 | public void tick(Level world, BlockPos ignoredPos, BlockState ignoredState) { | ||
| 183 | if (world.isClientSide) { | ||
| 184 | lidController.tickLid(); | ||
| 185 | } | ||
| 186 | recheckOpen(); | ||
| 187 | } | ||
| 188 | |||
| 189 | @Override | ||
| 190 | public boolean triggerEvent(int type, int data) { | ||
| 191 | if (type == EVENT) { | ||
| 192 | lidController.shouldBeOpen(data > 0); | ||
| 193 | return true; | ||
| 194 | } | ||
| 195 | |||
| 196 | return super.triggerEvent(type, data); | ||
| 197 | } | ||
| 198 | } | ||
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/block/entity/ErisAlchemyBlockEntities.java b/src/main/java/lv/enes/mc/eris_alchemy/block/entity/ErisAlchemyBlockEntities.java new file mode 100644 index 0000000..a95ac58 --- /dev/null +++ b/src/main/java/lv/enes/mc/eris_alchemy/block/entity/ErisAlchemyBlockEntities.java | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | package lv.enes.mc.eris_alchemy.block.entity; | ||
| 2 | |||
| 3 | import lv.enes.mc.eris_alchemy.ErisAlchemy; | ||
| 4 | import lv.enes.mc.eris_alchemy.block.ErisAlchemyBlocks; | ||
| 5 | import net.minecraft.resources.ResourceLocation; | ||
| 6 | import net.minecraft.world.level.block.entity.BlockEntity; | ||
| 7 | import net.minecraft.world.level.block.entity.BlockEntityType; | ||
| 8 | import org.quiltmc.qsl.block.entity.api.QuiltBlockEntityTypeBuilder; | ||
| 9 | |||
| 10 | import java.util.LinkedHashMap; | ||
| 11 | import java.util.Map; | ||
| 12 | import java.util.function.BiConsumer; | ||
| 13 | |||
| 14 | public final class ErisAlchemyBlockEntities { | ||
| 15 | private static final Map<ResourceLocation, BlockEntityType<?>> entities = new LinkedHashMap<>(); | ||
| 16 | |||
| 17 | public static final BlockEntityType<AlchemicalChestBlockEntity> ALCHEMICAL_CHEST = register( | ||
| 18 | "alchemical_chest", | ||
| 19 | QuiltBlockEntityTypeBuilder.create(AlchemicalChestBlockEntity::new, ErisAlchemyBlocks.ALCHEMICAL_CHEST) | ||
| 20 | .build() | ||
| 21 | ); | ||
| 22 | |||
| 23 | public static void consumeBlockEntities(BiConsumer<? super ResourceLocation, ? super BlockEntityType<?>> consumer) { | ||
| 24 | entities.forEach(consumer); | ||
| 25 | } | ||
| 26 | |||
| 27 | private static <T extends BlockEntity> BlockEntityType<T> register(String id, BlockEntityType<T> type) { | ||
| 28 | entities.putIfAbsent(new ResourceLocation(ErisAlchemy.ID, id), type); | ||
| 29 | return type; | ||
| 30 | } | ||
| 31 | |||
| 32 | private ErisAlchemyBlockEntities() {} | ||
| 33 | } | ||
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/client/AlchemicalChestScreen.java b/src/main/java/lv/enes/mc/eris_alchemy/client/AlchemicalChestScreen.java new file mode 100644 index 0000000..319dea8 --- /dev/null +++ b/src/main/java/lv/enes/mc/eris_alchemy/client/AlchemicalChestScreen.java | |||
| @@ -0,0 +1,43 @@ | |||
| 1 | package lv.enes.mc.eris_alchemy.client; | ||
| 2 | |||
| 3 | import lv.enes.mc.eris_alchemy.ErisAlchemy; | ||
| 4 | import lv.enes.mc.eris_alchemy.menu.AlchemicalChestMenu; | ||
| 5 | import net.minecraft.client.gui.GuiGraphics; | ||
| 6 | import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; | ||
| 7 | import net.minecraft.network.chat.Component; | ||
| 8 | import net.minecraft.resources.ResourceLocation; | ||
| 9 | import net.minecraft.world.entity.player.Inventory; | ||
| 10 | |||
| 11 | public class AlchemicalChestScreen extends AbstractContainerScreen<AlchemicalChestMenu> { | ||
| 12 | public static final ResourceLocation TEXTURE = | ||
| 13 | new ResourceLocation(ErisAlchemy.ID, "textures/gui/container/alchemical_chest.png"); | ||
| 14 | |||
| 15 | public static final int TEXTURE_WIDTH = 248; | ||
| 16 | public static final int TEXTURE_HEIGHT = 237; | ||
| 17 | |||
| 18 | public AlchemicalChestScreen(AlchemicalChestMenu menu, Inventory inventory, Component title) { | ||
| 19 | super(menu, inventory, title); | ||
| 20 | |||
| 21 | imageWidth = TEXTURE_WIDTH; | ||
| 22 | imageHeight = TEXTURE_HEIGHT; | ||
| 23 | } | ||
| 24 | |||
| 25 | @Override | ||
| 26 | public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) { | ||
| 27 | renderBackground(graphics); | ||
| 28 | super.render(graphics, mouseX, mouseY, delta); | ||
| 29 | renderTooltip(graphics, mouseX, mouseY); | ||
| 30 | } | ||
| 31 | |||
| 32 | @Override | ||
| 33 | protected void renderBg(GuiGraphics graphics, float delta, int mouseX, int mouseY) { | ||
| 34 | int x = (width - imageWidth) / 2; | ||
| 35 | int y = (height - imageHeight) / 2; | ||
| 36 | graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight); | ||
| 37 | } | ||
| 38 | |||
| 39 | @Override | ||
| 40 | protected void renderLabels(GuiGraphics graphics, int mouseX, int mouseY) { | ||
| 41 | // Don't render any labels, there's no space for them lol | ||
| 42 | } | ||
| 43 | } | ||
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/client/ChestItemRenderer.java b/src/main/java/lv/enes/mc/eris_alchemy/client/ChestItemRenderer.java new file mode 100644 index 0000000..d49cc28 --- /dev/null +++ b/src/main/java/lv/enes/mc/eris_alchemy/client/ChestItemRenderer.java | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | package lv.enes.mc.eris_alchemy.client; | ||
| 2 | |||
| 3 | import com.mojang.blaze3d.vertex.PoseStack; | ||
| 4 | import net.minecraft.client.Minecraft; | ||
| 5 | import net.minecraft.client.renderer.BlockEntityWithoutLevelRenderer; | ||
| 6 | import net.minecraft.client.renderer.MultiBufferSource; | ||
| 7 | import net.minecraft.core.BlockPos; | ||
| 8 | import net.minecraft.world.item.ItemDisplayContext; | ||
| 9 | import net.minecraft.world.item.ItemStack; | ||
| 10 | import net.minecraft.world.level.block.AbstractChestBlock; | ||
| 11 | import net.minecraft.world.level.block.entity.BaseContainerBlockEntity; | ||
| 12 | import net.minecraft.world.level.block.state.BlockState; | ||
| 13 | |||
| 14 | import java.util.function.BiFunction; | ||
| 15 | |||
| 16 | public class ChestItemRenderer<T extends BaseContainerBlockEntity> extends BlockEntityWithoutLevelRenderer { | ||
| 17 | private final T chest; | ||
| 18 | |||
| 19 | public ChestItemRenderer( | ||
| 20 | AbstractChestBlock<T> block, | ||
| 21 | BiFunction<? super BlockPos, ? super BlockState, ? extends T> creator | ||
| 22 | ) { | ||
| 23 | super(Minecraft.getInstance().getBlockEntityRenderDispatcher(), Minecraft.getInstance().getEntityModels()); | ||
| 24 | chest = creator.apply(BlockPos.ZERO, block.defaultBlockState()); | ||
| 25 | } | ||
| 26 | |||
| 27 | @Override | ||
| 28 | public void renderByItem( | ||
| 29 | ItemStack stack, | ||
| 30 | ItemDisplayContext transformationMode, | ||
| 31 | PoseStack matrices, | ||
| 32 | MultiBufferSource vertexConsumers, | ||
| 33 | int light, | ||
| 34 | int overlay | ||
| 35 | ) { | ||
| 36 | Minecraft.getInstance() | ||
| 37 | .getBlockEntityRenderDispatcher() | ||
| 38 | .renderItem(chest, matrices, vertexConsumers, light, overlay); | ||
| 39 | } | ||
| 40 | } | ||
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 new file mode 100644 index 0000000..bb5de4f --- /dev/null +++ b/src/main/java/lv/enes/mc/eris_alchemy/client/ErisAlchemyClient.java | |||
| @@ -0,0 +1,41 @@ | |||
| 1 | package lv.enes.mc.eris_alchemy.client; | ||
| 2 | |||
| 3 | import lv.enes.mc.eris_alchemy.EMC; | ||
| 4 | import lv.enes.mc.eris_alchemy.ErisAlchemyItems; | ||
| 5 | import lv.enes.mc.eris_alchemy.block.ErisAlchemyBlocks; | ||
| 6 | import lv.enes.mc.eris_alchemy.block.entity.AlchemicalChestBlockEntity; | ||
| 7 | import lv.enes.mc.eris_alchemy.block.entity.ErisAlchemyBlockEntities; | ||
| 8 | import lv.enes.mc.eris_alchemy.menu.ErisAlchemyMenus; | ||
| 9 | import net.fabricmc.fabric.api.client.rendering.v1.BuiltinItemRendererRegistry; | ||
| 10 | import net.minecraft.client.gui.screens.MenuScreens; | ||
| 11 | import net.minecraft.client.renderer.blockentity.BlockEntityRenderers; | ||
| 12 | import net.minecraft.client.renderer.blockentity.ChestRenderer; | ||
| 13 | import net.minecraft.network.chat.Component; | ||
| 14 | import org.quiltmc.loader.api.ModContainer; | ||
| 15 | import org.quiltmc.qsl.base.api.entrypoint.client.ClientModInitializer; | ||
| 16 | import org.quiltmc.qsl.tooltip.api.client.ItemTooltipCallback; | ||
| 17 | |||
| 18 | import java.text.DecimalFormat; | ||
| 19 | |||
| 20 | @SuppressWarnings("unused") | ||
| 21 | public class ErisAlchemyClient implements ClientModInitializer { | ||
| 22 | @Override | ||
| 23 | public void onInitializeClient(ModContainer mod) { | ||
| 24 | BlockEntityRenderers.register(ErisAlchemyBlockEntities.ALCHEMICAL_CHEST, ChestRenderer::new); | ||
| 25 | |||
| 26 | BuiltinItemRendererRegistry.INSTANCE.register( | ||
| 27 | ErisAlchemyItems.ALCHEMICAL_CHEST, | ||
| 28 | new ChestItemRenderer<>(ErisAlchemyBlocks.ALCHEMICAL_CHEST, AlchemicalChestBlockEntity::new)::renderByItem | ||
| 29 | ); | ||
| 30 | |||
| 31 | MenuScreens.register(ErisAlchemyMenus.ALCHEMICAL_CHEST, AlchemicalChestScreen::new); | ||
| 32 | |||
| 33 | var doubleFormat = new DecimalFormat("0"); | ||
| 34 | doubleFormat.setMaximumFractionDigits(1); | ||
| 35 | ItemTooltipCallback.EVENT.register((stack, player, context, tooltip) -> { | ||
| 36 | var world = player == null ? null : player.level(); | ||
| 37 | var emc = EMC.getInstance(world).get(stack.getItem()); | ||
| 38 | emc.ifPresent(value -> tooltip.add(Component.literal("EMC %s".formatted(doubleFormat.format(value))))); | ||
| 39 | }); | ||
| 40 | } | ||
| 41 | } | ||
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 new file mode 100644 index 0000000..15d9209 --- /dev/null +++ b/src/main/java/lv/enes/mc/eris_alchemy/client/ErisAlchemyMaterials.java | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | package lv.enes.mc.eris_alchemy.client; | ||
| 2 | |||
| 3 | import lv.enes.mc.eris_alchemy.ErisAlchemy; | ||
| 4 | import net.minecraft.client.renderer.Sheets; | ||
| 5 | import net.minecraft.client.resources.model.Material; | ||
| 6 | import net.minecraft.resources.ResourceLocation; | ||
| 7 | |||
| 8 | public final class ErisAlchemyMaterials { | ||
| 9 | public static final Material ALCHEMICAL_CHEST = new Material( | ||
| 10 | Sheets.CHEST_SHEET, | ||
| 11 | new ResourceLocation(ErisAlchemy.ID, "entity/chest/alchemical_chest") | ||
| 12 | ); | ||
| 13 | |||
| 14 | private ErisAlchemyMaterials() {} | ||
| 15 | } | ||
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/client/package-info.java b/src/main/java/lv/enes/mc/eris_alchemy/client/package-info.java new file mode 100644 index 0000000..7b1c99a --- /dev/null +++ b/src/main/java/lv/enes/mc/eris_alchemy/client/package-info.java | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | @ClientOnly | ||
| 2 | package lv.enes.mc.eris_alchemy.client; | ||
| 3 | |||
| 4 | import org.quiltmc.loader.api.minecraft.ClientOnly; \ No newline at end of file | ||
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 new file mode 100644 index 0000000..e4135c9 --- /dev/null +++ b/src/main/java/lv/enes/mc/eris_alchemy/menu/AlchemicalChestMenu.java | |||
| @@ -0,0 +1,91 @@ | |||
| 1 | package lv.enes.mc.eris_alchemy.menu; | ||
| 2 | |||
| 3 | import jakarta.annotation.Nonnull; | ||
| 4 | import net.minecraft.world.Container; | ||
| 5 | import net.minecraft.world.SimpleContainer; | ||
| 6 | import net.minecraft.world.entity.player.Inventory; | ||
| 7 | import net.minecraft.world.entity.player.Player; | ||
| 8 | import net.minecraft.world.inventory.AbstractContainerMenu; | ||
| 9 | import net.minecraft.world.inventory.Slot; | ||
| 10 | import net.minecraft.world.item.ItemStack; | ||
| 11 | |||
| 12 | public class AlchemicalChestMenu extends AbstractContainerMenu { | ||
| 13 | private static final int WIDTH = 13; | ||
| 14 | private static final int HEIGHT = 8; | ||
| 15 | |||
| 16 | private final Container container; | ||
| 17 | |||
| 18 | public AlchemicalChestMenu(int syncId, Inventory playerInventory) { | ||
| 19 | this(syncId, playerInventory, new SimpleContainer(WIDTH * HEIGHT)); | ||
| 20 | } | ||
| 21 | |||
| 22 | public AlchemicalChestMenu(int syncId, Inventory playerInventory, Container inventory) { | ||
| 23 | super(ErisAlchemyMenus.ALCHEMICAL_CHEST, syncId); | ||
| 24 | checkContainerSize(inventory, WIDTH * HEIGHT); | ||
| 25 | |||
| 26 | this.container = inventory; | ||
| 27 | inventory.startOpen(playerInventory.player); | ||
| 28 | |||
| 29 | var x_off = 8; | ||
| 30 | var y_off = 8; | ||
| 31 | |||
| 32 | for (var y = 0; y < HEIGHT; y++) { | ||
| 33 | for (var x = 0; x < WIDTH; x++ ) { | ||
| 34 | addSlot(new Slot(inventory, y * WIDTH + x, x_off + x * 18, y_off + y * 18)); | ||
| 35 | } | ||
| 36 | } | ||
| 37 | |||
| 38 | x_off = 44; | ||
| 39 | y_off = 155; | ||
| 40 | |||
| 41 | for (var y = 0; y < 3; y++) { | ||
| 42 | for (var x = 0; x < 9; x++) { | ||
| 43 | addSlot(new Slot(playerInventory, y * 9 + x + 9, x_off + x * 18, y_off + y * 18)); | ||
| 44 | } | ||
| 45 | } | ||
| 46 | |||
| 47 | y_off = 213; | ||
| 48 | |||
| 49 | for (var x = 0; x < 9; x++) { | ||
| 50 | addSlot(new Slot(playerInventory, x, x_off + x * 18, y_off)); | ||
| 51 | } | ||
| 52 | } | ||
| 53 | |||
| 54 | public Container getContainer() { | ||
| 55 | return container; | ||
| 56 | } | ||
| 57 | |||
| 58 | @Nonnull | ||
| 59 | @Override | ||
| 60 | public ItemStack quickMoveStack(Player player, int fromIndex) { | ||
| 61 | var newStack = ItemStack.EMPTY; | ||
| 62 | var slot = slots.get(fromIndex); | ||
| 63 | if (!slot.hasItem()) { | ||
| 64 | return newStack; | ||
| 65 | } | ||
| 66 | |||
| 67 | var originalStack = slot.getItem(); | ||
| 68 | newStack = originalStack.copy(); | ||
| 69 | |||
| 70 | if (fromIndex < container.getContainerSize()) { | ||
| 71 | if (!moveItemStackTo(originalStack, container.getContainerSize(), slots.size(), true)) { | ||
| 72 | return ItemStack.EMPTY; | ||
| 73 | } | ||
| 74 | } else if (!moveItemStackTo(originalStack, 0, container.getContainerSize(), false)) { | ||
| 75 | return ItemStack.EMPTY; | ||
| 76 | } | ||
| 77 | |||
| 78 | if (originalStack.isEmpty()) { | ||
| 79 | slot.setByPlayer(ItemStack.EMPTY); | ||
| 80 | } else { | ||
| 81 | slot.setChanged(); | ||
| 82 | } | ||
| 83 | |||
| 84 | return newStack; | ||
| 85 | } | ||
| 86 | |||
| 87 | @Override | ||
| 88 | public boolean stillValid(Player player) { | ||
| 89 | return container.stillValid(player); | ||
| 90 | } | ||
| 91 | } | ||
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/menu/ErisAlchemyMenus.java b/src/main/java/lv/enes/mc/eris_alchemy/menu/ErisAlchemyMenus.java new file mode 100644 index 0000000..5e3b54a --- /dev/null +++ b/src/main/java/lv/enes/mc/eris_alchemy/menu/ErisAlchemyMenus.java | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | package lv.enes.mc.eris_alchemy.menu; | ||
| 2 | |||
| 3 | import lv.enes.mc.eris_alchemy.ErisAlchemy; | ||
| 4 | import net.minecraft.resources.ResourceLocation; | ||
| 5 | import net.minecraft.world.flag.FeatureFlags; | ||
| 6 | import net.minecraft.world.inventory.AbstractContainerMenu; | ||
| 7 | import net.minecraft.world.inventory.MenuType; | ||
| 8 | |||
| 9 | import java.util.LinkedHashMap; | ||
| 10 | import java.util.Map; | ||
| 11 | import java.util.function.BiConsumer; | ||
| 12 | |||
| 13 | public final class ErisAlchemyMenus { | ||
| 14 | private static final Map<ResourceLocation, MenuType<?>> menus = new LinkedHashMap<>(); | ||
| 15 | |||
| 16 | public static final MenuType<AlchemicalChestMenu> ALCHEMICAL_CHEST = register("alchemy_chest", AlchemicalChestMenu::new); | ||
| 17 | |||
| 18 | public static void consumeMenus(BiConsumer<? super ResourceLocation, ? super MenuType<?>> consumer) { | ||
| 19 | menus.forEach(consumer); | ||
| 20 | } | ||
| 21 | |||
| 22 | private static <T extends AbstractContainerMenu> MenuType<T> register(String id, MenuType.MenuSupplier<T> supplier) { | ||
| 23 | var menuType = new MenuType<>(supplier, FeatureFlags.VANILLA_SET); | ||
| 24 | menus.putIfAbsent(new ResourceLocation(ErisAlchemy.ID, id), menuType); | ||
| 25 | return menuType; | ||
| 26 | } | ||
| 27 | |||
| 28 | private ErisAlchemyMenus() {} | ||
| 29 | } | ||
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 new file mode 100644 index 0000000..544dcef --- /dev/null +++ b/src/main/java/lv/enes/mc/eris_alchemy/mixin/client/SheetsMixin.java | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | package lv.enes.mc.eris_alchemy.mixin.client; | ||
| 2 | |||
| 3 | import lv.enes.mc.eris_alchemy.client.ErisAlchemyMaterials; | ||
| 4 | import lv.enes.mc.eris_alchemy.block.entity.AlchemicalChestBlockEntity; | ||
| 5 | import net.minecraft.client.renderer.Sheets; | ||
| 6 | import net.minecraft.client.resources.model.Material; | ||
| 7 | import net.minecraft.world.level.block.entity.BlockEntity; | ||
| 8 | import net.minecraft.world.level.block.state.properties.ChestType; | ||
| 9 | import org.spongepowered.asm.mixin.Mixin; | ||
| 10 | import org.spongepowered.asm.mixin.injection.At; | ||
| 11 | import org.spongepowered.asm.mixin.injection.Inject; | ||
| 12 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; | ||
| 13 | |||
| 14 | @Mixin(Sheets.class) | ||
| 15 | public abstract class SheetsMixin { | ||
| 16 | @Inject(method = "chooseMaterial(Lnet/minecraft/world/level/block/entity/BlockEntity;Lnet/minecraft/world/level/block/state/properties/ChestType;Z)Lnet/minecraft/client/resources/model/Material;", at = @At("RETURN"), cancellable = true) | ||
| 17 | private static void chooseMaterial(BlockEntity entity, ChestType type, boolean christmas, CallbackInfoReturnable<Material> cir) { | ||
| 18 | if (entity instanceof AlchemicalChestBlockEntity) { | ||
| 19 | cir.setReturnValue(ErisAlchemyMaterials.ALCHEMICAL_CHEST); | ||
| 20 | } | ||
| 21 | } | ||
| 22 | } | ||
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/mixin/client/package-info.java b/src/main/java/lv/enes/mc/eris_alchemy/mixin/client/package-info.java new file mode 100644 index 0000000..f7d5ada --- /dev/null +++ b/src/main/java/lv/enes/mc/eris_alchemy/mixin/client/package-info.java | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | @ClientOnly | ||
| 2 | package lv.enes.mc.eris_alchemy.mixin.client; | ||
| 3 | |||
| 4 | import org.quiltmc.loader.api.minecraft.ClientOnly; \ No newline at end of file | ||
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/CovalenceRepair.java b/src/main/java/lv/enes/mc/eris_alchemy/recipe/CovalenceRepair.java index f094342..dca464a 100644 --- a/src/main/java/lv/enes/mc/eris_alchemy/CovalenceRepair.java +++ b/src/main/java/lv/enes/mc/eris_alchemy/recipe/CovalenceRepair.java | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | package lv.enes.mc.eris_alchemy; | 1 | package lv.enes.mc.eris_alchemy.recipe; |
| 2 | 2 | ||
| 3 | import com.google.gson.Gson; | 3 | import com.google.gson.Gson; |
| 4 | import com.google.gson.JsonElement; | 4 | import com.google.gson.JsonElement; |
| @@ -29,10 +29,7 @@ public class CovalenceRepair extends CustomRecipe { | |||
| 29 | JsonElement tools = new JsonObject(); | 29 | JsonElement tools = new JsonObject(); |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | private Serializer() {} | 32 | Serializer() {} |
| 33 | |||
| 34 | public static final Serializer INSTANCE = new Serializer(); | ||
| 35 | public static final ResourceLocation ID = new ResourceLocation(ErisAlchemy.ID, "covalence_repair"); | ||
| 36 | 33 | ||
| 37 | @Override | 34 | @Override |
| 38 | public JsonObject toJson(CovalenceRepair recipe) { | 35 | public JsonObject toJson(CovalenceRepair recipe) { |
| @@ -124,7 +121,7 @@ public class CovalenceRepair extends CustomRecipe { | |||
| 124 | @Nonnull | 121 | @Nonnull |
| 125 | @Override | 122 | @Override |
| 126 | public RecipeSerializer<CovalenceRepair> getSerializer() { | 123 | public RecipeSerializer<CovalenceRepair> getSerializer() { |
| 127 | return Serializer.INSTANCE; | 124 | return ErisAlchemyRecipeSerializers.COVALENCE_REPAIR; |
| 128 | } | 125 | } |
| 129 | 126 | ||
| 130 | private boolean isTool(ItemStack stack) { | 127 | private boolean isTool(ItemStack stack) { |
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/recipe/ErisAlchemyRecipeSerializers.java b/src/main/java/lv/enes/mc/eris_alchemy/recipe/ErisAlchemyRecipeSerializers.java new file mode 100644 index 0000000..c5a6676 --- /dev/null +++ b/src/main/java/lv/enes/mc/eris_alchemy/recipe/ErisAlchemyRecipeSerializers.java | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | package lv.enes.mc.eris_alchemy.recipe; | ||
| 2 | |||
| 3 | import lv.enes.mc.eris_alchemy.ErisAlchemy; | ||
| 4 | import net.minecraft.resources.ResourceLocation; | ||
| 5 | import net.minecraft.world.item.crafting.Recipe; | ||
| 6 | import net.minecraft.world.item.crafting.RecipeSerializer; | ||
| 7 | |||
| 8 | import java.util.LinkedHashMap; | ||
| 9 | import java.util.Map; | ||
| 10 | import java.util.function.BiConsumer; | ||
| 11 | |||
| 12 | public final class ErisAlchemyRecipeSerializers { | ||
| 13 | private static final Map<ResourceLocation, RecipeSerializer<?>> serializers = new LinkedHashMap<>(); | ||
| 14 | |||
| 15 | public static final RecipeSerializer<CovalenceRepair> COVALENCE_REPAIR = register("covalence_repair", new CovalenceRepair.Serializer()); | ||
| 16 | |||
| 17 | public static void consumeSerializers(BiConsumer<? super ResourceLocation, ? super RecipeSerializer<?>> consumer) { | ||
| 18 | serializers.forEach(consumer); | ||
| 19 | } | ||
| 20 | |||
| 21 | private static <T extends Recipe<?>> RecipeSerializer<T> register(String id, RecipeSerializer<T> serializer) { | ||
| 22 | serializers.putIfAbsent(new ResourceLocation(ErisAlchemy.ID, id), serializer); | ||
| 23 | return serializer; | ||
| 24 | } | ||
| 25 | |||
| 26 | private ErisAlchemyRecipeSerializers() {} | ||
| 27 | } | ||
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/SubAxe.java b/src/main/java/lv/enes/mc/eris_alchemy/utils/AxeUtils.java index 045a5a1..22c0bad 100644 --- a/src/main/java/lv/enes/mc/eris_alchemy/SubAxe.java +++ b/src/main/java/lv/enes/mc/eris_alchemy/utils/AxeUtils.java | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | package lv.enes.mc.eris_alchemy; | 1 | package lv.enes.mc.eris_alchemy.utils; |
| 2 | 2 | ||
| 3 | import net.minecraft.world.item.AxeItem; | 3 | import net.minecraft.world.item.AxeItem; |
| 4 | import net.minecraft.world.item.Tier; | 4 | import net.minecraft.world.item.Tier; |
| @@ -6,13 +6,13 @@ import net.minecraft.world.level.block.Block; | |||
| 6 | 6 | ||
| 7 | import java.util.Map; | 7 | import java.util.Map; |
| 8 | 8 | ||
| 9 | /** The only reason this exists is to read STRIPPABLES property from AxeItem :3 */ | 9 | /** This extends AxeItem only to read the STRIPPABLES variable :3 */ |
| 10 | public abstract class SubAxe extends AxeItem { | 10 | public final class AxeUtils extends AxeItem { |
| 11 | public static Map<Block, Block> getStrippables() { | 11 | public static Map<Block, Block> getStrippables() { |
| 12 | return STRIPPABLES; | 12 | return STRIPPABLES; |
| 13 | } | 13 | } |
| 14 | 14 | ||
| 15 | private SubAxe(Tier material, float attackDamage, float attackSpeed, Properties settings) { | 15 | private AxeUtils(Tier material, float attackDamage, float attackSpeed, Properties settings) { |
| 16 | super(material, attackDamage, attackSpeed, settings); | 16 | super(material, attackDamage, attackSpeed, settings); |
| 17 | } | 17 | } |
| 18 | } | 18 | } |
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/utils/BlockUtils.java b/src/main/java/lv/enes/mc/eris_alchemy/utils/BlockUtils.java index 74b6069..88b6231 100644 --- a/src/main/java/lv/enes/mc/eris_alchemy/utils/BlockUtils.java +++ b/src/main/java/lv/enes/mc/eris_alchemy/utils/BlockUtils.java | |||
| @@ -6,8 +6,10 @@ import net.minecraft.world.level.block.Block; | |||
| 6 | 6 | ||
| 7 | import java.util.stream.Stream; | 7 | import java.util.stream.Stream; |
| 8 | 8 | ||
| 9 | public class BlockUtils { | 9 | public final class BlockUtils { |
| 10 | public static Stream<Block> streamTag(TagKey<Block> tag) { | 10 | public static Stream<Block> streamTag(TagKey<Block> tag) { |
| 11 | return TagUtils.stream(BuiltInRegistries.BLOCK, tag); | 11 | return TagUtils.stream(BuiltInRegistries.BLOCK, tag); |
| 12 | } | 12 | } |
| 13 | |||
| 14 | private BlockUtils() {} | ||
| 13 | } | 15 | } |
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/utils/CoralUtils.java b/src/main/java/lv/enes/mc/eris_alchemy/utils/CoralUtils.java index c9203c6..1136c9e 100644 --- a/src/main/java/lv/enes/mc/eris_alchemy/utils/CoralUtils.java +++ b/src/main/java/lv/enes/mc/eris_alchemy/utils/CoralUtils.java | |||
| @@ -5,7 +5,7 @@ import net.minecraft.world.level.block.*; | |||
| 5 | 5 | ||
| 6 | import java.util.stream.Stream; | 6 | import java.util.stream.Stream; |
| 7 | 7 | ||
| 8 | public class CoralUtils { | 8 | public final class CoralUtils { |
| 9 | /** | 9 | /** |
| 10 | * @see lv.enes.mc.eris_alchemy.mixin.CoralBlockMixin | 10 | * @see lv.enes.mc.eris_alchemy.mixin.CoralBlockMixin |
| 11 | * @see lv.enes.mc.eris_alchemy.mixin.CoralFanBlockMixin | 11 | * @see lv.enes.mc.eris_alchemy.mixin.CoralFanBlockMixin |
| @@ -39,4 +39,6 @@ public class CoralUtils { | |||
| 39 | public static Block getDeadCoralBlock(CoralBlock live) { | 39 | public static Block getDeadCoralBlock(CoralBlock live) { |
| 40 | return ((CoralSuper)live).lv_enes_mc$getDead(); | 40 | return ((CoralSuper)live).lv_enes_mc$getDead(); |
| 41 | } | 41 | } |
| 42 | |||
| 43 | private CoralUtils() {} | ||
| 42 | } | 44 | } |
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/utils/DyeUtils.java b/src/main/java/lv/enes/mc/eris_alchemy/utils/DyeUtils.java index 83c8e04..3ceb965 100644 --- a/src/main/java/lv/enes/mc/eris_alchemy/utils/DyeUtils.java +++ b/src/main/java/lv/enes/mc/eris_alchemy/utils/DyeUtils.java | |||
| @@ -7,7 +7,7 @@ import net.minecraft.world.level.block.Blocks; | |||
| 7 | import net.minecraft.world.level.block.ConcretePowderBlock; | 7 | import net.minecraft.world.level.block.ConcretePowderBlock; |
| 8 | import net.minecraft.world.level.block.ShulkerBoxBlock; | 8 | import net.minecraft.world.level.block.ShulkerBoxBlock; |
| 9 | 9 | ||
| 10 | public class DyeUtils { | 10 | public final class DyeUtils { |
| 11 | public static Block getConcrete(DyeColor color) { | 11 | public static Block getConcrete(DyeColor color) { |
| 12 | return switch (color) { | 12 | return switch (color) { |
| 13 | case BLACK -> Blocks.BLACK_CONCRETE; | 13 | case BLACK -> Blocks.BLACK_CONCRETE; |
| @@ -57,4 +57,6 @@ public class DyeUtils { | |||
| 57 | public static ShulkerBoxBlock getShulkerBox(DyeColor color) { | 57 | public static ShulkerBoxBlock getShulkerBox(DyeColor color) { |
| 58 | return (ShulkerBoxBlock)ShulkerBoxBlock.getBlockByColor(color); | 58 | return (ShulkerBoxBlock)ShulkerBoxBlock.getBlockByColor(color); |
| 59 | } | 59 | } |
| 60 | |||
| 61 | private DyeUtils() {} | ||
| 60 | } | 62 | } |
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/utils/ItemUtils.java b/src/main/java/lv/enes/mc/eris_alchemy/utils/ItemUtils.java index 2f7c8b2..26d4405 100644 --- a/src/main/java/lv/enes/mc/eris_alchemy/utils/ItemUtils.java +++ b/src/main/java/lv/enes/mc/eris_alchemy/utils/ItemUtils.java | |||
| @@ -6,8 +6,10 @@ import net.minecraft.world.item.Item; | |||
| 6 | 6 | ||
| 7 | import java.util.stream.Stream; | 7 | import java.util.stream.Stream; |
| 8 | 8 | ||
| 9 | public class ItemUtils { | 9 | public final class ItemUtils { |
| 10 | public static Stream<Item> streamTag(TagKey<Item> tag) { | 10 | public static Stream<Item> streamTag(TagKey<Item> tag) { |
| 11 | return TagUtils.stream(BuiltInRegistries.ITEM, tag); | 11 | return TagUtils.stream(BuiltInRegistries.ITEM, tag); |
| 12 | } | 12 | } |
| 13 | |||
| 14 | private ItemUtils() {} | ||
| 13 | } | 15 | } |
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/utils/RecipeUtils.java b/src/main/java/lv/enes/mc/eris_alchemy/utils/RecipeUtils.java index 53ceaab..0eb6a2c 100644 --- a/src/main/java/lv/enes/mc/eris_alchemy/utils/RecipeUtils.java +++ b/src/main/java/lv/enes/mc/eris_alchemy/utils/RecipeUtils.java | |||
| @@ -7,7 +7,7 @@ import net.minecraft.world.item.crafting.Recipe; | |||
| 7 | 7 | ||
| 8 | import java.util.List; | 8 | import java.util.List; |
| 9 | 9 | ||
| 10 | public class RecipeUtils { | 10 | public final class RecipeUtils { |
| 11 | public interface RecipeSuper { | 11 | public interface RecipeSuper { |
| 12 | List<Ingredient> lv_enes_mc$getIngredients(); | 12 | List<Ingredient> lv_enes_mc$getIngredients(); |
| 13 | ItemStack lv_enes_mc$getOutput(RegistryAccess registryAccess); | 13 | ItemStack lv_enes_mc$getOutput(RegistryAccess registryAccess); |
| @@ -20,4 +20,6 @@ public class RecipeUtils { | |||
| 20 | public static ItemStack getOutput(Recipe<?> recipe, RegistryAccess registryAccess) { | 20 | public static ItemStack getOutput(Recipe<?> recipe, RegistryAccess registryAccess) { |
| 21 | return ((RecipeSuper)recipe).lv_enes_mc$getOutput(registryAccess); | 21 | return ((RecipeSuper)recipe).lv_enes_mc$getOutput(registryAccess); |
| 22 | } | 22 | } |
| 23 | |||
| 24 | private RecipeUtils() {} | ||
| 23 | } | 25 | } |
diff --git a/src/main/java/lv/enes/mc/eris_alchemy/utils/TagUtils.java b/src/main/java/lv/enes/mc/eris_alchemy/utils/TagUtils.java index bb923ba..93e577f 100644 --- a/src/main/java/lv/enes/mc/eris_alchemy/utils/TagUtils.java +++ b/src/main/java/lv/enes/mc/eris_alchemy/utils/TagUtils.java | |||
| @@ -7,8 +7,10 @@ import net.minecraft.tags.TagKey; | |||
| 7 | import java.util.stream.Stream; | 7 | import java.util.stream.Stream; |
| 8 | import java.util.stream.StreamSupport; | 8 | import java.util.stream.StreamSupport; |
| 9 | 9 | ||
| 10 | public class TagUtils { | 10 | public final class TagUtils { |
| 11 | public static <T> Stream<T> stream(Registry<T> registry, TagKey<T> tag) { | 11 | public static <T> Stream<T> stream(Registry<T> registry, TagKey<T> tag) { |
| 12 | return StreamSupport.stream(registry.getTagOrEmpty(tag).spliterator(), false).map(Holder::value); | 12 | return StreamSupport.stream(registry.getTagOrEmpty(tag).spliterator(), false).map(Holder::value); |
| 13 | } | 13 | } |
| 14 | |||
| 15 | private TagUtils() {} | ||
| 14 | } | 16 | } |