From 000b84e87eaedb94fb87ccb11e376c51f99a1d07 Mon Sep 17 00:00:00 2001 From: Uko Kokņevičs Date: Wed, 10 Jan 2024 17:41:07 +0100 Subject: Added Energy Condenser --- .../block/entity/AlchemicalChestBlockEntity.java | 46 ----- .../block/entity/AlchemicalChestEntity.java | 39 ++++ .../block/entity/ChestLikeBlockEntity.java | 200 -------------------- .../eris_alchemy/block/entity/ChestLikeEntity.java | 207 +++++++++++++++++++++ .../block/entity/EnergyCondenserEntity.java | 143 ++++++++++++++ 5 files changed, 389 insertions(+), 246 deletions(-) delete mode 100644 src/main/java/lv/enes/mc/eris_alchemy/block/entity/AlchemicalChestBlockEntity.java create mode 100644 src/main/java/lv/enes/mc/eris_alchemy/block/entity/AlchemicalChestEntity.java delete mode 100644 src/main/java/lv/enes/mc/eris_alchemy/block/entity/ChestLikeBlockEntity.java create mode 100644 src/main/java/lv/enes/mc/eris_alchemy/block/entity/ChestLikeEntity.java create mode 100644 src/main/java/lv/enes/mc/eris_alchemy/block/entity/EnergyCondenserEntity.java (limited to 'src/main/java/lv/enes/mc/eris_alchemy/block/entity') 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 deleted file mode 100644 index bac49b6..0000000 --- a/src/main/java/lv/enes/mc/eris_alchemy/block/entity/AlchemicalChestBlockEntity.java +++ /dev/null @@ -1,46 +0,0 @@ -package lv.enes.mc.eris_alchemy.block.entity; - -import jakarta.annotation.Nonnull; -import lv.enes.mc.eris_alchemy.ErisAlchemyRegistry; -import lv.enes.mc.eris_alchemy.menu.AlchemicalChestMenu; -import lv.enes.mc.eris_alchemy.menu.ChestLikeBlockMenu; -import net.minecraft.core.BlockPos; -import net.minecraft.core.NonNullList; -import net.minecraft.network.chat.Component; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; - -public class AlchemicalChestBlockEntity extends ChestLikeBlockEntity { - private final static int WIDTH = 13; - private final static int HEIGHT = 8; - - private final NonNullList items = NonNullList.withSize(WIDTH * HEIGHT, ItemStack.EMPTY); - - public AlchemicalChestBlockEntity(BlockPos pos, BlockState state) { - super(ErisAlchemyRegistry.BlockEntities.ALCHEMICAL_CHEST, pos, state); - } - - @Nonnull - @Override - protected ChestLikeBlockMenu createMenu(int syncId, Inventory playerInventory) { - return new AlchemicalChestMenu(syncId, playerInventory, this); - } - - @Nonnull - @Override - protected Component getDefaultName() { - return Component.translatable("container.eris_alchemy.alchemical_chest"); - } - - @Override - protected NonNullList getItems() { - return items; - } - - @Override - protected Block getParent() { - return ErisAlchemyRegistry.Blocks.ALCHEMICAL_CHEST; - } -} diff --git a/src/main/java/lv/enes/mc/eris_alchemy/block/entity/AlchemicalChestEntity.java b/src/main/java/lv/enes/mc/eris_alchemy/block/entity/AlchemicalChestEntity.java new file mode 100644 index 0000000..38ed902 --- /dev/null +++ b/src/main/java/lv/enes/mc/eris_alchemy/block/entity/AlchemicalChestEntity.java @@ -0,0 +1,39 @@ +package lv.enes.mc.eris_alchemy.block.entity; + +import jakarta.annotation.Nonnull; +import lv.enes.mc.eris_alchemy.ErisAlchemyRegistry; +import lv.enes.mc.eris_alchemy.menu.AlchemicalChestMenu; +import lv.enes.mc.eris_alchemy.menu.ChestLikeMenu; +import net.minecraft.core.BlockPos; +import net.minecraft.core.NonNullList; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; + +public class AlchemicalChestEntity extends ChestLikeEntity { + private final static int WIDTH = 13; + private final static int HEIGHT = 8; + + private final NonNullList items = NonNullList.withSize(WIDTH * HEIGHT, ItemStack.EMPTY); + + public AlchemicalChestEntity(BlockPos pos, BlockState state) { + super(ErisAlchemyRegistry.BlockEntities.ALCHEMICAL_CHEST, pos, state); + } + + @Nonnull + @Override + protected ChestLikeMenu createMenu(int syncId, Inventory playerInventory) { + return new AlchemicalChestMenu(syncId, playerInventory, this); + } + + @Override + protected NonNullList getItems() { + return items; + } + + @Override + protected Block getParent() { + return ErisAlchemyRegistry.Blocks.ALCHEMICAL_CHEST; + } +} 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/ChestLikeBlockEntity.java deleted file mode 100644 index 48b3ad7..0000000 --- a/src/main/java/lv/enes/mc/eris_alchemy/block/entity/ChestLikeBlockEntity.java +++ /dev/null @@ -1,200 +0,0 @@ -package lv.enes.mc.eris_alchemy.block.entity; - -import jakarta.annotation.Nonnull; -import jakarta.annotation.Nullable; -import lv.enes.mc.eris_alchemy.menu.ChestLikeBlockMenu; -import net.minecraft.core.BlockPos; -import net.minecraft.core.NonNullList; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.world.Container; -import net.minecraft.world.ContainerHelper; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.*; -import net.minecraft.world.level.block.state.BlockState; - -public abstract class ChestLikeBlockEntity extends BaseContainerBlockEntity implements LidBlockEntity { - protected static final int EVENT_INTERACTED = 1; - - protected final ChestLidController lidController = new ChestLidController(); - protected final ContainerOpenersCounter openersCounter = new ContainerOpenersCounter() { - @Override - protected void onOpen(Level world, BlockPos pos, BlockState state) { - ChestLikeBlockEntity.this.onOpen(world, pos); - } - - @Override - protected void onClose(Level world, BlockPos pos, BlockState state) { - ChestLikeBlockEntity.this.onClose(world, pos); - } - - @Override - protected void openerCountChanged(Level world, BlockPos pos, BlockState state, int oldViewerCount, int newViewerCount) { - world.blockEvent(worldPosition, getParent(), EVENT_INTERACTED, newViewerCount); - } - - @Override - protected boolean isOwnContainer(Player player) { - if (player.containerMenu instanceof ChestLikeBlockMenu menu) { - return menu.getContainer() == ChestLikeBlockEntity.this; - } - return false; - } - }; - - public ChestLikeBlockEntity( - BlockEntityType type, - BlockPos pos, - BlockState state - ) { - super(type, pos, state); - } - - protected abstract Block getParent(); - protected abstract NonNullList getItems(); - - @Override - public void clearContent() { - getItems().clear(); - } - - @Override - public int getContainerSize() { - return getItems().size(); - } - - @Nonnull - @Override - public ItemStack getItem(int slot) { - return getItems().get(slot); - } - - @Override - public float getOpenNess(float tickDelta) { - return lidController.getOpenness(tickDelta); - } - - @Override - public boolean isEmpty() { - return getItems().stream().allMatch(ItemStack::isEmpty); - } - - @Override - public void load(CompoundTag nbt) { - super.load(nbt); - ContainerHelper.loadAllItems(nbt, getItems()); - } - - protected void onClose(@Nullable Level world, BlockPos pos) { - if (world == null) { - return; - } - - world.playSound( - null, - pos.getX() + 0.5, - pos.getY() + 0.5, - pos.getZ() + 0.5, - SoundEvents.CHEST_OPEN, - SoundSource.BLOCKS, - 0.5f, - world.random.nextFloat() * 0.1f + 0.9f - ); - } - - protected void onOpen(@Nullable Level world, BlockPos pos) { - if (world == null) { - return; - } - - world.playSound( - null, - pos.getX() + 0.5, - pos.getY() + 0.5, - pos.getZ() + 0.5, - SoundEvents.CHEST_CLOSE, - SoundSource.BLOCKS, - 0.5f, - world.random.nextFloat() * 0.1f + 0.9f - ); - } - - private void recheckOpen() { - if (!remove) { - openersCounter.recheckOpeners(getLevel(), getBlockPos(), getBlockState()); - } - } - - @Nonnull - @Override - public ItemStack removeItem(int slot, int amount) { - var stack = ContainerHelper.removeItem(getItems(), slot, amount); - if (!stack.isEmpty()) { - this.setChanged(); - } - return stack; - } - - @Nonnull - @Override - public ItemStack removeItemNoUpdate(int slot) { - return ContainerHelper.takeItem(getItems(), slot); - } - - @Override - protected void saveAdditional(CompoundTag nbt) { - super.saveAdditional(nbt); - ContainerHelper.saveAllItems(nbt, getItems()); - } - - @Override - public void setItem(int slot, ItemStack stack) { - getItems().set(slot, stack); - if (stack.getCount() > getMaxStackSize()) { - stack.setCount(getMaxStackSize()); - } - this.setChanged(); - } - - @Override - public void startOpen(Player player) { - if (!remove && !player.isSpectator()) { - openersCounter.incrementOpeners(player, getLevel(), getBlockPos(), getBlockState()); - } - } - - @Override - public boolean stillValid(Player player) { - return Container.stillValidBlockEntity(this, player); - } - - @Override - public void stopOpen(Player player) { - if (!remove && !player.isSpectator()) { - openersCounter.decrementOpeners(player, getLevel(), getBlockPos(), getBlockState()); - } - } - - public void tick(Level world, BlockPos ignoredPos, BlockState ignoredState) { - if (world.isClientSide) { - lidController.tickLid(); - } - recheckOpen(); - } - - - @Override - public boolean triggerEvent(int type, int data) { - if (type == EVENT_INTERACTED) { - lidController.shouldBeOpen(data > 0); - return true; - } - - return super.triggerEvent(type, data); - } -} - diff --git a/src/main/java/lv/enes/mc/eris_alchemy/block/entity/ChestLikeEntity.java b/src/main/java/lv/enes/mc/eris_alchemy/block/entity/ChestLikeEntity.java new file mode 100644 index 0000000..362b054 --- /dev/null +++ b/src/main/java/lv/enes/mc/eris_alchemy/block/entity/ChestLikeEntity.java @@ -0,0 +1,207 @@ +package lv.enes.mc.eris_alchemy.block.entity; + +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; +import lv.enes.mc.eris_alchemy.menu.ChestLikeMenu; +import net.minecraft.core.BlockPos; +import net.minecraft.core.NonNullList; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.Container; +import net.minecraft.world.ContainerHelper; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.*; +import net.minecraft.world.level.block.state.BlockState; + +public abstract class ChestLikeEntity extends BaseContainerBlockEntity implements LidBlockEntity { + protected static final int EVENT_INTERACTED = 1; + + protected final ChestLidController lidController = new ChestLidController(); + protected final ContainerOpenersCounter openersCounter = new ContainerOpenersCounter() { + @Override + protected void onOpen(Level world, BlockPos pos, BlockState state) { + ChestLikeEntity.this.onOpen(world, pos); + } + + @Override + protected void onClose(Level world, BlockPos pos, BlockState state) { + ChestLikeEntity.this.onClose(world, pos); + } + + @Override + protected void openerCountChanged(Level world, BlockPos pos, BlockState state, int oldViewerCount, int newViewerCount) { + world.blockEvent(worldPosition, getParent(), EVENT_INTERACTED, newViewerCount); + } + + @Override + protected boolean isOwnContainer(Player player) { + if (player.containerMenu instanceof ChestLikeMenu menu) { + return menu.getContainer() == ChestLikeEntity.this; + } + return false; + } + }; + + public ChestLikeEntity( + BlockEntityType type, + BlockPos pos, + BlockState state + ) { + super(type, pos, state); + } + + protected abstract Block getParent(); + protected abstract NonNullList getItems(); + + @Override + public void clearContent() { + getItems().clear(); + } + + @Override + public int getContainerSize() { + return getItems().size(); + } + + @Nonnull + @Override + protected Component getDefaultName() { + return getBlockState().getBlock().getName(); + } + + @Nonnull + @Override + public ItemStack getItem(int slot) { + return getItems().get(slot); + } + + @Override + public float getOpenNess(float tickDelta) { + return lidController.getOpenness(tickDelta); + } + + @Override + public boolean isEmpty() { + return getItems().stream().allMatch(ItemStack::isEmpty); + } + + @Override + public void load(CompoundTag nbt) { + super.load(nbt); + ContainerHelper.loadAllItems(nbt, getItems()); + } + + protected void onClose(@Nullable Level world, BlockPos pos) { + if (world == null) { + return; + } + + world.playSound( + null, + pos.getX() + 0.5, + pos.getY() + 0.5, + pos.getZ() + 0.5, + SoundEvents.CHEST_OPEN, + SoundSource.BLOCKS, + 0.5f, + world.random.nextFloat() * 0.1f + 0.9f + ); + } + + protected void onOpen(@Nullable Level world, BlockPos pos) { + if (world == null) { + return; + } + + world.playSound( + null, + pos.getX() + 0.5, + pos.getY() + 0.5, + pos.getZ() + 0.5, + SoundEvents.CHEST_CLOSE, + SoundSource.BLOCKS, + 0.5f, + world.random.nextFloat() * 0.1f + 0.9f + ); + } + + private void recheckOpen() { + if (!remove) { + openersCounter.recheckOpeners(getLevel(), getBlockPos(), getBlockState()); + } + } + + @Nonnull + @Override + public ItemStack removeItem(int slot, int amount) { + var stack = ContainerHelper.removeItem(getItems(), slot, amount); + if (!stack.isEmpty()) { + setChanged(); + } + return stack; + } + + @Nonnull + @Override + public ItemStack removeItemNoUpdate(int slot) { + return ContainerHelper.takeItem(getItems(), slot); + } + + @Override + protected void saveAdditional(CompoundTag nbt) { + super.saveAdditional(nbt); + ContainerHelper.saveAllItems(nbt, getItems()); + } + + @Override + public void setItem(int slot, ItemStack stack) { + getItems().set(slot, stack); + if (stack.getCount() > getMaxStackSize()) { + stack.setCount(getMaxStackSize()); + } + setChanged(); + } + + @Override + public void startOpen(Player player) { + if (!remove && !player.isSpectator()) { + openersCounter.incrementOpeners(player, getLevel(), getBlockPos(), getBlockState()); + } + } + + @Override + public boolean stillValid(Player player) { + return Container.stillValidBlockEntity(this, player); + } + + @Override + public void stopOpen(Player player) { + if (!remove && !player.isSpectator()) { + openersCounter.decrementOpeners(player, getLevel(), getBlockPos(), getBlockState()); + } + } + + public void tick(Level world, BlockPos ignoredPos, BlockState ignoredState) { + if (world.isClientSide) { + lidController.tickLid(); + } + recheckOpen(); + } + + + @Override + public boolean triggerEvent(int type, int data) { + if (type == EVENT_INTERACTED) { + lidController.shouldBeOpen(data > 0); + return true; + } + + return super.triggerEvent(type, data); + } +} + 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 @@ +package lv.enes.mc.eris_alchemy.block.entity; + +import jakarta.annotation.Nonnull; +import lv.enes.mc.eris_alchemy.EMC; +import lv.enes.mc.eris_alchemy.ErisAlchemyRegistry; +import lv.enes.mc.eris_alchemy.menu.ChestLikeMenu; +import lv.enes.mc.eris_alchemy.menu.EnergyCondenserMenu; +import lv.enes.mc.eris_alchemy.utils.ContainerOpenersCounterUtil; +import lv.enes.mc.eris_alchemy.utils.SyncedValue.SyncedDouble; +import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory; +import net.minecraft.core.BlockPos; +import net.minecraft.core.NonNullList; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; + +import java.util.stream.IntStream; + +public class EnergyCondenserEntity extends ChestLikeEntity implements ExtendedScreenHandlerFactory { + private final static int WIDTH = 13; + private final static int HEIGHT = 7; + + private final NonNullList items = NonNullList.withSize(WIDTH * HEIGHT + 1, ItemStack.EMPTY); + + public final SyncedDouble storedEmc = new SyncedDouble(0); + + public EnergyCondenserEntity(BlockPos pos, BlockState state) { + super(ErisAlchemyRegistry.BlockEntities.ENERGY_CONDENSER, pos, state); + } + + @Nonnull + @Override + protected ChestLikeMenu createMenu(int syncId, Inventory playerInventory) { + return new EnergyCondenserMenu(syncId, playerInventory, this); + } + + @Override + protected NonNullList getItems() { + return items; + } + + @Override + protected Block getParent() { + return ErisAlchemyRegistry.Blocks.ENERGY_CONDENSER; + } + + public double getStoredEmc() { + return storedEmc.getValue(); + } + + public SyncedDouble getStoredEmcSyncer() { + return storedEmc; + } + + @Override + public void load(CompoundTag nbt) { + super.load(nbt); + storedEmc.setValue(nbt.getDouble("stored_emc")); + } + + @Override + protected void saveAdditional(CompoundTag nbt) { + super.saveAdditional(nbt); + nbt.putDouble("stored_emc", storedEmc.getValue()); + } + + public void setStoredEmc(double storedEmc) { + this.storedEmc.setValue(storedEmc); + setChanged(); + } + + @Override + public void tick(Level world, BlockPos pos, BlockState state) { + super.tick(world, pos, state); + EMC.getInstance(world).get(items.get(0)).ifPresent(cost -> { + tryConsumeEmc(world, cost); + tryCloneTemplate(cost); + }); + + this.storedEmc.syncIfChanged(ContainerOpenersCounterUtil.getOpeners(openersCounter)); + } + + @Override + public void writeScreenOpeningData(ServerPlayer player, FriendlyByteBuf buf) { + storedEmc.serialize(buf); + } + + private void tryCloneTemplate(double cost) { + if (cost > getStoredEmc()) { + return; + } + + var template = items.get(0); + + items.stream() + .skip(1) // skip template + .filter(stack -> ItemStack.isSameItemSameTags(template, stack)) + .filter(stack -> stack.getCount() < getMaxStackSize() && stack.getCount() < stack.getMaxStackSize()) + .findFirst() + .ifPresentOrElse( + stack -> { + stack.setCount(stack.getCount() + 1); + setStoredEmc(getStoredEmc() - cost); + setChanged(); + }, + () -> IntStream.range(1, items.size()) + .filter(i -> items.get(i).isEmpty()) + .findFirst() + .ifPresent(emptySlot -> { + items.set(emptySlot, template.copyWithCount(1)); + setStoredEmc(getStoredEmc() - cost); + setChanged(); + }) + ); + } + + private void tryConsumeEmc(Level world, double cost) { + if (cost <= getStoredEmc()) { + return; + } + + var emc = EMC.getInstance(world); + var template = items.get(0); + var sacrifice = items.stream() + .skip(1) // skip the template + .filter(stack -> !ItemStack.isSameItemSameTags(template, stack)) + .flatMap(stack -> emc.get(stack) + .stream() + .mapToObj(emcValue -> new StackEmcPair(stack, emcValue))) + .findFirst(); + sacrifice.ifPresent(pair -> { + pair.stack.setCount(pair.stack.getCount() - 1); + setStoredEmc(getStoredEmc() + pair.emc()); + }); + } + + private record StackEmcPair(ItemStack stack, double emc) {} +} -- cgit v1.2.3