Untitled

mail@pastecode.io avatar
unknown
java
2 months ago
19 kB
7
Indexable
Never
package realmayus.youmatter.creator;


import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
import net.minecraft.world.MenuProvider;
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.BucketItem;
import net.minecraft.world.item.Item;
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.minecraft.world.level.material.FlowingFluid;
import net.minecraft.world.level.material.Fluid;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.ForgeCapabilities;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.fluids.capability.templates.FluidTank;
import net.minecraftforge.items.IItemHandlerModifiable;
import net.minecraftforge.items.ItemStackHandler;
import org.jetbrains.annotations.NotNull;
import realmayus.youmatter.ModContent;
import realmayus.youmatter.YMConfig;
import realmayus.youmatter.replicator.ReplicatorBlockEntity;
import realmayus.youmatter.util.GeneralUtils;
import realmayus.youmatter.util.MyEnergyStorage;
import realmayus.youmatter.util.json.filter.FluidFilterManager;
import realmayus.youmatter.util.temperature.Status;
import realmayus.youmatter.util.temperature.TemperatureUtils;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

public class CreatorBlockEntity extends BlockEntity implements MenuProvider {

    public CreatorBlockEntity(BlockPos pos, BlockState state) {
        super(ModContent.CREATOR_BLOCK_ENTITY.get(), pos, state);
    }

    private static final int MAX_UMATTER = 16000;
    private static final int MAX_STABILIZER = 16000;
    private boolean isActivated = true;
    boolean isProducing = false;

    boolean isActivated() {
        return isActivated;
    }

    public void setActivated(boolean activated) {
        isActivated = activated;
        setChanged();

        if (level != null && !level.isClientSide) {
            level.sendBlockUpdated(worldPosition, getBlockState(), getBlockState(), 3);
        }
    }

    @Nonnull
    @Override
    public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
        if (cap == ForgeCapabilities.ITEM_HANDLER) {
            return inventory.cast();
        }

        if (cap == ForgeCapabilities.ENERGY) {
            return myEnergyStorage.cast();

        }
        if (cap == ForgeCapabilities.FLUID_HANDLER) {
            return fluidHandler.cast();

        }
        return super.getCapability(cap, side);
    }

    public LazyOptional<ItemStackHandler> inventory = LazyOptional.of(() -> new ItemStackHandler(5) {
        @Override
        protected void onContentsChanged(int slot) {
            CreatorBlockEntity.this.setChanged();
        }
    });

    private final FluidTank uTank = new FluidTank(MAX_UMATTER) {
        @Override
        protected void onContentsChanged() {
            BlockState state = level.getBlockState(worldPosition);
            level.sendBlockUpdated(worldPosition, state, state, 3);
            setChanged();
        }
    };

    private final FluidTank sTank = new FluidTank(MAX_STABILIZER) {
        @Override
        protected void onContentsChanged() {
            BlockState state = level.getBlockState(worldPosition);
            level.sendBlockUpdated(worldPosition, state, state, 3);
            setChanged();
        }
    };

    FluidTank getUTank() {
        return uTank;
    }

    FluidTank getSTank() {
        return sTank;
    }

    private final LazyOptional<IFluidHandler> fluidHandler = LazyOptional.of(() -> new IFluidHandler() {
        @Override
        public int getTanks() {
            return 2;
        }

        @Nonnull
        @Override
        public FluidStack getFluidInTank(int tank) {
            if (tank == 0) {
                return uTank.getFluid();
            } else if (tank == 1) {
                return sTank.getFluid();
            }
            return null;
        }

        @Override
        public int getTankCapacity(int tank) {
            if (tank == 0) {
                return MAX_UMATTER;
            } else if (tank == 1) {
                return MAX_STABILIZER;
            }
            return 0;
        }

        @Override
        @Deprecated
        public boolean isFluidValid(int tank, @Nonnull FluidStack stack) {
            if (tank == 0) {
                return false;
            } else
                return tank == 1 && FluidFilterManager.getFluids().stream().anyMatch(s -> s.equals(stack.getFluid()));
        }

        @Override
        @Deprecated
        public int fill(FluidStack resource, FluidAction action) {
            if (FluidFilterManager.getFluids().stream().anyMatch(s -> s.equals(resource.getFluid()))) {
                if (MAX_STABILIZER - getSTank().getFluidAmount() < resource.getAmount()) {
                    return sTank.fill(new FluidStack(resource.getFluid(), MAX_STABILIZER), action);
                } else {
                    return sTank.fill(resource, action);
                }
            }
            return 0;
        }

        @Nonnull
        @Override
        public FluidStack drain(FluidStack resource, FluidAction action) {
            if (resource.getFluid().equals(ModContent.UMATTER.get())) {
                if (uTank.getFluidAmount() < resource.getAmount()) {
                    uTank.drain(uTank.getFluid(), action);
                    return uTank.getFluid();
                } else {
                    uTank.drain(resource, action);
                    return resource;
                }
            }
            return null;
        }

        @Nonnull
        @Override
        public FluidStack drain(int maxDrain, FluidAction action) {
            if (uTank.getFluid().getFluid() != null) {
                return uTank.drain(uTank.getFluid(), action);
            } else {
                return null;
            }
        }
    });

    public void setTemperature(float temperature) {
        temperatureUtils.resolve().get().setTemperature(temperature);
    }

    public double getTemperature() {
        return temperatureUtils.resolve().get().getTemperature();
    }

    public double getMaxTemperature() {
        return temperatureUtils.resolve().get().getMaxTemperature();
    }

    public Status getStatus() { return temperatureUtils.resolve().get().getStatus(getTemperature(), getMaxTemperature());}

    private final LazyOptional<TemperatureUtils> temperatureUtils = LazyOptional.of(() -> new TemperatureUtils(this, 0.0, 1.0, 2000.0));

    public int getEnergy() {
        return myEnergyStorage.resolve().get().getEnergyStored();
    }

    public void setEnergy(int energy) {
        myEnergyStorage.resolve().get().setEnergy(energy);
    }

    private final LazyOptional<MyEnergyStorage> myEnergyStorage = LazyOptional.of(() -> new MyEnergyStorage(this, 1000000, Integer.MAX_VALUE));

    @Override
    public void setRemoved() {
        super.setRemoved();
        inventory.invalidate();
        myEnergyStorage.invalidate();
        fluidHandler.invalidate();
    }

    @Override
    public void load(CompoundTag compound) {
        super.load(compound);

        if (compound.contains("uTank")) {
            CompoundTag tagUTank = compound.getCompound("uTank");
            uTank.readFromNBT(tagUTank);
        }
        if (compound.contains("sTank")) {
            CompoundTag tagSTank = compound.getCompound("sTank");
            sTank.readFromNBT(tagSTank);
        }
        if (compound.contains("temperature")) {
            setTemperature(compound.getFloat("temperature"));
        }
        if (compound.contains("energy")) {
            setEnergy(compound.getInt("energy"));
        }
        if (compound.contains("isActivated")) {
            isActivated = compound.getBoolean("isActivated");
        }
        if (compound.contains("inventory")) {
            inventory.resolve().get().deserializeNBT((CompoundTag) compound.get("inventory"));
        }
    }


    @Override
    public void saveAdditional(CompoundTag compound) {
        super.saveAdditional(compound);
        CompoundTag tagSTank = new CompoundTag();
        CompoundTag tagUTank = new CompoundTag();
        sTank.writeToNBT(tagSTank);
        uTank.writeToNBT(tagUTank);
        compound.put("uTank", tagUTank);
        compound.put("sTank", tagSTank);
        compound.putDouble("temperature", getTemperature());
        compound.putInt("energy", getEnergy());
        compound.putBoolean("isActivated", isActivated);
        if (compound.contains("inventory")) {
            inventory.resolve().get().deserializeNBT((CompoundTag) compound.get("inventory"));
        }
    }

    @Override
    public CompoundTag getUpdateTag() {
        return saveWithoutMetadata();
    }

    @Override
    public ClientboundBlockEntityDataPacket getUpdatePacket() {
        return ClientboundBlockEntityDataPacket.create(this);
    }

    private int currentPartTick = 0;

    private void meltdown(Level level, BlockPos pos) {
        if (YMConfig.CONFIG.creatorExplodes.get()) {
            if (!level.isClientSide()) {
                level.destroyBlock(this.getBlockPos(), false);
                level.explode(null, pos.getX(), pos.getY(), pos.getZ(), 16.0F, Level.ExplosionInteraction.TNT);
            }
        }
    }

    public static void tick(Level level, BlockPos pos, BlockState state, CreatorBlockEntity be) {
        be.tick(level, pos, state);
    }
    @Deprecated
    public void tick(Level level, BlockPos pos, BlockState state) {
        if (currentPartTick == 20) {
            if (getStatus() == Status.MELTDOWN) {
                meltdown(level, pos);
            }
            isProducing = isActivated() && getEnergy() >= 0.3f * 1000000;
            if (isProducing) {
                temperatureUtils.ifPresent(temperatureUtils -> {
                    temperatureUtils.heat(100.0F);
                    int production = TemperatureUtils.calculateProduction(getTemperature());
                    if (uTank.getFluidAmount() + production <= MAX_UMATTER) {
                        uTank.fill(new FluidStack(ModContent.UMATTER.get(), production), IFluidHandler.FluidAction.EXECUTE);
                        myEnergyStorage.ifPresent(storage -> storage.extractEnergy(Math.round(getEnergy() / 3f), false));
                    }
                });
            }
            //Auto-outputting U-Matter
            Object[] neighborTE = getNeighborTileEntity(pos);
            if (neighborTE != null) {
                if (uTank.getFluidAmount() >= 1000) { // set a maximum output of 500 mB (every two seconds)
                    uTank.drain(level.getBlockEntity((BlockPos) neighborTE[0]).getCapability(ForgeCapabilities.FLUID_HANDLER, (Direction) neighborTE[1]).map(h -> h.fill(new FluidStack(ModContent.UMATTER.get(), 1000), IFluidHandler.FluidAction.EXECUTE)).orElse(0), IFluidHandler.FluidAction.EXECUTE);
                } else {
                    uTank.drain(level.getBlockEntity((BlockPos) neighborTE[0]).getCapability(ForgeCapabilities.FLUID_HANDLER, (Direction) neighborTE[1]).map(h -> h.fill(new FluidStack(ModContent.UMATTER.get(), uTank.getFluidAmount()), IFluidHandler.FluidAction.EXECUTE)).orElse(0), IFluidHandler.FluidAction.EXECUTE);
                }
            }
            currentPartTick = 0;
        } else if ((currentPartTick % 5) == 0) { // every five ticks
            inventory.ifPresent(inventory -> {
                if (!(inventory.getStackInSlot(3).isEmpty()) && GeneralUtils.canAddItemToSlot(inventory.getStackInSlot(4), inventory.getStackInSlot(3), false)) {
                    ItemStack item = inventory.getStackInSlot(3);
                    if (item.getItem() instanceof BucketItem) {
                        if (getUTank().getFluidAmount() >= 1000) {
                            getUTank().drain(1000, IFluidHandler.FluidAction.EXECUTE);
                            inventory.setStackInSlot(3, ItemStack.EMPTY);
                            inventory.insertItem(4, new ItemStack(ModContent.UMATTER_BUCKET.get(), 1), false);
                        }
                    } else {
                        item.getCapability(ForgeCapabilities.FLUID_HANDLER_ITEM).ifPresent(h -> {
                            if (h.getFluidInTank(0).getFluid().isSame(ModContent.UMATTER.get()) || h.getFluidInTank(0).isEmpty()) {
                                if (h.getTankCapacity(0) - h.getFluidInTank(0).getAmount() < getUTank().getFluidAmount()) { //fluid in S-Tank is more than what fits in the item's tank
                                    getUTank().drain(h.fill(new FluidStack(ModContent.UMATTER.get(), h.getTankCapacity(0) - h.getFluidInTank(0).getAmount()), IFluidHandler.FluidAction.EXECUTE), IFluidHandler.FluidAction.EXECUTE);
                                } else { //S-Tank's fluid fits perfectly in item's tank
                                    getUTank().drain(h.fill(getUTank().getFluid(), IFluidHandler.FluidAction.EXECUTE), IFluidHandler.FluidAction.EXECUTE);
                                }
                            }
                        });
                        inventory.setStackInSlot(3, ItemStack.EMPTY);
                        inventory.insertItem(4, item, false);
                    }
                }
                if (!inventory.getStackInSlot(1).isEmpty()) {
                    ItemStack item = inventory.getStackInSlot(1);
                    if (item.getItem() instanceof BucketItem && GeneralUtils.canAddItemToSlot(inventory.getStackInSlot(2), new ItemStack(Items.BUCKET, 1), false)) {
                        item.getCapability(ForgeCapabilities.FLUID_HANDLER_ITEM).ifPresent(h -> {
                            if (!h.getFluidInTank(0).isEmpty() && isFluidAllowed(h.getFluidInTank(0).getFluid())) {
                                if (MAX_STABILIZER - getSTank().getFluidAmount() >= 1000) {
                                    if(getSTank().isEmpty() || getSTank().getFluidInTank(0).getFluid().isSame(h.getFluidInTank(0).getFluid())) {
                                        getSTank().fill(new FluidStack(h.getFluidInTank(0).getFluid(), 1000), IFluidHandler.FluidAction.EXECUTE);
                                        inventory.setStackInSlot(1, ItemStack.EMPTY);
                                        inventory.insertItem(2, new ItemStack(Items.BUCKET, 1), false);
                                    }
                                }
                            }
                        });
                    } else if(GeneralUtils.canAddItemToSlot(inventory.getStackInSlot(2), inventory.getStackInSlot(1), false)) {
                        item.getCapability(ForgeCapabilities.FLUID_HANDLER_ITEM).ifPresent(h -> {
                            if (isFluidAllowed(h.getFluidInTank(0).getFluid())) {
                                if (h.getFluidInTank(0).getAmount() > MAX_STABILIZER - getSTank().getFluidAmount()) { //given fluid is more than what fits in the S-Tank
                                    if (getSTank().isEmpty() || getSTank().getFluidInTank(0).getFluid().isSame(h.getFluidInTank(0).getFluid())) {
                                        getSTank().fill(h.drain(MAX_STABILIZER - getSTank().getFluidAmount(), IFluidHandler.FluidAction.EXECUTE), IFluidHandler.FluidAction.EXECUTE);
                                    }
                                } else {
                                    if (getSTank().isEmpty() || getSTank().getFluidInTank(0).getFluid().isSame(h.getFluidInTank(0).getFluid())) { //given fluid fits perfectly in S-Tank
                                        getSTank().fill(h.drain(h.getFluidInTank(0).getAmount(), IFluidHandler.FluidAction.EXECUTE), IFluidHandler.FluidAction.EXECUTE);
                                    }
                                }
                            }
                        });
                        inventory.setStackInSlot(1, ItemStack.EMPTY);
                        inventory.insertItem(2, item, false);
                    }
                }
            });
            currentPartTick++;
        } else {
            currentPartTick++;
        }
    }


    @Deprecated
    private boolean isFluidAllowed(Fluid fluid) {
        boolean matches = FluidFilterManager.getFluids().stream().anyMatch(s -> s.equals(fluid));
        if (FluidFilterManager.getFilterMode() && matches) {
            return false;
        } else return FluidFilterManager.getFilterMode() || matches;
    }

    private Object[] getNeighborTileEntity(BlockPos creatorPos) {
        HashMap<BlockPos, Direction> foundPos = new HashMap<>();
        for(Direction facing : Direction.values()) {
            BlockPos offsetPos = creatorPos.relative(facing);
            BlockEntity offsetBe = level.getBlockEntity(offsetPos);

            if(offsetBe != null) {
                offsetBe.getCapability(ForgeCapabilities.FLUID_HANDLER, facing).ifPresent(x -> foundPos.put(offsetPos, facing));
            }
        }

        // Prioritize Replicator
        for (Map.Entry<BlockPos, Direction> entry : foundPos.entrySet()) {
            if (level.getBlockEntity(entry.getKey()) instanceof ReplicatorBlockEntity replicator) {
                if(replicator.getCapability(ForgeCapabilities.FLUID_HANDLER, entry.getValue()).map(h -> h.fill(new FluidStack(ModContent.UMATTER.get(), 1000), IFluidHandler.FluidAction.SIMULATE)).orElse(0) > 0) {
                    //Replicator can take fluid
                    return new Object[] {entry.getKey(), entry.getValue()}; // position, facing
                }
            }
        }

        // Replicator not found / can't take fluid, now trying other blocks
        for (Map.Entry<BlockPos, Direction> entry : foundPos.entrySet()) {
            if(Objects.requireNonNull(level.getBlockEntity(entry.getKey())).getCapability(ForgeCapabilities.FLUID_HANDLER, entry.getValue()).map(h -> h.fill(new FluidStack(ModContent.UMATTER.get(), 1000), IFluidHandler.FluidAction.SIMULATE)).orElse(0) > 0) {
                //Tile can take fluid
                return new Object[] {entry.getKey(), entry.getValue()}; // position, facing
            }
        }

        // found nothing
        return null;
    }

    @Override
    public Component getDisplayName() {
        return Component.translatable(ModContent.CREATOR_BLOCK.get().getDescriptionId());
    }

    @Nullable
    @Override
    public AbstractContainerMenu createMenu(int windowID, Inventory playerInventory, Player playerEntity) {
        return new CreatorMenu(windowID, level, worldPosition, playerInventory, playerEntity);

    }
}
Leave a Comment