Lots more moved

This commit is contained in:
Sebastian Hartte
2020-07-04 21:03:30 +02:00
parent 5982f094ec
commit 1478e4c378
444 changed files with 4693 additions and 5235 deletions
@@ -0,0 +1,103 @@
package appeng.fluids.container;
import java.math.RoundingMode;
import java.util.Collections;
import java.util.Map;
import alexiil.mc.lib.attributes.Simulation;
import alexiil.mc.lib.attributes.fluid.FluidAttributes;
import alexiil.mc.lib.attributes.fluid.amount.FluidAmount;
import alexiil.mc.lib.attributes.fluid.volume.FluidVolume;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.screen.ScreenHandlerType;
import net.minecraft.screen.ScreenHandlerListener;
import net.minecraft.item.ItemStack;
import appeng.api.config.Upgrades;
import appeng.api.implementations.IUpgradeableHost;
import appeng.api.storage.data.IAEFluidStack;
import appeng.container.implementations.UpgradeableContainer;
import appeng.fluids.helper.FluidSyncHelper;
import appeng.fluids.util.AEFluidStack;
import appeng.fluids.util.IAEFluidTank;
import appeng.util.Platform;
public abstract class FluidConfigurableContainer extends UpgradeableContainer implements IFluidSyncContainer {
private FluidSyncHelper sync = null;
public FluidConfigurableContainer(ScreenHandlerType<?> containerType, int id, PlayerInventory ip, IUpgradeableHost te) {
super(containerType, id, ip, te);
}
public abstract IAEFluidTank getFluidConfigInventory();
private FluidSyncHelper getSyncHelper() {
if (this.sync == null) {
this.sync = new FluidSyncHelper(this.getFluidConfigInventory(), 0);
}
return this.sync;
}
@Override
protected ItemStack transferStackToContainer(ItemStack input) {
FluidVolume fluid = FluidAttributes.EXTRACTABLE.get(input)
.attemptAnyExtraction(FluidAmount.MAX_VALUE, Simulation.ACTION);
if (!fluid.isEmpty()) {
final IAEFluidTank t = this.getFluidConfigInventory();
final IAEFluidStack stack = AEFluidStack.fromFluidVolume(fluid, RoundingMode.DOWN);
for (int i = 0; i < t.getSlots(); ++i) {
if (t.getFluidInSlot(i) == null && this.isValidForConfig(i, stack)) {
t.setFluidInSlot(i, stack);
break;
}
}
}
return input;
}
protected boolean isValidForConfig(int slot, IAEFluidStack fs) {
if (this.supportCapacity()) {
// assumes 4 slots per upgrade
final int upgrades = this.getUpgradeable().getInstalledUpgrades(Upgrades.CAPACITY);
if (slot > 0 && upgrades < 1) {
return false;
}
if (slot > 4 && upgrades < 2) {
return false;
}
}
return true;
}
@Override
protected void standardDetectAndSendChanges() {
if (Platform.isServer()) {
this.getSyncHelper().sendDiff(this.getListeners());
// clear out config items that are no longer valid (eg capacity upgrade removed)
final IAEFluidTank t = this.getFluidConfigInventory();
for (int i = 0; i < t.getSlots(); ++i) {
if (t.getFluidInSlot(i) != null && !this.isValidForConfig(i, t.getFluidInSlot(i))) {
t.setFluidInSlot(i, null);
}
}
}
super.standardDetectAndSendChanges();
}
@Override
public void addListener(ScreenHandlerListener listener) {
super.addListener(listener);
this.getSyncHelper().sendFull(Collections.singleton(listener));
}
@Override
public void receiveFluidSlots(Map<Integer, IAEFluidStack> fluids) {
this.getSyncHelper().readPacket(fluids);
}
}
@@ -0,0 +1,104 @@
package appeng.fluids.container;
import alexiil.mc.lib.attributes.item.FixedItemInv;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.screen.ScreenHandlerType;
import net.minecraft.network.PacketByteBuf;
import appeng.api.config.SecurityPermissions;
import appeng.api.config.Upgrades;
import appeng.api.storage.data.IAEFluidStack;
import appeng.container.ContainerLocator;
import appeng.container.implementations.ContainerHelper;
import appeng.container.slot.RestrictedInputSlot;
import appeng.fluids.parts.FluidFormationPlanePart;
import appeng.fluids.util.IAEFluidTank;
public class FluidFormationPlaneContainer extends FluidConfigurableContainer {
public static ScreenHandlerType<FluidFormationPlaneContainer> TYPE;
private static final ContainerHelper<FluidFormationPlaneContainer, FluidFormationPlanePart> helper = new ContainerHelper<>(
FluidFormationPlaneContainer::new, FluidFormationPlanePart.class, SecurityPermissions.BUILD);
public static FluidFormationPlaneContainer fromNetwork(int windowId, PlayerInventory inv, PacketByteBuf buf) {
return helper.fromNetwork(windowId, inv, buf);
}
public static boolean open(PlayerEntity player, ContainerLocator locator) {
return helper.open(player, locator);
}
private final FluidFormationPlanePart plane;
public FluidFormationPlaneContainer(int id, final PlayerInventory ip, final FluidFormationPlanePart te) {
super(TYPE, id, ip, te);
this.plane = te;
}
@Override
protected int getHeight() {
return 251;
}
@Override
public IAEFluidTank getFluidConfigInventory() {
return this.plane.getConfig();
}
@Override
protected void setupConfig() {
final FixedItemInv upgrades = this.getUpgradeable().getInventoryByName("upgrades");
this.addSlot((new RestrictedInputSlot(RestrictedInputSlot.PlacableItemType.UPGRADES, upgrades, 0, 187, 8,
this.getPlayerInventory())).setNotDraggable());
this.addSlot((new RestrictedInputSlot(RestrictedInputSlot.PlacableItemType.UPGRADES, upgrades, 1, 187, 8 + 18,
this.getPlayerInventory())).setNotDraggable());
this.addSlot((new RestrictedInputSlot(RestrictedInputSlot.PlacableItemType.UPGRADES, upgrades, 2, 187,
8 + 18 * 2, this.getPlayerInventory())).setNotDraggable());
this.addSlot((new RestrictedInputSlot(RestrictedInputSlot.PlacableItemType.UPGRADES, upgrades, 3, 187,
8 + 18 * 3, this.getPlayerInventory())).setNotDraggable());
this.addSlot((new RestrictedInputSlot(RestrictedInputSlot.PlacableItemType.UPGRADES, upgrades, 4, 187,
8 + 18 * 4, this.getPlayerInventory())).setNotDraggable());
}
@Override
public void sendContentUpdates() {
this.verifyPermissions(SecurityPermissions.BUILD, false);
this.checkToolbox();
this.standardDetectAndSendChanges();
}
@Override
protected boolean isValidForConfig(int slot, IAEFluidStack fs) {
if (this.supportCapacity()) {
final int upgrades = this.getUpgradeable().getInstalledUpgrades(Upgrades.CAPACITY);
final int y = slot / 9;
if (y >= upgrades + 2) {
return false;
}
}
return true;
}
@Override
public boolean isSlotEnabled(final int idx) {
final int upgrades = this.getUpgradeable().getInstalledUpgrades(Upgrades.CAPACITY);
return upgrades > idx;
}
@Override
protected boolean supportCapacity() {
return true;
}
@Override
public int availableUpgrades() {
return 5;
}
}
@@ -0,0 +1,68 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2018, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.fluids.container;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.screen.ScreenHandlerType;
import net.minecraft.network.PacketByteBuf;
import appeng.api.config.SecurityPermissions;
import appeng.container.ContainerLocator;
import appeng.container.implementations.ContainerHelper;
import appeng.fluids.parts.SharedFluidBusPart;
import appeng.fluids.util.IAEFluidTank;
/**
* @author BrockWS
* @version rv5 - 1/05/2018
* @since rv5 1/05/2018
*/
public class FluidIOContainer extends FluidConfigurableContainer {
public static ScreenHandlerType<FluidIOContainer> TYPE;
private static final ContainerHelper<FluidIOContainer, SharedFluidBusPart> helper = new ContainerHelper<>(
FluidIOContainer::new, SharedFluidBusPart.class, SecurityPermissions.BUILD);
public static FluidIOContainer fromNetwork(int windowId, PlayerInventory inv, PacketByteBuf buf) {
return helper.fromNetwork(windowId, inv, buf);
}
public static boolean open(PlayerEntity player, ContainerLocator locator) {
return helper.open(player, locator);
}
private final SharedFluidBusPart bus;
public FluidIOContainer(int id, PlayerInventory ip, SharedFluidBusPart te) {
super(TYPE, id, ip, te);
this.bus = te;
}
@Override
public IAEFluidTank getFluidConfigInventory() {
return this.bus.getConfig();
}
@Override
protected void setupConfig() {
this.setupUpgrades();
}
}
@@ -0,0 +1,125 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2018, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.fluids.container;
import java.util.Collections;
import java.util.Map;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.screen.ScreenHandlerListener;
import net.minecraft.screen.ScreenHandlerType;
import net.minecraft.network.PacketByteBuf;
import appeng.api.config.SecurityPermissions;
import appeng.api.storage.data.IAEFluidStack;
import appeng.api.util.IConfigManager;
import appeng.container.ContainerLocator;
import appeng.container.implementations.ContainerHelper;
import appeng.fluids.helper.DualityFluidInterface;
import appeng.fluids.helper.FluidSyncHelper;
import appeng.fluids.helper.IFluidInterfaceHost;
import appeng.fluids.util.IAEFluidTank;
import appeng.util.Platform;
public class FluidInterfaceContainer extends FluidConfigurableContainer {
public static ScreenHandlerType<FluidInterfaceContainer> TYPE;
private static final ContainerHelper<FluidInterfaceContainer, IFluidInterfaceHost> helper = new ContainerHelper<>(
FluidInterfaceContainer::new, IFluidInterfaceHost.class, SecurityPermissions.BUILD);
public static FluidInterfaceContainer fromNetwork(int windowId, PlayerInventory inv, PacketByteBuf buf) {
return helper.fromNetwork(windowId, inv, buf);
}
public static boolean open(PlayerEntity player, ContainerLocator locator) {
return helper.open(player, locator);
}
private final DualityFluidInterface myDuality;
private final FluidSyncHelper tankSync;
public FluidInterfaceContainer(int id, final PlayerInventory ip, final IFluidInterfaceHost te) {
super(TYPE, id, ip, te.getDualityFluidInterface().getHost());
this.myDuality = te.getDualityFluidInterface();
this.tankSync = new FluidSyncHelper(this.myDuality.getTanks(), DualityFluidInterface.NUMBER_OF_TANKS);
}
@Override
protected int getHeight() {
return 231;
}
public IAEFluidTank getTanks() {
return myDuality.getTanks();
}
@Override
public IAEFluidTank getFluidConfigInventory() {
return this.myDuality.getConfig();
}
@Override
public void sendContentUpdates() {
this.verifyPermissions(SecurityPermissions.BUILD, false);
if (Platform.isServer()) {
this.tankSync.sendDiff(this.getListeners());
}
super.sendContentUpdates();
}
@Override
protected void setupConfig() {
}
@Override
protected void loadSettingsFromHost(final IConfigManager cm) {
}
@Override
public void addListener(ScreenHandlerListener listener) {
super.addListener(listener);
this.tankSync.sendFull(Collections.singleton(listener));
}
@Override
public void receiveFluidSlots(Map<Integer, IAEFluidStack> fluids) {
super.receiveFluidSlots(fluids);
this.tankSync.readPacket(fluids);
}
@Override
protected boolean supportCapacity() {
return false;
}
@Override
public int availableUpgrades() {
return 0;
}
@Override
public boolean hasToolbox() {
return false;
}
}
@@ -0,0 +1,99 @@
package appeng.fluids.container;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.screen.ScreenHandlerType;
import net.minecraft.network.PacketByteBuf;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import appeng.api.config.RedstoneMode;
import appeng.api.config.SecurityPermissions;
import appeng.api.config.Settings;
import appeng.container.ContainerLocator;
import appeng.container.guisync.GuiSync;
import appeng.container.implementations.ContainerHelper;
import appeng.fluids.parts.FluidLevelEmitterPart;
import appeng.fluids.util.IAEFluidTank;
import appeng.util.Platform;
public class FluidLevelEmitterContainer extends FluidConfigurableContainer {
public static ScreenHandlerType<FluidLevelEmitterContainer> TYPE;
private static final ContainerHelper<FluidLevelEmitterContainer, FluidLevelEmitterPart> helper = new ContainerHelper<>(
FluidLevelEmitterContainer::new, FluidLevelEmitterPart.class, SecurityPermissions.BUILD);
public static FluidLevelEmitterContainer fromNetwork(int windowId, PlayerInventory inv, PacketByteBuf buf) {
return helper.fromNetwork(windowId, inv, buf);
}
public static boolean open(PlayerEntity player, ContainerLocator locator) {
return helper.open(player, locator);
}
private final FluidLevelEmitterPart lvlEmitter;
@Environment(EnvType.CLIENT)
private TextFieldWidget textField;
@GuiSync(3)
public long EmitterValue = -1;
public FluidLevelEmitterContainer(int id, final PlayerInventory ip, final FluidLevelEmitterPart te) {
super(TYPE, id, ip, te);
this.lvlEmitter = te;
}
@Environment(EnvType.CLIENT)
public void setTextField(final TextFieldWidget level) {
this.textField = level;
this.textField.setText(String.valueOf(this.EmitterValue));
}
public void setLevel(final long l, final PlayerEntity player) {
this.lvlEmitter.setReportingValue(l);
this.EmitterValue = l;
}
@Override
protected void setupConfig() {
}
@Override
protected boolean supportCapacity() {
return false;
}
@Override
public int availableUpgrades() {
return 0;
}
@Override
public void sendContentUpdates() {
this.verifyPermissions(SecurityPermissions.BUILD, false);
if (Platform.isServer()) {
this.EmitterValue = this.lvlEmitter.getReportingValue();
this.setRedStoneMode(
(RedstoneMode) this.getUpgradeable().getConfigManager().getSetting(Settings.REDSTONE_EMITTER));
}
this.standardDetectAndSendChanges();
}
@Override
public void onUpdate(final String field, final Object oldValue, final Object newValue) {
if (field.equals("EmitterValue")) {
if (this.textField != null) {
this.textField.setText(String.valueOf(this.EmitterValue));
}
}
}
@Override
public IAEFluidTank getFluidConfigInventory() {
return this.lvlEmitter.getConfig();
}
}
@@ -0,0 +1,199 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2018, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.fluids.container;
import java.util.Iterator;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.screen.ScreenHandlerType;
import net.minecraft.network.PacketByteBuf;
import alexiil.mc.lib.attributes.item.FixedItemInv;
import appeng.api.AEApi;
import appeng.api.config.AccessRestriction;
import appeng.api.config.FuzzyMode;
import appeng.api.config.SecurityPermissions;
import appeng.api.config.Settings;
import appeng.api.config.StorageFilter;
import appeng.api.config.Upgrades;
import appeng.api.storage.IMEInventory;
import appeng.api.storage.channels.IFluidStorageChannel;
import appeng.api.storage.data.IAEFluidStack;
import appeng.api.storage.data.IItemList;
import appeng.container.ContainerLocator;
import appeng.container.guisync.GuiSync;
import appeng.container.implementations.ContainerHelper;
import appeng.container.slot.RestrictedInputSlot;
import appeng.fluids.parts.FluidStorageBusPart;
import appeng.fluids.util.IAEFluidTank;
import appeng.util.Platform;
import appeng.util.iterators.NullIterator;
/**
* @author BrockWS
* @version rv6 - 22/05/2018
* @since rv6 22/05/2018
*/
public class FluidStorageBusContainer extends FluidConfigurableContainer {
public static ScreenHandlerType<FluidStorageBusContainer> TYPE;
private static final ContainerHelper<FluidStorageBusContainer, FluidStorageBusPart> helper = new ContainerHelper<>(
FluidStorageBusContainer::new, FluidStorageBusPart.class);
public static FluidStorageBusContainer fromNetwork(int windowId, PlayerInventory inv, PacketByteBuf buf) {
return helper.fromNetwork(windowId, inv, buf);
}
public static boolean open(PlayerEntity player, ContainerLocator locator) {
return helper.open(player, locator);
}
private final FluidStorageBusPart storageBus;
@GuiSync(3)
public AccessRestriction rwMode = AccessRestriction.READ_WRITE;
@GuiSync(4)
public StorageFilter storageFilter = StorageFilter.EXTRACTABLE_ONLY;
public FluidStorageBusContainer(int id, PlayerInventory ip, FluidStorageBusPart te) {
super(TYPE, id, ip, te);
this.storageBus = te;
}
@Override
protected int getHeight() {
return 251;
}
@Override
protected void setupConfig() {
final FixedItemInv upgrades = this.getUpgradeable().getInventoryByName("upgrades");
this.addSlot((new RestrictedInputSlot(RestrictedInputSlot.PlacableItemType.UPGRADES, upgrades, 0, 187, 8,
this.getPlayerInventory())).setNotDraggable());
this.addSlot((new RestrictedInputSlot(RestrictedInputSlot.PlacableItemType.UPGRADES, upgrades, 1, 187, 8 + 18,
this.getPlayerInventory())).setNotDraggable());
this.addSlot((new RestrictedInputSlot(RestrictedInputSlot.PlacableItemType.UPGRADES, upgrades, 2, 187,
8 + 18 * 2, this.getPlayerInventory())).setNotDraggable());
this.addSlot((new RestrictedInputSlot(RestrictedInputSlot.PlacableItemType.UPGRADES, upgrades, 3, 187,
8 + 18 * 3, this.getPlayerInventory())).setNotDraggable());
this.addSlot((new RestrictedInputSlot(RestrictedInputSlot.PlacableItemType.UPGRADES, upgrades, 4, 187,
8 + 18 * 4, this.getPlayerInventory())).setNotDraggable());
}
@Override
protected boolean isValidForConfig(int slot, IAEFluidStack fs) {
if (this.supportCapacity()) {
final int upgrades = this.getUpgradeable().getInstalledUpgrades(Upgrades.CAPACITY);
final int y = slot / 9;
if (y >= upgrades + 2) {
return false;
}
}
return true;
}
@Override
protected boolean supportCapacity() {
return true;
}
@Override
public int availableUpgrades() {
return 5;
}
@Override
public void sendContentUpdates() {
this.verifyPermissions(SecurityPermissions.BUILD, false);
if (Platform.isServer()) {
this.setFuzzyMode((FuzzyMode) this.getUpgradeable().getConfigManager().getSetting(Settings.FUZZY_MODE));
this.setReadWriteMode(
(AccessRestriction) this.getUpgradeable().getConfigManager().getSetting(Settings.ACCESS));
this.setStorageFilter(
(StorageFilter) this.getUpgradeable().getConfigManager().getSetting(Settings.STORAGE_FILTER));
}
this.standardDetectAndSendChanges();
}
@Override
public boolean isSlotEnabled(final int idx) {
final int upgrades = this.getUpgradeable().getInstalledUpgrades(Upgrades.CAPACITY);
return upgrades > idx;
}
public void clear() {
IAEFluidTank h = this.storageBus.getConfig();
for (int i = 0; i < h.getSlots(); ++i) {
h.setFluidInSlot(i, null);
}
this.sendContentUpdates();
}
public void partition() {
IAEFluidTank h = this.storageBus.getConfig();
final IMEInventory<IAEFluidStack> cellInv = this.storageBus.getInternalHandler();
Iterator<IAEFluidStack> i = new NullIterator<>();
if (cellInv != null) {
final IItemList<IAEFluidStack> list = cellInv.getAvailableItems(
AEApi.instance().storage().getStorageChannel(IFluidStorageChannel.class).createList());
i = list.iterator();
}
for (int x = 0; x < h.getSlots(); x++) {
if (i.hasNext() && this.isSlotEnabled((x / 9) - 2)) {
h.setFluidInSlot(x, i.next());
} else {
h.setFluidInSlot(x, null);
}
}
this.sendContentUpdates();
}
public AccessRestriction getReadWriteMode() {
return this.rwMode;
}
private void setReadWriteMode(final AccessRestriction rwMode) {
this.rwMode = rwMode;
}
public StorageFilter getStorageFilter() {
return this.storageFilter;
}
private void setStorageFilter(final StorageFilter storageFilter) {
this.storageFilter = storageFilter;
}
@Override
public IAEFluidTank getFluidConfigInventory() {
return this.storageBus.getConfig();
}
}
@@ -0,0 +1,449 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2018, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.fluids.container;
import java.io.IOException;
import java.math.RoundingMode;
import java.nio.BufferOverflowException;
import javax.annotation.Nonnull;
import alexiil.mc.lib.attributes.Simulation;
import alexiil.mc.lib.attributes.fluid.FluidAttributes;
import alexiil.mc.lib.attributes.fluid.FluidExtractable;
import alexiil.mc.lib.attributes.fluid.FluidInsertable;
import alexiil.mc.lib.attributes.fluid.amount.FluidAmount;
import alexiil.mc.lib.attributes.fluid.filter.ExactFluidFilter;
import alexiil.mc.lib.attributes.fluid.volume.FluidVolume;
import alexiil.mc.lib.attributes.misc.Ref;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.screen.ScreenHandlerListener;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.screen.ScreenHandlerType;
import net.minecraft.item.ItemStack;
import net.minecraft.network.PacketByteBuf;
import appeng.api.AEApi;
import appeng.api.config.Actionable;
import appeng.api.config.PowerMultiplier;
import appeng.api.config.SecurityPermissions;
import appeng.api.config.Settings;
import appeng.api.config.SortDir;
import appeng.api.config.SortOrder;
import appeng.api.config.ViewItems;
import appeng.api.networking.IGrid;
import appeng.api.networking.IGridHost;
import appeng.api.networking.IGridNode;
import appeng.api.networking.energy.IEnergyGrid;
import appeng.api.networking.energy.IEnergySource;
import appeng.api.networking.security.IActionHost;
import appeng.api.networking.security.IActionSource;
import appeng.api.networking.storage.IBaseMonitor;
import appeng.api.storage.IMEMonitor;
import appeng.api.storage.IMEMonitorHandlerReceiver;
import appeng.api.storage.ITerminalHost;
import appeng.api.storage.channels.IFluidStorageChannel;
import appeng.api.storage.data.IAEFluidStack;
import appeng.api.storage.data.IItemList;
import appeng.api.util.AEPartLocation;
import appeng.api.util.IConfigManager;
import appeng.api.util.IConfigurableObject;
import appeng.container.AEBaseContainer;
import appeng.container.ContainerLocator;
import appeng.container.guisync.GuiSync;
import appeng.container.implementations.ContainerHelper;
import appeng.core.AELog;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.ConfigValuePacket;
import appeng.core.sync.packets.MEFluidInventoryUpdatePacket;
import appeng.core.sync.packets.TargetFluidStackPacket;
import appeng.fluids.util.AEFluidStack;
import appeng.helpers.InventoryAction;
import appeng.me.helpers.ChannelPowerSrc;
import appeng.util.ConfigManager;
import appeng.util.IConfigManagerHost;
import appeng.util.Platform;
/**
* @author BrockWS
* @version rv6 - 12/05/2018
* @since rv6 12/05/2018
*/
public class FluidTerminalContainer extends AEBaseContainer
implements IConfigManagerHost, IConfigurableObject, IMEMonitorHandlerReceiver<IAEFluidStack> {
public static ScreenHandlerType<FluidTerminalContainer> TYPE;
private static final ContainerHelper<FluidTerminalContainer, ITerminalHost> helper = new ContainerHelper<>(
FluidTerminalContainer::new, ITerminalHost.class, SecurityPermissions.BUILD);
public static FluidTerminalContainer fromNetwork(int windowId, PlayerInventory inv, PacketByteBuf buf) {
return helper.fromNetwork(windowId, inv, buf);
}
public static boolean open(PlayerEntity player, ContainerLocator locator) {
return helper.open(player, locator);
}
private final IConfigManager clientCM;
private final IMEMonitor<IAEFluidStack> monitor;
private final IItemList<IAEFluidStack> fluids = AEApi.instance().storage()
.getStorageChannel(IFluidStorageChannel.class).createList();
@GuiSync(99)
public boolean hasPower = false;
private ITerminalHost terminal;
private IConfigManager serverCM;
private IConfigManagerHost gui;
private IGridNode networkNode;
// Holds the fluid the client wishes to extract, or null for insert
private IAEFluidStack clientRequestedTargetFluid = null;
public FluidTerminalContainer(int id, PlayerInventory ip, ITerminalHost terminal) {
super(TYPE, id, ip, terminal);
this.terminal = terminal;
this.clientCM = new ConfigManager(this);
this.clientCM.registerSetting(Settings.SORT_BY, SortOrder.NAME);
this.clientCM.registerSetting(Settings.SORT_DIRECTION, SortDir.ASCENDING);
this.clientCM.registerSetting(Settings.VIEW_MODE, ViewItems.ALL);
if (Platform.isServer()) {
this.serverCM = terminal.getConfigManager();
this.monitor = terminal
.getInventory(AEApi.instance().storage().getStorageChannel(IFluidStorageChannel.class));
if (this.monitor != null) {
this.monitor.addListener(this, null);
if (terminal instanceof IEnergySource) {
this.setPowerSource((IEnergySource) terminal);
} else if (terminal instanceof IGridHost || terminal instanceof IActionHost) {
final IGridNode node;
if (terminal instanceof IGridHost) {
node = ((IGridHost) terminal).getGridNode(AEPartLocation.INTERNAL);
} else if (terminal instanceof IActionHost) {
node = ((IActionHost) terminal).getActionableNode();
} else {
node = null;
}
if (node != null) {
this.networkNode = node;
final IGrid g = node.getGrid();
if (g != null) {
this.setPowerSource(new ChannelPowerSrc(this.networkNode,
(IEnergySource) g.getCache(IEnergyGrid.class)));
}
}
}
}
} else {
this.monitor = null;
}
this.bindPlayerInventory(ip, 0, 222 - 82);
}
@Override
public boolean isValid(Object verificationToken) {
return true;
}
@Override
public void postChange(IBaseMonitor<IAEFluidStack> monitor, Iterable<IAEFluidStack> change,
IActionSource actionSource) {
for (final IAEFluidStack is : change) {
this.fluids.add(is);
}
}
@Override
public void onListUpdate() {
for (final ScreenHandlerListener c : this.getListeners()) {
this.queueInventory(c);
}
}
@Override
public void addListener(ScreenHandlerListener listener) {
super.addListener(listener);
this.queueInventory(listener);
}
@Override
public void close(final PlayerEntity player) {
super.close(player);
if (this.monitor != null) {
this.monitor.removeListener(this);
}
}
private void queueInventory(final ScreenHandlerListener c) {
if (Platform.isServer() && c instanceof PlayerEntity && this.monitor != null) {
try {
MEFluidInventoryUpdatePacket piu = new MEFluidInventoryUpdatePacket();
final IItemList<IAEFluidStack> monitorCache = this.monitor.getStorageList();
for (final IAEFluidStack send : monitorCache) {
try {
piu.appendFluid(send);
} catch (final BufferOverflowException boe) {
NetworkHandler.instance().sendTo(piu, (ServerPlayerEntity) c);
piu = new MEFluidInventoryUpdatePacket();
piu.appendFluid(send);
}
}
NetworkHandler.instance().sendTo(piu, (ServerPlayerEntity) c);
} catch (final IOException e) {
AELog.debug(e);
}
}
}
@Override
public IConfigManager getConfigManager() {
if (Platform.isServer()) {
return this.serverCM;
}
return this.clientCM;
}
public void setTargetStack(final IAEFluidStack stack) {
if (Platform.isClient()) {
if (stack == null && this.clientRequestedTargetFluid == null) {
return;
}
if (stack != null && this.clientRequestedTargetFluid != null
&& FluidVolume.areEqualExceptAmounts(stack.getFluidStack(), this.clientRequestedTargetFluid.getFluidStack())) {
return;
}
NetworkHandler.instance().sendToServer(new TargetFluidStackPacket((AEFluidStack) stack));
}
this.clientRequestedTargetFluid = stack == null ? null : stack.copy();
}
@Override
public void updateSetting(IConfigManager manager, Settings settingName, Enum<?> newValue) {
if (this.getGui() != null) {
this.getGui().updateSetting(manager, settingName, newValue);
}
}
@Override
public void sendContentUpdates() {
if (Platform.isServer()) {
if (this.monitor != this.terminal
.getInventory(AEApi.instance().storage().getStorageChannel(IFluidStorageChannel.class))) {
this.setValidContainer(false);
}
for (final Settings set : this.serverCM.getSettings()) {
final Enum<?> sideLocal = this.serverCM.getSetting(set);
final Enum<?> sideRemote = this.clientCM.getSetting(set);
if (sideLocal != sideRemote) {
this.clientCM.putSetting(set, sideLocal);
for (final ScreenHandlerListener crafter : this.getListeners()) {
if (crafter instanceof ServerPlayerEntity) {
NetworkHandler.instance().sendTo(new ConfigValuePacket(set.name(), sideLocal.name()),
(ServerPlayerEntity) crafter);
}
}
}
}
if (!this.fluids.isEmpty()) {
try {
final IItemList<IAEFluidStack> monitorCache = this.monitor.getStorageList();
final MEFluidInventoryUpdatePacket piu = new MEFluidInventoryUpdatePacket();
for (final IAEFluidStack is : this.fluids) {
final IAEFluidStack send = monitorCache.findPrecise(is);
if (send == null) {
is.setStackSize(0);
piu.appendFluid(is);
} else {
piu.appendFluid(send);
}
}
if (!piu.isEmpty()) {
this.fluids.resetStatus();
for (final Object c : this.getListeners()) {
if (c instanceof PlayerEntity) {
NetworkHandler.instance().sendTo(piu, (ServerPlayerEntity) c);
}
}
}
} catch (final IOException e) {
AELog.debug(e);
}
}
this.updatePowerStatus();
super.sendContentUpdates();
}
}
@Override
public void doAction(ServerPlayerEntity player, InventoryAction action, int slot, long id) {
if (action != InventoryAction.FILL_ITEM && action != InventoryAction.EMPTY_ITEM) {
super.doAction(player, action, slot, id);
return;
}
final ItemStack held = player.inventory.getCursorStack();
if (held.getCount() != 1) {
// only support stacksize 1 for now
return;
}
if (action == InventoryAction.FILL_ITEM && this.clientRequestedTargetFluid != null) {
Ref<ItemStack> container = new Ref<>(held);
FluidInsertable insertable = FluidAttributes.INSERTABLE.getFirstOrNull(container);
if (insertable == null) {
return; // Not a fillable item.
}
// Check how much we can store in the item
FluidVolume volumeAllowed = insertable.attemptInsertion(this.clientRequestedTargetFluid.getFluidStack().withAmount(FluidAmount.MAX_VALUE), Simulation.SIMULATE);
final IAEFluidStack stack = AEFluidStack.fromFluidVolume(this.clientRequestedTargetFluid.getFluidStack().withAmount(volumeAllowed.amount()), RoundingMode.DOWN);
if (stack == null) {
return; // Might be nothing allowed...
}
// Check if we can pull out of the system
final IAEFluidStack canPull = Platform.poweredExtraction(this.getPowerSource(), this.monitor, stack,
this.getActionSource(), Actionable.SIMULATE);
if (canPull == null || canPull.getStackSize() < 1) {
return;
}
// How much could fit into the container
volumeAllowed = insertable.attemptInsertion(canPull.getFluidStack(), Simulation.SIMULATE);
if (volumeAllowed.isEmpty()) {
return;
}
// Now actually pull out of the system
stack.setStackSize(volumeAllowed.amount().asLong(1000, RoundingMode.DOWN));
final IAEFluidStack pulled = Platform.poweredExtraction(this.getPowerSource(), this.monitor, stack,
this.getActionSource());
if (pulled == null || pulled.getStackSize() < 1) {
// Something went wrong
AELog.error("Unable to pull fluid out of the ME system even though the simulation said yes ");
return;
}
// Actually fill
final FluidVolume reallyFilled = insertable.attemptInsertion(pulled.getFluidStack(), Simulation.ACTION);
if (!reallyFilled.amount().equals(volumeAllowed.amount())) {
AELog.error("Fluid item [%s] reported a different possible amount than it actually accepted.",
held.getName());
}
player.inventory.setCursorStack(container.get());
this.updateHeld(player);
} else if (action == InventoryAction.EMPTY_ITEM) {
Ref<ItemStack> container = new Ref<>(held);
FluidExtractable extractable = FluidAttributes.EXTRACTABLE.getFirstOrNull(container);
if (extractable == null) {
return; // Not a drainable item.
}
// See how much we can drain from the item
FluidVolume extract = extractable.attemptAnyExtraction(FluidAmount.MAX_VALUE, Simulation.SIMULATE);
AEFluidStack aeStack = AEFluidStack.fromFluidVolume(extract, RoundingMode.DOWN);
if (aeStack == null || aeStack.getStackSize() == 0) {
return; // Not enough liquid in the container
}
// Check if we can push into the system
final IAEFluidStack notStorable = Platform.poweredInsert(this.getPowerSource(), this.monitor,
aeStack, this.getActionSource(), Actionable.SIMULATE);
// Adjust the amount if needed
if (notStorable != null && notStorable.getStackSize() > 0) {
final FluidAmount toStore = aeStack.getAmount().sub(notStorable.getAmount());
extract = extractable.attemptExtraction(new ExactFluidFilter(aeStack.getFluid()), toStore, Simulation.SIMULATE);
if (extract.isEmpty()) {
return;
}
}
// Actually drain
FluidVolume drained = extractable.extract(extract.getFluidKey(), extract.amount());
aeStack = AEFluidStack.fromFluidVolume(drained, RoundingMode.DOWN);
if (aeStack == null) {
// TODO WARN
return; // I guess the extractable decided to return a different amount upon execution
}
final IAEFluidStack notInserted = Platform.poweredInsert(this.getPowerSource(), this.monitor,
aeStack, this.getActionSource());
if (notInserted != null && notInserted.getStackSize() > 0) {
AELog.error("Fluid item [%s] reported a different possible amount to drain than it actually provided.",
held.getName());
}
player.inventory.setCursorStack(container.get());
this.updateHeld(player);
}
}
protected void updatePowerStatus() {
try {
if (this.networkNode != null) {
this.setPowered(this.networkNode.isActive());
} else if (this.getPowerSource() instanceof IEnergyGrid) {
this.setPowered(((IEnergyGrid) this.getPowerSource()).isNetworkPowered());
} else {
this.setPowered(
this.getPowerSource().extractAEPower(1, Actionable.SIMULATE, PowerMultiplier.CONFIG) > 0.8);
}
} catch (final Exception ignore) {
// :P
}
}
private IConfigManagerHost getGui() {
return this.gui;
}
public void setGui(@Nonnull final IConfigManagerHost gui) {
this.gui = gui;
}
public boolean isPowered() {
return this.hasPower;
}
private void setPowered(final boolean isPowered) {
this.hasPower = isPowered;
}
}
@@ -0,0 +1,10 @@
package appeng.fluids.container;
import java.util.Map;
import appeng.api.storage.data.IAEFluidStack;
public interface IFluidSyncContainer {
void receiveFluidSlots(final Map<Integer, IAEFluidStack> fluids);
}
@@ -0,0 +1,34 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2018, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.fluids.container.slots;
import appeng.api.storage.data.IAEFluidStack;
/**
* @author yueh
* @version rv6
* @since rv6
*/
public interface IMEFluidSlot {
IAEFluidStack getAEFluidStack();
default boolean shouldRenderAsFluid() {
return true;
}
}