package com.thebrokenrail.energonrelics.api.block.entity.core; import com.thebrokenrail.energonrelics.EnergonRelics; import com.thebrokenrail.energonrelics.api.energy.Action; import com.thebrokenrail.energonrelics.component.NetworkComponent; import com.thebrokenrail.energonrelics.config.HardcodedConfig; import com.thebrokenrail.energonrelics.api.energy.tick.EnergyTickable; import com.thebrokenrail.energonrelics.api.energy.tick.EnergyTicker; import com.thebrokenrail.energonrelics.util.BlockPosWithDimension; import net.fabricmc.fabric.api.block.entity.BlockEntityClientSerializable; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntityType; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.Tickable; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraft.util.registry.RegistryKey; import net.minecraft.world.World; import java.util.Collections; import java.util.List; import java.util.Objects; /** * Block Entity That Provides Energy */ public class EnergyProviderBlockEntity extends BlockEntity implements BlockEntityClientSerializable, Tickable, EnergyTickable { public EnergyProviderBlockEntity(BlockEntityType type) { super(type); } /** * Give Propagated Action To This Block * @param action Action */ public final void addPropagatedAction(Action.PropagatedAction action) { if (isEnergyProvider()) { handlePropagatedAction(action); } else { throw new UnsupportedOperationException(); } } /** * Is In Energy Network * @param network Network ID * @return If Is In Network */ public final boolean isNetwork(int network) { return isEnergyProvider() && EnergonRelics.NETWORK_CHIP_ITEM.getID(stack) == network; } /** * Is Within Valid Distance Of Position * @param pos Position * @return Is Within Distance */ public final boolean isWithinDistance(Vec3d pos) { return getPos().isWithinDistance(pos, HardcodedConfig.POWER_RANGE); } /** * Get Current Dimension * @return Current Dimension */ public RegistryKey getRegistryKey() { return Objects.requireNonNull(getWorld()).getRegistryKey(); } private ItemStack stack = ItemStack.EMPTY; @Override public CompoundTag toTag(CompoundTag tag) { super.toTag(tag); if (isEnergyProvider()) { tag.put("NetworkChip", stack.toTag(new CompoundTag())); } return tag; } @Override public void fromTag(BlockState state, CompoundTag tag) { super.fromTag(state, tag); if (isEnergyProvider()) { stack = ItemStack.fromTag(tag.getCompound("NetworkChip")); } else { stack = ItemStack.EMPTY; } } /** * Should Behave As Energy Provider * @return Is Energy Provider */ public boolean isEnergyProvider() { return false; } /** * Override To Handle Propagated Action * @param action Propagated Action */ protected void handlePropagatedAction(Action.PropagatedAction action) { if (!isEnergyProvider()) { throw new UnsupportedOperationException(); } } @Override public void logicTick() { } @Override public List startTick() { if (isEnergyProvider() && stack.getItem() == EnergonRelics.NETWORK_CHIP_ITEM) { NetworkComponent component = NetworkComponent.getInstance((ServerWorld) Objects.requireNonNull(getWorld())); List sources = component.getSourcesPos(EnergonRelics.NETWORK_CHIP_ITEM.getID(stack)); if (!sources.contains(new BlockPosWithDimension(getPos(), getWorld().getRegistryKey()))) { takeStack(getWorld()); } } return Collections.emptyList(); } @Override public final void tick() { if (hasWorld() && !Objects.requireNonNull(getWorld()).isClient()) { EnergyTicker.schedule(this); } } private static void setEnergyProviderSource(World world, BlockPos pos, ItemStack stack, boolean remove) { ServerWorld serverWorld = (ServerWorld) world; NetworkComponent component = NetworkComponent.getInstance(serverWorld); BlockPosWithDimension newPos = new BlockPosWithDimension(pos, world.getRegistryKey()); if (remove) { component.removeSource(EnergonRelics.NETWORK_CHIP_ITEM.getID(stack), newPos); } else { component.addSource(EnergonRelics.NETWORK_CHIP_ITEM.getID(stack), newPos); } } /** * Take Network Chip Item Stack * @param world World * @return Item Stack */ public ItemStack takeStack(World world) { ItemStack newStack = stack.copy(); setEnergyProviderSource(world, getPos(), newStack, true); stack = ItemStack.EMPTY; markDirty(); return newStack; } /** * Place Network Chip Item Stack * @param newStack Item Stack * @param world World */ public void placeStack(ItemStack newStack, World world) { setEnergyProviderSource(world, getPos(), newStack, false); stack = newStack.copy(); markDirty(); } /** * Has Item Stack * @return Has Item Stack */ public boolean hasStack() { return !stack.isEmpty(); } @Override public void fromClientTag(CompoundTag compoundTag) { fromTag(Blocks.AIR.getDefaultState(), compoundTag); } @Override public CompoundTag toClientTag(CompoundTag compoundTag) { return toTag(compoundTag); } @Override public void markDirty() { super.markDirty(); if (hasWorld()) { sync(); } } @Override public String getID() { return String.valueOf(BlockEntityType.getId(getType())); } }