mirror of
https://github.com/XevianLight/Aphelion.git
synced 2026-05-11 01:50:56 +01:00
Basic development
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
package net.xevianlight.aphelion.block.custom;
|
||||
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.SoundType;
|
||||
|
||||
public class BlockSteel extends Block {
|
||||
public BlockSteel(Properties properties) {
|
||||
super(properties);
|
||||
}
|
||||
|
||||
public static Properties getProperties() {
|
||||
return Properties
|
||||
.of()
|
||||
.sound(SoundType.NETHERITE_BLOCK)
|
||||
.destroyTime(2f)
|
||||
.explosionResistance(10f)
|
||||
.requiresCorrectToolForDrops();
|
||||
}
|
||||
|
||||
public static Item.Properties getItemProperties() {
|
||||
return new Item.Properties();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package net.xevianlight.aphelion.block.custom;
|
||||
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.BaseEntityBlock;
|
||||
import net.minecraft.world.level.block.RenderShape;
|
||||
import net.minecraft.world.level.block.SoundType;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.portal.DimensionTransition;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.xevianlight.aphelion.block.entity.custom.DimensionChangerBlockEntity;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class DimensionChangerBlock extends BaseEntityBlock {
|
||||
|
||||
public DimensionChangerBlock(Properties properties) {
|
||||
super(properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MapCodec<? extends BaseEntityBlock> codec() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Properties getProperties() {
|
||||
return Properties
|
||||
.of()
|
||||
.sound(SoundType.ANVIL)
|
||||
.destroyTime(2f)
|
||||
.explosionResistance(10f)
|
||||
.requiresCorrectToolForDrops();
|
||||
}
|
||||
|
||||
public static Item.Properties getItemProperties() {
|
||||
return new Item.Properties().stacksTo(3);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult result) {
|
||||
|
||||
|
||||
if (!level.isClientSide && player instanceof ServerPlayer serverPlayer && level.getBlockEntity(pos) instanceof DimensionChangerBlockEntity dimensionChangerBlockEntity) {
|
||||
ServerLevel sourceDim = serverPlayer.serverLevel();
|
||||
ServerLevel targetDim = serverPlayer.server.getLevel(Level.NETHER);
|
||||
serverPlayer.changeDimension(new DimensionTransition(
|
||||
targetDim,
|
||||
serverPlayer.position().multiply(
|
||||
sourceDim.dimensionType().coordinateScale() / targetDim.dimensionType().coordinateScale(),
|
||||
1,
|
||||
sourceDim.dimensionType().coordinateScale() / targetDim.dimensionType().coordinateScale()),
|
||||
Vec3.ZERO, serverPlayer.getYRot(),
|
||||
serverPlayer.getXRot(),
|
||||
DimensionTransition.PLAY_PORTAL_SOUND
|
||||
));
|
||||
}
|
||||
return InteractionResult.sidedSuccess(level.isClientSide);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
|
||||
super.tick(state, level, pos, random);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable BlockEntity newBlockEntity(BlockPos blockPos, BlockState blockState) {
|
||||
return new DimensionChangerBlockEntity(blockPos, blockState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RenderShape getRenderShape(BlockState pState) {
|
||||
return RenderShape.MODEL;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
|
||||
if (state.getBlock() != newState.getBlock()) {
|
||||
BlockEntity blockEntity= level.getBlockEntity(pos);
|
||||
if (blockEntity instanceof DimensionChangerBlockEntity dimensionChangerBlockEntity) {
|
||||
dimensionChangerBlockEntity.drops();
|
||||
}
|
||||
}
|
||||
super.onRemove(state, level, pos, newState, movedByPiston);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
package net.xevianlight.aphelion.block.custom;
|
||||
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.SimpleMenuProvider;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.*;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityTicker;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.StateDefinition;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
||||
import net.minecraft.world.level.block.state.properties.DirectionProperty;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.neoforged.neoforge.items.ItemStackHandler;
|
||||
import net.xevianlight.aphelion.block.entity.custom.ElectricArcFurnaceEntity;
|
||||
import net.xevianlight.aphelion.core.init.ModBlockEntities;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ElectricArcFurnace extends BaseEntityBlock {
|
||||
|
||||
public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING;
|
||||
public static final BooleanProperty LIT = BlockStateProperties.LIT;
|
||||
|
||||
public ElectricArcFurnace(Properties properties) {
|
||||
super(properties);
|
||||
}
|
||||
|
||||
public static final MapCodec<ElectricArcFurnace> CODEC = simpleCodec(ElectricArcFurnace::new);
|
||||
|
||||
@Override
|
||||
protected MapCodec<? extends BaseEntityBlock> codec() {
|
||||
return CODEC;
|
||||
}
|
||||
|
||||
public static Properties getProperties() {
|
||||
return Properties
|
||||
.of()
|
||||
.sound(SoundType.METAL)
|
||||
.destroyTime(2f)
|
||||
.explosionResistance(10f)
|
||||
.requiresCorrectToolForDrops();
|
||||
}
|
||||
|
||||
public static Item.Properties getItemProperties() {
|
||||
return new Item.Properties();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult result) {
|
||||
|
||||
if (!level.isClientSide && player instanceof ServerPlayer serverPlayer && level.getBlockEntity(pos) instanceof ElectricArcFurnaceEntity electricArcFurnaceEntity) {
|
||||
serverPlayer.openMenu(new SimpleMenuProvider(electricArcFurnaceEntity, Component.literal("Electric Arc Furnace")), pos);
|
||||
}
|
||||
return InteractionResult.sidedSuccess(level.isClientSide);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public @Nullable BlockEntity newBlockEntity(BlockPos blockPos, BlockState blockState) {
|
||||
return new ElectricArcFurnaceEntity(blockPos, blockState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RenderShape getRenderShape(BlockState pState) {
|
||||
return RenderShape.MODEL;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
|
||||
if (state.getBlock() != newState.getBlock()) {
|
||||
BlockEntity blockEntity= level.getBlockEntity(pos);
|
||||
if (blockEntity instanceof ElectricArcFurnaceEntity electricArcFurnaceEntity) {
|
||||
electricArcFurnaceEntity.drops();
|
||||
}
|
||||
}
|
||||
super.onRemove(state, level, pos, newState, movedByPiston);
|
||||
}
|
||||
|
||||
public static int getRedstoneSignalFromItemHandler(@javax.annotation.Nullable ItemStackHandler itemStackHandler, List<Integer> slots) {
|
||||
if (itemStackHandler == null) {
|
||||
return 0;
|
||||
} else {
|
||||
int i = 0;
|
||||
float f = 0.0F;
|
||||
|
||||
for(int slot : slots) {
|
||||
ItemStack itemstack = itemStackHandler.getStackInSlot(slot);
|
||||
if (!itemstack.isEmpty()) {
|
||||
f += (float)itemstack.getCount() / (float)Math.min(itemStackHandler.getSlotLimit(slot), itemstack.getMaxStackSize());
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
f /= (float)slots.size();
|
||||
return Mth.floor(f * 14.0F) + (i > 0 ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isSignalSource(BlockState state) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getSignal(BlockState state, BlockGetter level, BlockPos pos, Direction direction) {
|
||||
return super.getSignal(state, level, pos, direction);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean hasAnalogOutputSignal(BlockState state) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getAnalogOutputSignal(BlockState blockState, Level level, BlockPos pos) {
|
||||
List<Integer> slots = new ArrayList<>();
|
||||
slots.add(0);
|
||||
slots.add(1);
|
||||
slots.add(2);
|
||||
slots.add(3);
|
||||
ElectricArcFurnaceEntity electricArcFurnaceEntity = ((ElectricArcFurnaceEntity) level.getBlockEntity(pos));
|
||||
return getRedstoneSignalFromItemHandler(electricArcFurnaceEntity.inventory, slots);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState state, BlockEntityType<T> blockEntityType) {
|
||||
if (level.isClientSide) {
|
||||
return null;
|
||||
}
|
||||
return createTickerHelper(blockEntityType, ModBlockEntities.ELECTRIC_ARC_FURNACE_ENTITY.get(), (level1, blockPos, blockState, electricArcFurnaceEntity) -> electricArcFurnaceEntity.tick(level1, blockPos, blockState));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BlockState rotate(BlockState state, Rotation rotation) {
|
||||
return state.setValue(FACING, rotation.rotate(state.getValue(FACING)));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BlockState mirror(BlockState state, Mirror mirror) {
|
||||
return state.rotate(mirror.getRotation(state.getValue(FACING)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable BlockState getStateForPlacement(BlockPlaceContext context) {
|
||||
return this.defaultBlockState().setValue(FACING, context.getHorizontalDirection().getOpposite()).setValue(LIT, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
|
||||
builder.add(FACING, LIT);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
package net.xevianlight.aphelion.block.custom;
|
||||
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.SimpleMenuProvider;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.BaseEntityBlock;
|
||||
import net.minecraft.world.level.block.RenderShape;
|
||||
import net.minecraft.world.level.block.SoundType;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityTicker;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.neoforged.neoforge.items.ItemStackHandler;
|
||||
import net.xevianlight.aphelion.block.entity.custom.TestBlockEntity;
|
||||
import net.xevianlight.aphelion.core.init.ModBlockEntities;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class TestBlock extends BaseEntityBlock {
|
||||
public TestBlock(Properties properties) {
|
||||
super(properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MapCodec<? extends BaseEntityBlock> codec() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Properties getProperties() {
|
||||
return Properties
|
||||
.of()
|
||||
.sound(SoundType.ANVIL)
|
||||
.destroyTime(2f)
|
||||
.explosionResistance(10f)
|
||||
.requiresCorrectToolForDrops();
|
||||
}
|
||||
|
||||
public static Item.Properties getItemProperties() {
|
||||
return new Item.Properties().stacksTo(3);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult result) {
|
||||
|
||||
if (!level.isClientSide && player instanceof ServerPlayer serverPlayer && level.getBlockEntity(pos) instanceof TestBlockEntity testBlockEntity) {
|
||||
serverPlayer.openMenu(new SimpleMenuProvider(testBlockEntity, Component.literal("Test Block")), pos);
|
||||
}
|
||||
return InteractionResult.sidedSuccess(level.isClientSide);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public @Nullable BlockEntity newBlockEntity(BlockPos blockPos, BlockState blockState) {
|
||||
return new TestBlockEntity(blockPos, blockState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RenderShape getRenderShape(BlockState pState) {
|
||||
return RenderShape.MODEL;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
|
||||
if (state.getBlock() != newState.getBlock()) {
|
||||
BlockEntity blockEntity= level.getBlockEntity(pos);
|
||||
if (blockEntity instanceof TestBlockEntity testBlockEntity) {
|
||||
testBlockEntity.drops();
|
||||
}
|
||||
}
|
||||
super.onRemove(state, level, pos, newState, movedByPiston);
|
||||
}
|
||||
|
||||
public static int getRedstoneSignalFromItemHandler(@javax.annotation.Nullable ItemStackHandler itemStackHandler, List<Integer> slots) {
|
||||
if (itemStackHandler == null) {
|
||||
return 0;
|
||||
} else {
|
||||
int i = 0;
|
||||
float f = 0.0F;
|
||||
|
||||
for(int slot : slots) {
|
||||
ItemStack itemstack = itemStackHandler.getStackInSlot(slot);
|
||||
if (!itemstack.isEmpty()) {
|
||||
f += (float)itemstack.getCount() / (float)Math.min(itemStackHandler.getSlotLimit(slot), itemstack.getMaxStackSize());
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
f /= (float)slots.size();
|
||||
return Mth.floor(f * 14.0F) + (i > 0 ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isSignalSource(BlockState state) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getSignal(BlockState state, BlockGetter level, BlockPos pos, Direction direction) {
|
||||
return super.getSignal(state, level, pos, direction);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean hasAnalogOutputSignal(BlockState state) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getAnalogOutputSignal(BlockState blockState, Level level, BlockPos pos) {
|
||||
List<Integer> slots = new ArrayList<>();
|
||||
slots.add(0);
|
||||
TestBlockEntity testBlockEntity = ((TestBlockEntity) level.getBlockEntity(pos));
|
||||
return getRedstoneSignalFromItemHandler(testBlockEntity.inventory, slots);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState state, BlockEntityType<T> blockEntityType) {
|
||||
if (level.isClientSide) {
|
||||
return null;
|
||||
}
|
||||
return createTickerHelper(blockEntityType, ModBlockEntities.TEST_BLOCK_ENTITY.get(), (level1, blockPos, blockState, testBlockEntity) -> testBlockEntity.tick(level1, blockPos, blockState));
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package net.xevianlight.aphelion.block.entity.custom;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.core.NonNullList;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.Containers;
|
||||
import net.minecraft.world.MenuProvider;
|
||||
import net.minecraft.world.SimpleContainer;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.neoforged.neoforge.items.IItemHandler;
|
||||
import net.neoforged.neoforge.items.ItemStackHandler;
|
||||
import net.xevianlight.aphelion.core.init.ModBlockEntities;
|
||||
import net.xevianlight.aphelion.screen.TestBlockMenu;
|
||||
import net.xevianlight.aphelion.util.SidedSlotHandler;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class DimensionChangerBlockEntity extends BlockEntity implements MenuProvider {
|
||||
|
||||
private final int SIZE = 1;
|
||||
|
||||
private NonNullList<ItemStack> items = NonNullList.withSize(SIZE, ItemStack.EMPTY);
|
||||
|
||||
public DimensionChangerBlockEntity(BlockPos pos, BlockState blockState) {
|
||||
super(ModBlockEntities.DIMENSION_CHANGER_BLOCK_ENTITY.get(), pos, blockState);
|
||||
}
|
||||
|
||||
public final ItemStackHandler inventory = new ItemStackHandler(SIZE) {
|
||||
@Override
|
||||
protected void onContentsChanged(int slot) {
|
||||
setChanged();
|
||||
if(!level.isClientSide()) {
|
||||
level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 3);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public void sendUpdate() {
|
||||
setChanged();
|
||||
level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 3);
|
||||
}
|
||||
|
||||
private final IItemHandler topHandler = new SidedSlotHandler(inventory, new int[]{0}, true, false);
|
||||
private final IItemHandler bottomHandler = new SidedSlotHandler(inventory, new int[]{0}, false, true);
|
||||
private final IItemHandler jadeHandler = new SidedSlotHandler(inventory, new int[]{0}, false, false);
|
||||
|
||||
public IItemHandler getItemHandler(Direction direction) {
|
||||
if (direction == Direction.UP) return topHandler;
|
||||
if (direction == Direction.DOWN) return bottomHandler;
|
||||
if (direction == null) return jadeHandler;
|
||||
return null;
|
||||
}
|
||||
|
||||
public ItemStackHandler getInventory() {
|
||||
return inventory;
|
||||
}
|
||||
|
||||
public void drops() {
|
||||
SimpleContainer inv = new SimpleContainer(inventory.getSlots());
|
||||
for(int i = 0; i < inventory.getSlots(); i++) {
|
||||
inv.setItem(i, inventory.getStackInSlot(i));
|
||||
}
|
||||
|
||||
Containers.dropContents(this.level, this.worldPosition, inv);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveAdditional(CompoundTag pTag, HolderLookup.Provider pRegistries) {
|
||||
pTag.put("inventory", inventory.serializeNBT(pRegistries));
|
||||
super.saveAdditional(pTag, pRegistries);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadAdditional(CompoundTag pTag, HolderLookup.Provider pRegistries) {
|
||||
super.loadAdditional(pTag, pRegistries);
|
||||
inventory.deserializeNBT(pRegistries, pTag.getCompound("inventory"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getDisplayName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable AbstractContainerMenu createMenu(int i, Inventory inventory, Player player) {
|
||||
return new TestBlockMenu(i, inventory, this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,311 @@
|
||||
package net.xevianlight.aphelion.block.entity.custom;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.network.protocol.game.ClientGamePacketListener;
|
||||
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
||||
import net.minecraft.world.Containers;
|
||||
import net.minecraft.world.MenuProvider;
|
||||
import net.minecraft.world.SimpleContainer;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraft.world.inventory.ContainerData;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.item.crafting.*;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.neoforged.neoforge.capabilities.Capabilities;
|
||||
import net.neoforged.neoforge.energy.EnergyStorage;
|
||||
import net.neoforged.neoforge.energy.IEnergyStorage;
|
||||
import net.neoforged.neoforge.items.IItemHandler;
|
||||
import net.neoforged.neoforge.items.ItemStackHandler;
|
||||
import net.xevianlight.aphelion.Aphelion;
|
||||
import net.xevianlight.aphelion.block.custom.ElectricArcFurnace;
|
||||
import net.xevianlight.aphelion.block.entity.energy.ModEnergyStorage;
|
||||
import net.xevianlight.aphelion.block.entity.energy.ModEnergyUtil;
|
||||
import net.xevianlight.aphelion.client.dimension.DimensionRendererCache;
|
||||
import net.xevianlight.aphelion.core.init.ModBlockEntities;
|
||||
import net.xevianlight.aphelion.screen.ElectricArcFurnaceMenu;
|
||||
import net.xevianlight.aphelion.util.SidedSlotHandler;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class ElectricArcFurnaceEntity extends BlockEntity implements MenuProvider {
|
||||
|
||||
private final int SIZE = 4;
|
||||
private int ENERGY_CAPACITY = 64000;
|
||||
private int MAX_TRANSFER = 320;
|
||||
private int progress = 0;
|
||||
private int maxProgress = 100;
|
||||
private final int DEFAULT_MAX_PROGRESS = 100;
|
||||
private final ContainerData data;
|
||||
private int Blasting_ENERGY_COST = 20;
|
||||
|
||||
private final int INPUT_SLOT = 0;
|
||||
private final int SECONDARY_INPUT_SLOT = 1;
|
||||
private final int OUTPUT_SLOT = 2;
|
||||
private final int ENERGY_SLOT = 3;
|
||||
|
||||
public ElectricArcFurnaceEntity(BlockPos pos, BlockState blockState) {
|
||||
super(ModBlockEntities.ELECTRIC_ARC_FURNACE_ENTITY.get(), pos, blockState);
|
||||
this.data = new ContainerData() {
|
||||
@Override
|
||||
public int get(int index) {
|
||||
return switch (index) {
|
||||
case 0 -> ElectricArcFurnaceEntity.this.progress;
|
||||
case 1 -> ElectricArcFurnaceEntity.this.maxProgress;
|
||||
default -> 0;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(int index, int pValue) {
|
||||
switch (index) {
|
||||
case 0: ElectricArcFurnaceEntity.this.progress = pValue;
|
||||
case 1: ElectricArcFurnaceEntity.this.maxProgress = pValue;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return 2;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public final ItemStackHandler inventory = new ItemStackHandler(SIZE) {
|
||||
@Override
|
||||
protected void onContentsChanged(int slot) {
|
||||
setChanged();
|
||||
if(!level.isClientSide()) {
|
||||
level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 3);
|
||||
}
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public boolean isItemValid(int slot, ItemStack stack) {
|
||||
// if (slot == ENERGY_SLOT) {
|
||||
// var capability = stack.getCapability(Capabilities.EnergyStorage.ITEM);
|
||||
// return capability != null;
|
||||
// }
|
||||
// return super.isItemValid(slot, stack);
|
||||
// }
|
||||
};
|
||||
|
||||
public void tick(Level level, BlockPos pos, BlockState blockState) {
|
||||
|
||||
if (inventory.getStackInSlot(SECONDARY_INPUT_SLOT).isEmpty()) {
|
||||
if (hasFurnaceRecipe(INPUT_SLOT) && hasEnoughEnergyToCraft(Blasting_ENERGY_COST)) {
|
||||
progress++;
|
||||
useEnergyForBlasting();
|
||||
level.setBlockAndUpdate(pos, blockState.setValue(ElectricArcFurnace.LIT, true));
|
||||
setChanged(level, pos, blockState);
|
||||
|
||||
if (hasCraftingFinished()) {
|
||||
outputBlastingResult(INPUT_SLOT, OUTPUT_SLOT);
|
||||
resetProgress();
|
||||
}
|
||||
} else if (hasFurnaceRecipe(INPUT_SLOT) && !hasEnoughEnergyToCraft(Blasting_ENERGY_COST)) {
|
||||
level.setBlockAndUpdate(pos, blockState.setValue(ElectricArcFurnace.LIT, false));
|
||||
setChanged(level, pos, blockState);
|
||||
progress = progress > 0 ? progress - 1 : 0;
|
||||
} else {
|
||||
resetProgress();
|
||||
level.setBlockAndUpdate(pos, blockState.setValue(ElectricArcFurnace.LIT, false));
|
||||
setChanged(level, pos, blockState);
|
||||
}
|
||||
} else {
|
||||
resetProgress();
|
||||
level.setBlockAndUpdate(pos, blockState.setValue(ElectricArcFurnace.LIT, false));
|
||||
setChanged(level, pos, blockState);
|
||||
}
|
||||
|
||||
chargeFromItem();
|
||||
}
|
||||
|
||||
private void chargeFromItem() {
|
||||
ItemStack stack;
|
||||
|
||||
try {
|
||||
stack = inventory.getStackInSlot(ENERGY_SLOT);
|
||||
|
||||
if (stack.isEmpty()) return;
|
||||
|
||||
IEnergyStorage itemEnergy = stack.getCapability(Capabilities.EnergyStorage.ITEM);
|
||||
if (itemEnergy == null || !itemEnergy.canExtract()) return;
|
||||
|
||||
int freeCapacity = ENERGY_STORAGE.getMaxEnergyStored() - ENERGY_STORAGE.getEnergyStored();
|
||||
if (freeCapacity <= 0) return;
|
||||
|
||||
int maxMove = Math.min(MAX_TRANSFER, freeCapacity);
|
||||
|
||||
// Simulate extraction first
|
||||
int canExtract = itemEnergy.extractEnergy(maxMove, true);
|
||||
if (canExtract <= 0) return;
|
||||
|
||||
// Receive into block (simulate then execute is safest)
|
||||
int canReceive = ENERGY_STORAGE.receiveEnergy(canExtract, true);
|
||||
if (canReceive <= 0) return;
|
||||
|
||||
int extracted = itemEnergy.extractEnergy(canReceive, false);
|
||||
ENERGY_STORAGE.receiveEnergy(maxMove, false);
|
||||
|
||||
setChanged();
|
||||
} catch (Exception e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void outputBlastingResult(int slot, int resultSlot) {
|
||||
Optional<RecipeHolder<BlastingRecipe>> recipe = getFurnaceRecipe(inventory.getStackInSlot(slot));
|
||||
ItemStack output = recipe.get().value().getResultItem(null);
|
||||
|
||||
// 2x multiplier for smelting recipes
|
||||
|
||||
inventory.extractItem(slot, 1, false);
|
||||
inventory.setStackInSlot(resultSlot, new ItemStack(output.getItem(),
|
||||
inventory.getStackInSlot(resultSlot).getCount() + (output.getCount() * 2)));
|
||||
}
|
||||
|
||||
private void resetProgress() {
|
||||
this.progress = 0;
|
||||
this.maxProgress = DEFAULT_MAX_PROGRESS;
|
||||
}
|
||||
|
||||
private void useEnergyForBlasting() {
|
||||
this.ENERGY_STORAGE.extractEnergy(Blasting_ENERGY_COST, false);
|
||||
}
|
||||
|
||||
private boolean hasEnoughEnergyToCraft(int energyCost) {
|
||||
return ENERGY_STORAGE.getEnergyStored() >= energyCost;
|
||||
}
|
||||
|
||||
private boolean canInsertItemIntoOutputSlot(ItemStack output, int slot) {
|
||||
return inventory.getStackInSlot(slot).isEmpty() ||
|
||||
inventory.getStackInSlot(slot).getItem() == output.getItem();
|
||||
}
|
||||
|
||||
private boolean canInsertAmountIntoOutputSlot(int count, int slot) {
|
||||
int maxCount = inventory.getStackInSlot(slot).isEmpty() ? 64 : inventory.getStackInSlot(slot).getMaxStackSize();
|
||||
int currentCount = inventory.getStackInSlot(slot).getCount();
|
||||
|
||||
return maxCount >= currentCount + count;
|
||||
}
|
||||
|
||||
private boolean isOutputSlotEmptyOrReceivable(int slot) {
|
||||
return this.inventory.getStackInSlot(slot).isEmpty() ||
|
||||
this.inventory.getStackInSlot(slot).getCount() < this.inventory.getStackInSlot(slot).getMaxStackSize();
|
||||
}
|
||||
|
||||
private boolean hasCraftingFinished() {
|
||||
return this.progress >= this.maxProgress;
|
||||
}
|
||||
|
||||
private boolean hasFurnaceRecipe(int slot) {
|
||||
Optional<RecipeHolder<BlastingRecipe>> recipe = getFurnaceRecipe(new ItemStack(inventory.getStackInSlot(slot).getItem().asItem(), 1));
|
||||
if (recipe.isEmpty())
|
||||
return false;
|
||||
|
||||
ItemStack output = recipe.get().value().getResultItem(null);
|
||||
return canInsertAmountIntoOutputSlot(output.getCount() * 2, OUTPUT_SLOT) && canInsertItemIntoOutputSlot(output, OUTPUT_SLOT);
|
||||
}
|
||||
|
||||
private Optional<RecipeHolder<BlastingRecipe>> getFurnaceRecipe(ItemStack stack) {
|
||||
if (stack.isEmpty()) return Optional.empty();
|
||||
|
||||
return this.level.getRecipeManager()
|
||||
.getRecipeFor(RecipeType.BLASTING, new SingleRecipeInput(stack), level);
|
||||
|
||||
}
|
||||
|
||||
public void sendUpdate() {
|
||||
setChanged();
|
||||
level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 3);
|
||||
}
|
||||
|
||||
private final IItemHandler fullHandler = new SidedSlotHandler(inventory, new int[]{0,1}, true, true);
|
||||
private final IItemHandler inputHandler = new SidedSlotHandler(inventory, new int[]{0,1}, true, true);
|
||||
private final IItemHandler outputHandler = new SidedSlotHandler(inventory, new int[]{2,3}, false, true);
|
||||
private final IItemHandler jadeHandler = new SidedSlotHandler(inventory, new int[]{0}, false, false);
|
||||
|
||||
public IItemHandler getItemHandler(Direction direction) {
|
||||
return fullHandler;
|
||||
}
|
||||
|
||||
public IEnergyStorage getEnergyStorage(@Nullable Direction direction) {
|
||||
return this.ENERGY_STORAGE;
|
||||
}
|
||||
|
||||
private final ModEnergyStorage ENERGY_STORAGE = createEnergyStorage();
|
||||
private ModEnergyStorage createEnergyStorage() {
|
||||
return new ModEnergyStorage(ENERGY_CAPACITY, MAX_TRANSFER) {
|
||||
@Override
|
||||
public void onEnergyChanged() {
|
||||
setChanged();
|
||||
getLevel().sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 3);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public ItemStackHandler getInventory() {
|
||||
return inventory;
|
||||
}
|
||||
|
||||
public void drops() {
|
||||
SimpleContainer inv = new SimpleContainer(inventory.getSlots());
|
||||
for(int i = 0; i < inventory.getSlots(); i++) {
|
||||
inv.setItem(i, inventory.getStackInSlot(i));
|
||||
}
|
||||
|
||||
Containers.dropContents(this.level, this.worldPosition, inv);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveAdditional(CompoundTag tag, HolderLookup.Provider pRegistries) {
|
||||
tag.put("inventory", inventory.serializeNBT(pRegistries));
|
||||
tag.putInt("electric_arc_furnace.progress", progress);
|
||||
tag.putInt("electric_arc_furnace.maxProgress", maxProgress);
|
||||
tag.putInt("electric_arc_furnace.energy", ENERGY_STORAGE.getEnergyStored());
|
||||
super.saveAdditional(tag, pRegistries);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadAdditional(CompoundTag tag, HolderLookup.Provider pRegistries) {
|
||||
super.loadAdditional(tag, pRegistries);
|
||||
inventory.deserializeNBT(pRegistries, tag.getCompound("inventory"));
|
||||
progress = tag.getInt("electric_arc_furnace.progress");
|
||||
maxProgress = tag.getInt("electric_arc_furnace.maxProgress");
|
||||
ENERGY_STORAGE.setEnergy(tag.getInt("electric_arc_furnace.energy"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getDisplayName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable AbstractContainerMenu createMenu(int i, Inventory inventory, Player player) {
|
||||
return new ElectricArcFurnaceMenu(i, inventory, this, this.data);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Packet<ClientGamePacketListener> getUpdatePacket() {
|
||||
return ClientboundBlockEntityDataPacket.create(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag getUpdateTag(HolderLookup.Provider pRegistries) {
|
||||
return saveWithoutMetadata(pRegistries);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package net.xevianlight.aphelion.block.entity.custom;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.core.NonNullList;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.*;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.neoforged.neoforge.items.IItemHandler;
|
||||
import net.neoforged.neoforge.items.ItemStackHandler;
|
||||
import net.xevianlight.aphelion.core.init.ModBlockEntities;
|
||||
import net.xevianlight.aphelion.screen.TestBlockMenu;
|
||||
import net.xevianlight.aphelion.util.SidedSlotHandler;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class TestBlockEntity extends BlockEntity implements MenuProvider {
|
||||
|
||||
private final int SIZE = 1;
|
||||
|
||||
private NonNullList<ItemStack> items = NonNullList.withSize(SIZE, ItemStack.EMPTY);
|
||||
|
||||
public TestBlockEntity(BlockPos pos, BlockState blockState) {
|
||||
super(ModBlockEntities.TEST_BLOCK_ENTITY.get(), pos, blockState);
|
||||
}
|
||||
|
||||
public final ItemStackHandler inventory = new ItemStackHandler(SIZE) {
|
||||
@Override
|
||||
protected void onContentsChanged(int slot) {
|
||||
setChanged();
|
||||
if(!level.isClientSide()) {
|
||||
level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 3);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public void tick(Level level, BlockPos pos, BlockState blockState) {
|
||||
inventory.insertItem(0, new ItemStack(Items.DIAMOND), false);
|
||||
|
||||
}
|
||||
|
||||
public void sendUpdate() {
|
||||
setChanged();
|
||||
level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 3);
|
||||
}
|
||||
|
||||
private final IItemHandler topHandler = new SidedSlotHandler(inventory, new int[]{0}, true, false);
|
||||
private final IItemHandler bottomHandler = new SidedSlotHandler(inventory, new int[]{0}, false, true);
|
||||
private final IItemHandler jadeHandler = new SidedSlotHandler(inventory, new int[]{0}, false, false);
|
||||
|
||||
public IItemHandler getItemHandler(Direction direction) {
|
||||
if (direction == Direction.UP) return topHandler;
|
||||
if (direction == Direction.DOWN) return bottomHandler;
|
||||
if (direction == null) return jadeHandler;
|
||||
return null;
|
||||
}
|
||||
|
||||
public ItemStackHandler getInventory() {
|
||||
return inventory;
|
||||
}
|
||||
|
||||
public void drops() {
|
||||
SimpleContainer inv = new SimpleContainer(inventory.getSlots());
|
||||
for(int i = 0; i < inventory.getSlots(); i++) {
|
||||
inv.setItem(i, inventory.getStackInSlot(i));
|
||||
}
|
||||
|
||||
Containers.dropContents(this.level, this.worldPosition, inv);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveAdditional(CompoundTag pTag, HolderLookup.Provider pRegistries) {
|
||||
pTag.put("inventory", inventory.serializeNBT(pRegistries));
|
||||
super.saveAdditional(pTag, pRegistries);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadAdditional(CompoundTag pTag, HolderLookup.Provider pRegistries) {
|
||||
super.loadAdditional(pTag, pRegistries);
|
||||
inventory.deserializeNBT(pRegistries, pTag.getCompound("inventory"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getDisplayName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable AbstractContainerMenu createMenu(int i, Inventory inventory, Player player) {
|
||||
return new TestBlockMenu(i, inventory, this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package net.xevianlight.aphelion.block.entity.custom;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.core.NonNullList;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.*;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.block.entity.BaseContainerBlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.xevianlight.aphelion.core.init.ModBlockEntities;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class TestBlockEntity2 extends BaseContainerBlockEntity implements WorldlyContainer {
|
||||
|
||||
// The constructor, like before.
|
||||
public TestBlockEntity2 (BlockPos pos, BlockState blockState) {
|
||||
super(ModBlockEntities.TEST_BLOCK_ENTITY.get(), pos, blockState);
|
||||
}
|
||||
// The container size. This can of course be any value you want.
|
||||
public static final int SIZE = 9;
|
||||
// Our item stack list. This is not final due to #setItems existing.
|
||||
private NonNullList<ItemStack> items = NonNullList.withSize(SIZE, ItemStack.EMPTY);
|
||||
|
||||
// The container size, like before.
|
||||
@Override
|
||||
public int getContainerSize() {
|
||||
return SIZE;
|
||||
}
|
||||
|
||||
// The getter for our item stack list.
|
||||
@Override
|
||||
protected NonNullList<ItemStack> getItems() {
|
||||
return items;
|
||||
}
|
||||
|
||||
// The setter for our item stack list.
|
||||
@Override
|
||||
protected void setItems(NonNullList<ItemStack> items) {
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
// The display name of the menu. Don't forget to add a translation!
|
||||
@Override
|
||||
protected Component getDefaultName() {
|
||||
return Component.translatable("container.examplemod.myblockentity");
|
||||
}
|
||||
|
||||
// The menu to create from this container. See below for what to return here.
|
||||
@Override
|
||||
protected AbstractContainerMenu createMenu(int containerId, Inventory inventory) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getSlotsForFace(Direction direction) {
|
||||
return new int[] {0,1,2,3,4,5,6,7,8};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPlaceItemThroughFace(int i, ItemStack itemStack, @Nullable Direction direction) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canTakeItemThroughFace(int i, ItemStack itemStack, Direction direction) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadAdditional(CompoundTag nbt, HolderLookup.Provider provider) {
|
||||
super.loadAdditional(nbt, provider);
|
||||
this.items = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY);
|
||||
ContainerHelper.loadAllItems(nbt, this.items, provider);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveAdditional(CompoundTag nbt, HolderLookup.Provider provider) {
|
||||
super.saveAdditional(nbt, provider);
|
||||
ContainerHelper.saveAllItems(nbt, this.items, provider);
|
||||
}
|
||||
|
||||
public void dropContents() {
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
ItemStack stack = getItem(i);
|
||||
Containers.dropItemStack(level, (double) worldPosition.getX(), (double) worldPosition.getY(), (double) worldPosition.getZ(), stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package net.xevianlight.aphelion.block.entity.energy;
|
||||
|
||||
import net.neoforged.neoforge.energy.EnergyStorage;
|
||||
|
||||
public abstract class ModEnergyStorage extends EnergyStorage {
|
||||
public ModEnergyStorage(int capacity, int maxTransfer) {
|
||||
super(capacity, maxTransfer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int extractEnergy(int maxExtract, boolean simulate) {
|
||||
int extractedEnergy = super.extractEnergy(maxExtract, simulate);
|
||||
if(extractedEnergy != 0) {
|
||||
onEnergyChanged();
|
||||
}
|
||||
|
||||
return extractedEnergy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int receiveEnergy(int maxReceive, boolean simulate) {
|
||||
int receiveEnergy = super.receiveEnergy(maxReceive, simulate);
|
||||
if(receiveEnergy != 0) {
|
||||
onEnergyChanged();
|
||||
}
|
||||
|
||||
return receiveEnergy;
|
||||
}
|
||||
|
||||
public int setEnergy(int energy) {
|
||||
this.energy = energy;
|
||||
return energy;
|
||||
}
|
||||
|
||||
public abstract void onEnergyChanged();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package net.xevianlight.aphelion.block.entity.energy;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.neoforged.neoforge.capabilities.Capabilities;
|
||||
import net.neoforged.neoforge.energy.IEnergyStorage;
|
||||
|
||||
public class ModEnergyUtil {
|
||||
public static boolean move(BlockPos from, BlockPos to, int amount, Level level) {
|
||||
IEnergyStorage fromStorage = level.getCapability(Capabilities.EnergyStorage.BLOCK, from, null);
|
||||
IEnergyStorage toStorage = level.getCapability(Capabilities.EnergyStorage.BLOCK, to, null);
|
||||
|
||||
if(canEnergyStorageExtractThisAmount(fromStorage, amount)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(canEnergyStorageStillReceiveEnergy(toStorage)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int maxAmountToReceive = toStorage.receiveEnergy(amount, true);
|
||||
|
||||
int extractedEnergy = fromStorage.extractEnergy(maxAmountToReceive, false);
|
||||
toStorage.receiveEnergy(extractedEnergy, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean canEnergyStorageStillReceiveEnergy(IEnergyStorage toStorage) {
|
||||
// No more Energy to draw or cannot extract
|
||||
return toStorage.getEnergyStored() >= toStorage.getMaxEnergyStored() || !toStorage.canReceive();
|
||||
}
|
||||
|
||||
private static boolean canEnergyStorageExtractThisAmount(IEnergyStorage fromStorage, int amount) {
|
||||
// No more Space to receive or cannot receive
|
||||
return fromStorage.getEnergyStored() <= 0 || fromStorage.getEnergyStored() < amount || !fromStorage.canExtract();
|
||||
}
|
||||
|
||||
public static boolean doesBlockHaveEnergyStorage(BlockPos positionToCheck, Level level) {
|
||||
return level.getBlockEntity(positionToCheck) != null
|
||||
&& level.getCapability(Capabilities.EnergyStorage.BLOCK, positionToCheck, null) != null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user