mirror of
https://github.com/GTNewHorizons/AE2FluidCraft-Rework.git
synced 2026-11-12 00:07:29 +00:00
Merge fe1ec6276d into b1dff2ec2c
This commit is contained in:
22 files changed
+1108
-35
No files matched your search
@@ -1,7 +1,6 @@
|
||||
package com.glodblock.github;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.config.Upgrades;
|
||||
import com.glodblock.github.common.Config;
|
||||
import com.glodblock.github.common.storage.FluidCellHandler;
|
||||
import com.glodblock.github.crossmod.opencomputers.OCDriverInit;
|
||||
@@ -20,7 +19,6 @@ import cpw.mods.fml.common.event.FMLLoadCompleteEvent;
|
||||
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
|
||||
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
|
||||
import cpw.mods.fml.common.network.NetworkRegistry;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
@Mod(
|
||||
@@ -71,26 +69,6 @@ public class FluidCraft {
|
||||
if (!Config.removeRecipe) {
|
||||
(new RecipeLoader()).run();
|
||||
}
|
||||
|
||||
if (ModAndClassUtil.isBigInterface) {
|
||||
Upgrades.PATTERN_CAPACITY.registerItem(new ItemStack(ItemAndBlockHolder.FLUID_INTERFACE), 3);
|
||||
Upgrades.PATTERN_CAPACITY.registerItem(new ItemStack(ItemAndBlockHolder.INTERFACE), 3);
|
||||
}
|
||||
Upgrades.CRAFTING.registerItem(new ItemStack(ItemAndBlockHolder.FLUID_INTERFACE), 1);
|
||||
Upgrades.CRAFTING.registerItem(new ItemStack(ItemAndBlockHolder.INTERFACE), 1);
|
||||
|
||||
if (Config.fluidIOBus) {
|
||||
Upgrades.CAPACITY.registerItem(new ItemStack(ItemAndBlockHolder.FLUID_EXPORT_BUS), 2);
|
||||
Upgrades.CAPACITY.registerItem(new ItemStack(ItemAndBlockHolder.FLUID_IMPORT_BUS), 2);
|
||||
Upgrades.REDSTONE.registerItem(new ItemStack(ItemAndBlockHolder.FLUID_EXPORT_BUS), 1);
|
||||
Upgrades.REDSTONE.registerItem(new ItemStack(ItemAndBlockHolder.FLUID_IMPORT_BUS), 1);
|
||||
Upgrades.SPEED.registerItem(new ItemStack(ItemAndBlockHolder.FLUID_EXPORT_BUS), 4);
|
||||
Upgrades.SPEED.registerItem(new ItemStack(ItemAndBlockHolder.FLUID_IMPORT_BUS), 4);
|
||||
Upgrades.SUPERSPEED.registerItem(new ItemStack(ItemAndBlockHolder.FLUID_EXPORT_BUS), 4);
|
||||
Upgrades.SUPERSPEED.registerItem(new ItemStack(ItemAndBlockHolder.FLUID_IMPORT_BUS), 4);
|
||||
Upgrades.CRAFTING.registerItem(new ItemStack(ItemAndBlockHolder.FLUID_EXPORT_BUS), 1);
|
||||
}
|
||||
|
||||
try {
|
||||
Class<?> calculatorV2 = Class.forName("appeng.crafting.v2.CraftingCalculations");
|
||||
if (calculatorV2 != null) {
|
||||
|
||||
@@ -13,15 +13,17 @@ import appeng.core.sync.packets.PacketValueConfig;
|
||||
import appeng.helpers.IPriorityHost;
|
||||
import com.glodblock.github.FluidCraft;
|
||||
import com.glodblock.github.common.parts.PartFluidInterface;
|
||||
import com.glodblock.github.common.parts.PartFluidStorageBus;
|
||||
import com.glodblock.github.common.tile.TileFluidInterface;
|
||||
import com.glodblock.github.inventory.gui.GuiType;
|
||||
import com.glodblock.github.loader.ItemAndBlockHolder;
|
||||
import com.glodblock.github.network.CPacketSwitchGuis;
|
||||
import java.io.IOException;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class GuiFCPriority extends AEBaseGui {
|
||||
|
||||
private GuiNumberBox priority;
|
||||
@@ -71,6 +73,9 @@ public class GuiFCPriority extends AEBaseGui {
|
||||
} else if (target instanceof PartFluidInterface) {
|
||||
myIcon = ItemAndBlockHolder.FLUID_INTERFACE.stack();
|
||||
this.OriginalGui = GuiType.DUAL_INTERFACE_FLUID_PART;
|
||||
} else if (target instanceof PartFluidStorageBus) {
|
||||
myIcon = ItemAndBlockHolder.FLUID_STORAGE_BUS.stack();
|
||||
this.OriginalGui = GuiType.FLUID_STORAGE_BUS;
|
||||
}
|
||||
|
||||
if (this.OriginalGui != null && myIcon != null) {
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
package com.glodblock.github.client.gui;
|
||||
|
||||
import appeng.api.config.AccessRestriction;
|
||||
import appeng.api.config.ActionItems;
|
||||
import appeng.api.config.Settings;
|
||||
import appeng.api.config.StorageFilter;
|
||||
import appeng.api.storage.data.IAEFluidStack;
|
||||
import appeng.client.gui.implementations.GuiUpgradeable;
|
||||
import appeng.client.gui.widgets.GuiImgButton;
|
||||
import appeng.client.gui.widgets.GuiTabButton;
|
||||
import appeng.core.localization.GuiColors;
|
||||
import appeng.core.localization.GuiText;
|
||||
import appeng.core.sync.network.NetworkHandler;
|
||||
import appeng.core.sync.packets.PacketConfigButton;
|
||||
import com.glodblock.github.FluidCraft;
|
||||
import com.glodblock.github.client.gui.container.ContainerFluidStorageBus;
|
||||
import com.glodblock.github.common.parts.PartFluidStorageBus;
|
||||
import com.glodblock.github.inventory.gui.GuiType;
|
||||
import com.glodblock.github.network.CPacketFluidPatternTermBtns;
|
||||
import com.glodblock.github.network.CPacketSwitchGuis;
|
||||
import com.glodblock.github.util.NameConst;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
import org.lwjgl.input.Mouse;
|
||||
|
||||
public class GuiFluidStorageBus extends GuiUpgradeable {
|
||||
|
||||
private GuiImgButton rwMode;
|
||||
private GuiTabButton priority;
|
||||
private GuiImgButton partition;
|
||||
private GuiImgButton clear;
|
||||
|
||||
public GuiFluidStorageBus(InventoryPlayer inventoryPlayer, PartFluidStorageBus te) {
|
||||
super(new ContainerFluidStorageBus(inventoryPlayer, te));
|
||||
this.ySize = 251;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void addButtons() {
|
||||
this.clear = new GuiImgButton(this.guiLeft - 18, this.guiTop + 8, Settings.ACTIONS, ActionItems.CLOSE);
|
||||
this.partition = new GuiImgButton(this.guiLeft - 18, this.guiTop + 28, Settings.ACTIONS, ActionItems.WRENCH);
|
||||
this.rwMode =
|
||||
new GuiImgButton(this.guiLeft - 18, this.guiTop + 48, Settings.ACCESS, AccessRestriction.READ_WRITE);
|
||||
this.priority = new GuiTabButton(
|
||||
this.guiLeft + 154, this.guiTop, 2 + 4 * 16, GuiText.Priority.getLocal(), itemRender);
|
||||
|
||||
this.buttonList.add(this.priority);
|
||||
this.buttonList.add(this.rwMode);
|
||||
this.buttonList.add(this.partition);
|
||||
this.buttonList.add(this.clear);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawFG(final int offsetX, final int offsetY, final int mouseX, final int mouseY) {
|
||||
this.fontRendererObj.drawString(
|
||||
this.getGuiDisplayName(I18n.format(NameConst.GUI_FLUID_STORAGE_BUS)), 8, 6, GuiColors.StorageBusTitle.getColor());
|
||||
this.fontRendererObj.drawString(
|
||||
GuiText.inventory.getLocal(), 8, this.ySize - 96 + 3, GuiColors.StorageBusInventory.getColor());
|
||||
|
||||
if (this.rwMode != null) {
|
||||
this.rwMode.set(((ContainerFluidStorageBus) this.cvb).getReadWriteMode());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getBackground() {
|
||||
return "guis/storagebus.png";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void actionPerformed(final GuiButton btn) {
|
||||
super.actionPerformed(btn);
|
||||
final boolean backwards = Mouse.isButtonDown(1);
|
||||
if (btn == this.partition) {
|
||||
FluidCraft.proxy.netHandler.sendToServer(new CPacketFluidPatternTermBtns("StorageBus.Action", "Partition"));
|
||||
} else if (btn == this.clear) {
|
||||
FluidCraft.proxy.netHandler.sendToServer(new CPacketFluidPatternTermBtns("StorageBus.Action", "Clear"));
|
||||
} else if (btn == this.priority) {
|
||||
FluidCraft.proxy.netHandler.sendToServer(new CPacketSwitchGuis(GuiType.FLUID_STORAGE_BUS_PRIORITY));
|
||||
} else if (btn == this.rwMode) {
|
||||
NetworkHandler.instance.sendToServer(new PacketConfigButton(this.rwMode.getSetting(), backwards));
|
||||
}
|
||||
}
|
||||
|
||||
public void update(int id, IAEFluidStack stack) {
|
||||
((ContainerFluidStorageBus) this.cvb).bus.setFluidInSlot(id, stack);
|
||||
}
|
||||
|
||||
}
|
||||
+155
@@ -0,0 +1,155 @@
|
||||
package com.glodblock.github.client.gui.container;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.config.*;
|
||||
import appeng.api.storage.IMEInventory;
|
||||
import appeng.api.storage.data.IAEFluidStack;
|
||||
import appeng.api.storage.data.IItemList;
|
||||
import appeng.container.guisync.GuiSync;
|
||||
import appeng.container.slot.SlotRestrictedInput;
|
||||
import appeng.tile.inventory.AppEngInternalAEInventory;
|
||||
import appeng.util.Platform;
|
||||
import appeng.util.iterators.NullIterator;
|
||||
import com.glodblock.github.common.item.ItemFluidPacket;
|
||||
import com.glodblock.github.common.parts.PartFluidStorageBus;
|
||||
import com.glodblock.github.inventory.slot.OptionalFluidSlotFakeTypeOnly;
|
||||
import com.glodblock.github.util.Ae2Reflect;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
import net.minecraft.inventory.IInventory;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
public class ContainerFluidStorageBus extends ContainerFluidConfigurable {
|
||||
|
||||
public final PartFluidStorageBus bus;
|
||||
@GuiSync(3)
|
||||
public AccessRestriction rwMode = AccessRestriction.READ_WRITE;
|
||||
@GuiSync(4)
|
||||
public StorageFilter storageFilter = StorageFilter.EXTRACTABLE_ONLY;
|
||||
|
||||
public ContainerFluidStorageBus(InventoryPlayer ip, PartFluidStorageBus te) {
|
||||
super(ip, te);
|
||||
this.bus = te;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getHeight() {
|
||||
return 251;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setupConfig() {
|
||||
final int xo = 8;
|
||||
final int yo = 23 + 6;
|
||||
final IInventory upgrades = Ae2Reflect.getUpgradeList(this).getInventoryByName("upgrades");
|
||||
final IInventory config = Ae2Reflect.getUpgradeList(this).getInventoryByName("config");
|
||||
for (int y = 0; y < 7; y++) {
|
||||
for (int x = 0; x < 9; x++) {
|
||||
this.addSlotToContainer(new OptionalFluidSlotFakeTypeOnly(config, null, this, y * 9 + x, xo, yo, x, y, y));
|
||||
}
|
||||
}
|
||||
this.addSlotToContainer((new SlotRestrictedInput(SlotRestrictedInput.PlacableItemType.UPGRADES, upgrades, 0, 187, 8, this.getInventoryPlayer()))
|
||||
.setNotDraggable());
|
||||
this.addSlotToContainer(
|
||||
(new SlotRestrictedInput(SlotRestrictedInput.PlacableItemType.UPGRADES, upgrades, 1, 187, 8 + 18, this.getInventoryPlayer()))
|
||||
.setNotDraggable());
|
||||
this.addSlotToContainer(
|
||||
(new SlotRestrictedInput(SlotRestrictedInput.PlacableItemType.UPGRADES, upgrades, 2, 187, 8 + 18 * 2, this.getInventoryPlayer()))
|
||||
.setNotDraggable());
|
||||
this.addSlotToContainer(
|
||||
(new SlotRestrictedInput(SlotRestrictedInput.PlacableItemType.UPGRADES, upgrades, 3, 187, 8 + 18 * 3, this.getInventoryPlayer()))
|
||||
.setNotDraggable());
|
||||
this.addSlotToContainer(
|
||||
(new SlotRestrictedInput(SlotRestrictedInput.PlacableItemType.UPGRADES, upgrades, 4, 187, 8 + 18 * 4, this.getInventoryPlayer()))
|
||||
.setNotDraggable());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isValidForConfig(int slot, IAEFluidStack fs) {
|
||||
if (this.supportCapacity()) {
|
||||
final int upgrades = Ae2Reflect.getUpgradeList(this).getInstalledUpgrades(Upgrades.CAPACITY);
|
||||
final int y = slot / 9;
|
||||
return y < upgrades + 2;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportCapacity() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int availableUpgrades() {
|
||||
return 5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void detectAndSendChanges() {
|
||||
this.verifyPermissions(SecurityPermissions.BUILD, false);
|
||||
|
||||
if (Platform.isServer()) {
|
||||
this.setReadWriteMode((AccessRestriction) Ae2Reflect.getUpgradeList(this).getConfigManager().getSetting(Settings.ACCESS));
|
||||
this.setStorageFilter((StorageFilter) Ae2Reflect.getUpgradeList(this).getConfigManager().getSetting(Settings.STORAGE_FILTER));
|
||||
}
|
||||
|
||||
this.standardDetectAndSendChanges();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSlotEnabled(final int idx) {
|
||||
if (Ae2Reflect.getUpgradeList(this).getInstalledUpgrades(Upgrades.ORE_FILTER) > 0) return false;
|
||||
final int upgrades = Ae2Reflect.getUpgradeList(this).getInstalledUpgrades(Upgrades.CAPACITY);
|
||||
return upgrades > (idx - 2);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
AppEngInternalAEInventory h = this.bus.getConfig();
|
||||
for (int i = 0; i < h.getSizeInventory(); ++i) {
|
||||
h.setInventorySlotContents(i, null);
|
||||
}
|
||||
this.detectAndSendChanges();
|
||||
}
|
||||
|
||||
public void partition() {
|
||||
AppEngInternalAEInventory h = this.bus.getConfig();
|
||||
final IMEInventory<IAEFluidStack> cellInv = this.bus.getInternalHandler();
|
||||
Iterator<IAEFluidStack> i = new NullIterator<>();
|
||||
if (cellInv != null) {
|
||||
final IItemList<IAEFluidStack> list = cellInv
|
||||
.getAvailableItems(AEApi.instance().storage().createFluidList());
|
||||
i = list.iterator();
|
||||
}
|
||||
|
||||
for (int x = 0; x < h.getSizeInventory(); x++) {
|
||||
if (i.hasNext() && this.isSlotEnabled((x / 9) - 2)) {
|
||||
h.setInventorySlotContents(x, ItemFluidPacket.newStack(i.next()));
|
||||
} else {
|
||||
h.setInventorySlotContents(x, null);
|
||||
}
|
||||
}
|
||||
this.detectAndSendChanges();
|
||||
}
|
||||
|
||||
public AccessRestriction getReadWriteMode() {
|
||||
return this.rwMode;
|
||||
}
|
||||
|
||||
public StorageFilter getStorageFilter() {
|
||||
return this.storageFilter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AppEngInternalAEInventory getFakeFluidInv() {
|
||||
return (AppEngInternalAEInventory) this.bus.getInventoryByName("config");
|
||||
}
|
||||
|
||||
private void setReadWriteMode(final AccessRestriction rwMode) {
|
||||
this.rwMode = rwMode;
|
||||
}
|
||||
|
||||
private void setStorageFilter(final StorageFilter storageFilter) {
|
||||
this.storageFilter = storageFilter;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,6 +18,7 @@ public enum FCPartsTexture {
|
||||
PartTerminalBroad("terminal_broad"),
|
||||
PartFluidImportBus("fluid_import_face"),
|
||||
PartFluidExportBus("fluid_export_face"),
|
||||
PartFluidStorageBus("fluid_storage_bus"),
|
||||
BlockFluidInterfaceAlternate_Arrow("fluid_interface_arrow"),
|
||||
BlockInterfaceAlternate("fluid_interface_a"),
|
||||
BlockInterface_Face("fluid_interface"),
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.glodblock.github.common.item;
|
||||
|
||||
import appeng.api.storage.data.IAEFluidStack;
|
||||
import appeng.api.storage.data.IAEItemStack;
|
||||
import appeng.util.item.AEItemStack;
|
||||
import com.glodblock.github.FluidCraft;
|
||||
@@ -91,6 +92,13 @@ public class ItemFluidPacket extends Item {
|
||||
return stack;
|
||||
}
|
||||
|
||||
public static ItemStack newStack(@Nullable IAEFluidStack fluid) {
|
||||
if (fluid == null || fluid.getStackSize() == 0) {
|
||||
return null;
|
||||
}
|
||||
return newStack(fluid.getFluidStack());
|
||||
}
|
||||
|
||||
public static ItemStack newDisplayStack(@Nullable FluidStack fluid) {
|
||||
if (fluid == null) {
|
||||
return null;
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.glodblock.github.common.item;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.parts.IPartItem;
|
||||
import com.glodblock.github.FluidCraft;
|
||||
import com.glodblock.github.common.parts.PartFluidStorageBus;
|
||||
import com.glodblock.github.common.tabs.FluidCraftingTabs;
|
||||
import com.glodblock.github.util.NameConst;
|
||||
import cpw.mods.fml.common.registry.GameRegistry;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import net.minecraft.client.renderer.texture.IIconRegister;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class ItemPartFluidStorageBus extends Item implements IPartItem {
|
||||
|
||||
public ItemPartFluidStorageBus() {
|
||||
this.setMaxStackSize(64);
|
||||
this.setUnlocalizedName(NameConst.ITEM_PART_FLUID_STORAGE_BUS);
|
||||
AEApi.instance().partHelper().setItemBusRenderer(this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PartFluidStorageBus createPartFromItemStack(ItemStack is) {
|
||||
return new PartFluidStorageBus(is);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onItemUse(
|
||||
ItemStack stack,
|
||||
EntityPlayer player,
|
||||
World world,
|
||||
int x,
|
||||
int y,
|
||||
int z,
|
||||
int side,
|
||||
float xOffset,
|
||||
float yOffset,
|
||||
float zOffset) {
|
||||
return AEApi.instance().partHelper().placeBus(player.getHeldItem(), x, y, z, side, player, world);
|
||||
}
|
||||
|
||||
public ItemPartFluidStorageBus register() {
|
||||
GameRegistry.registerItem(this, NameConst.ITEM_PART_FLUID_STORAGE_BUS, FluidCraft.MODID);
|
||||
setCreativeTab(FluidCraftingTabs.INSTANCE);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerIcons(IIconRegister _iconRegister) {}
|
||||
|
||||
@Override
|
||||
@SideOnly(Side.CLIENT)
|
||||
public int getSpriteNumber() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public ItemStack stack(int size) {
|
||||
return new ItemStack(this, size);
|
||||
}
|
||||
|
||||
public ItemStack stack() {
|
||||
return new ItemStack(this, 1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,509 @@
|
||||
package com.glodblock.github.common.parts;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.config.*;
|
||||
import appeng.api.networking.IGridNode;
|
||||
import appeng.api.networking.events.MENetworkCellArrayUpdate;
|
||||
import appeng.api.networking.events.MENetworkChannelsChanged;
|
||||
import appeng.api.networking.events.MENetworkEventSubscribe;
|
||||
import appeng.api.networking.events.MENetworkPowerStatusChange;
|
||||
import appeng.api.networking.security.BaseActionSource;
|
||||
import appeng.api.networking.security.MachineSource;
|
||||
import appeng.api.networking.storage.IBaseMonitor;
|
||||
import appeng.api.networking.storage.IStorageGrid;
|
||||
import appeng.api.networking.ticking.IGridTickable;
|
||||
import appeng.api.networking.ticking.ITickManager;
|
||||
import appeng.api.networking.ticking.TickRateModulation;
|
||||
import appeng.api.networking.ticking.TickingRequest;
|
||||
import appeng.api.parts.IPart;
|
||||
import appeng.api.parts.IPartCollisionHelper;
|
||||
import appeng.api.parts.IPartRenderHelper;
|
||||
import appeng.api.storage.*;
|
||||
import appeng.api.storage.data.IAEFluidStack;
|
||||
import appeng.api.storage.data.IAEItemStack;
|
||||
import appeng.api.storage.data.IItemList;
|
||||
import appeng.api.util.IConfigManager;
|
||||
import appeng.client.texture.CableBusTextures;
|
||||
import appeng.core.settings.TickRates;
|
||||
import appeng.helpers.IPriorityHost;
|
||||
import appeng.me.GridAccessException;
|
||||
import appeng.me.cache.GridStorageCache;
|
||||
import appeng.me.storage.MEInventoryHandler;
|
||||
import appeng.parts.automation.PartUpgradeable;
|
||||
import appeng.tile.inventory.AppEngInternalAEInventory;
|
||||
import appeng.tile.inventory.InvOperation;
|
||||
import appeng.tile.networking.TileCableBus;
|
||||
import appeng.util.ConfigManager;
|
||||
import appeng.util.Platform;
|
||||
import appeng.util.item.AEFluidStack;
|
||||
import appeng.util.prioitylist.FuzzyPriorityList;
|
||||
import appeng.util.prioitylist.PrecisePriorityList;
|
||||
import com.glodblock.github.client.textures.FCPartsTexture;
|
||||
import com.glodblock.github.common.item.ItemFluidPacket;
|
||||
import com.glodblock.github.common.tile.TileFluidInterface;
|
||||
import com.glodblock.github.inventory.*;
|
||||
import com.glodblock.github.inventory.gui.GuiType;
|
||||
import com.glodblock.github.util.BlockPos;
|
||||
import com.glodblock.github.util.ModAndClassUtil;
|
||||
import com.glodblock.github.util.Util;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import extracells.tileentity.TileEntityFluidInterface;
|
||||
import net.minecraft.client.renderer.RenderBlocks;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.inventory.IInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.Vec3;
|
||||
import net.minecraftforge.fluids.IFluidHandler;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class PartFluidStorageBus extends PartUpgradeable implements IGridTickable, ICellContainer, IMEMonitorHandlerReceiver<IAEFluidStack>, IPriorityHost {
|
||||
|
||||
private final BaseActionSource source;
|
||||
private final AppEngInternalAEInventory config = new AppEngInternalAEInventory(this, 63);
|
||||
private int priority = 0;
|
||||
private boolean cached = false;
|
||||
private MEMonitorIFluidHandler monitor = null;
|
||||
private MEInventoryHandler<IAEFluidStack> handler = null;
|
||||
private int handlerHash = 0;
|
||||
private boolean wasActive = false;
|
||||
private byte resetCacheLogic = 0;
|
||||
private boolean accessChanged;
|
||||
private boolean readOncePass;
|
||||
|
||||
public PartFluidStorageBus(ItemStack is) {
|
||||
super(is);
|
||||
this.getConfigManager().registerSetting(Settings.ACCESS, AccessRestriction.READ_WRITE);
|
||||
this.getConfigManager().registerSetting(Settings.FUZZY_MODE, FuzzyMode.IGNORE_ALL);
|
||||
this.getConfigManager().registerSetting(Settings.STORAGE_FILTER, StorageFilter.EXTRACTABLE_ONLY);
|
||||
this.source = new MachineSource(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@MENetworkEventSubscribe
|
||||
public void powerRender(final MENetworkPowerStatusChange c) {
|
||||
this.updateStatus();
|
||||
}
|
||||
|
||||
@Override
|
||||
@MENetworkEventSubscribe
|
||||
public void chanRender(final MENetworkChannelsChanged changedChannels) {
|
||||
this.updateStatus();
|
||||
}
|
||||
|
||||
protected void updateStatus() {
|
||||
final boolean currentActive = this.getProxy().isActive();
|
||||
if (this.wasActive != currentActive) {
|
||||
this.wasActive = currentActive;
|
||||
try {
|
||||
this.getProxy().getGrid().postEvent(new MENetworkCellArrayUpdate());
|
||||
this.getHost().markForUpdate();
|
||||
} catch (final GridAccessException e) {
|
||||
// NO-OP
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getUpgradeSlots() {
|
||||
return 5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSetting(final IConfigManager manager, final Enum settingName, final Enum newValue) {
|
||||
if (settingName.name().equals("ACCESS")) {
|
||||
this.accessChanged = true;
|
||||
}
|
||||
this.resetCache(true);
|
||||
this.getHost().markForSave();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void upgradesChanged() {
|
||||
super.upgradesChanged();
|
||||
this.resetCache(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromNBT(final NBTTagCompound data) {
|
||||
super.readFromNBT(data);
|
||||
this.config.readFromNBT(data, "config");
|
||||
this.priority = data.getInteger("priority");
|
||||
this.accessChanged = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToNBT(final NBTTagCompound data) {
|
||||
super.writeToNBT(data);
|
||||
this.config.writeToNBT(data, "config");
|
||||
data.setInteger("priority", this.priority);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IInventory getInventoryByName(final String name) {
|
||||
if (name.equals("config")) {
|
||||
return this.config;
|
||||
}
|
||||
return super.getInventoryByName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeInventory(
|
||||
final IInventory inv,
|
||||
final int slot,
|
||||
final InvOperation mc,
|
||||
final ItemStack removedStack,
|
||||
final ItemStack newStack) {
|
||||
super.onChangeInventory(inv, slot, mc, removedStack, newStack);
|
||||
|
||||
if (inv == this.config) {
|
||||
this.resetCache(true);
|
||||
}
|
||||
}
|
||||
|
||||
protected void resetCache(final boolean fullReset) {
|
||||
if (this.getHost() == null || this.getHost().getTile() == null || this.getHost().getTile().getWorldObj() == null || this.getHost().getTile().getWorldObj().isRemote) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (fullReset) {
|
||||
this.resetCacheLogic = 2;
|
||||
} else if (this.resetCacheLogic < 2) {
|
||||
this.resetCacheLogic = 1;
|
||||
}
|
||||
|
||||
try {
|
||||
this.getProxy().getTick().alertDevice(this.getProxy().getNode());
|
||||
} catch (final GridAccessException ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
protected void resetCache() {
|
||||
final boolean fullReset = this.resetCacheLogic == 2;
|
||||
this.resetCacheLogic = 0;
|
||||
|
||||
final MEInventoryHandler<IAEFluidStack> in = this.getInternalHandler();
|
||||
IItemList<IAEFluidStack> before = AEApi.instance().storage().createFluidList();
|
||||
if (in != null) {
|
||||
if (accessChanged) {
|
||||
AccessRestriction currentAccess = (AccessRestriction) this.getConfigManager().getSetting(Settings.ACCESS);
|
||||
if (!currentAccess.hasPermission(AccessRestriction.READ)) {
|
||||
readOncePass = true;
|
||||
}
|
||||
before = in.getAvailableItems(before);
|
||||
in.setBaseAccess(currentAccess);
|
||||
accessChanged = false;
|
||||
} else {
|
||||
before = in.getAvailableItems(before);
|
||||
}
|
||||
}
|
||||
|
||||
this.cached = false;
|
||||
if (fullReset) {
|
||||
this.handlerHash = 0;
|
||||
}
|
||||
|
||||
final MEInventoryHandler<IAEFluidStack> out = this.getInternalHandler();
|
||||
IItemList<IAEFluidStack> after = AEApi.instance().storage().createFluidList();
|
||||
|
||||
if (in != out) {
|
||||
if (out != null) {
|
||||
after = out.getAvailableItems(after);
|
||||
}
|
||||
Platform.postListChanges(before, after, this, this.source);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(final Object verificationToken) {
|
||||
return this.handler == verificationToken;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postChange(final IBaseMonitor<IAEFluidStack> monitor, final Iterable<IAEFluidStack> change, final BaseActionSource source) {
|
||||
if (this.getProxy().isActive()) {
|
||||
AccessRestriction currentAccess = (AccessRestriction) ((ConfigManager) this.getConfigManager()).getSetting(Settings.ACCESS);
|
||||
if (readOncePass) {
|
||||
readOncePass = false;
|
||||
try {
|
||||
this.getProxy().getStorage().postAlterationOfStoredItems(StorageChannel.FLUIDS, change, this.source);
|
||||
} catch (final GridAccessException ignore) {
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!currentAccess.hasPermission(AccessRestriction.READ)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
this.getProxy().getStorage().postAlterationOfStoredItems(StorageChannel.FLUIDS, change, source);
|
||||
} catch (final GridAccessException ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onListUpdate() {
|
||||
// NO-OP
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getBoxes(final IPartCollisionHelper bch) {
|
||||
bch.addBox(3, 3, 15, 13, 13, 16);
|
||||
bch.addBox(2, 2, 14, 14, 14, 15);
|
||||
bch.addBox(5, 5, 12, 11, 11, 14);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNeighborChanged() {
|
||||
BlockPos neighbor = new BlockPos(this.getTile()).getOffSet(this.getSide());
|
||||
final TileEntity te = neighbor.getTileEntity();
|
||||
// In case the TE was destroyed, we have to do a full reset immediately.
|
||||
if (te instanceof TileCableBus) {
|
||||
IPart iPart = ((TileCableBus) te).getPart(this.getSide().getOpposite());
|
||||
if (iPart == null || iPart instanceof PartFluidInterface) {
|
||||
this.resetCache(true);
|
||||
this.resetCache();
|
||||
} if (ModAndClassUtil.EC2) {
|
||||
if (iPart == null || iPart instanceof extracells.part.PartFluidInterface) {
|
||||
this.resetCache(true);
|
||||
this.resetCache();
|
||||
}
|
||||
}
|
||||
} else if (te == null || te instanceof TileFluidInterface) {
|
||||
this.resetCache(true);
|
||||
this.resetCache();
|
||||
} else if (ModAndClassUtil.EC2) {
|
||||
if (te instanceof TileEntityFluidInterface) {
|
||||
this.resetCache(true);
|
||||
this.resetCache();
|
||||
}
|
||||
} else {
|
||||
this.resetCache(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPartActivate(final EntityPlayer player, final Vec3 pos) {
|
||||
if (player.isSneaking()) {
|
||||
return false;
|
||||
}
|
||||
if (Platform.isServer()) {
|
||||
InventoryHandler.openGui(
|
||||
player,
|
||||
this.getHost().getTile().getWorldObj(),
|
||||
new BlockPos(this.getHost().getTile()),
|
||||
Objects.requireNonNull(Util.from(this.getSide())),
|
||||
GuiType.FLUID_STORAGE_BUS);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickingRequest getTickingRequest(IGridNode node) {
|
||||
return new TickingRequest(TickRates.StorageBus.getMin(), TickRates.StorageBus.getMax(), monitor == null, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickRateModulation tickingRequest(IGridNode node, int ticksSinceLastCall) {
|
||||
if (this.resetCacheLogic != 0) {
|
||||
this.resetCache();
|
||||
}
|
||||
if (this.monitor != null) {
|
||||
return this.monitor.onTick();
|
||||
}
|
||||
return TickRateModulation.SLEEP;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public MEInventoryHandler<IAEFluidStack> getInternalHandler() {
|
||||
if (this.cached) {
|
||||
return this.handler;
|
||||
}
|
||||
|
||||
final boolean wasSleeping = this.monitor == null;
|
||||
|
||||
this.cached = true;
|
||||
final TileEntity self = this.getHost().getTile();
|
||||
final TileEntity target = new BlockPos(self).getOffSet(this.getSide()).getTileEntity();
|
||||
final int newHandlerHash = Platform.generateTileHash(target);
|
||||
if (newHandlerHash != 0 && newHandlerHash == this.handlerHash) {
|
||||
return this.handler;
|
||||
}
|
||||
this.handlerHash = newHandlerHash;
|
||||
this.handler = null;
|
||||
this.monitor = null;
|
||||
if (target != null) {
|
||||
final IExternalStorageHandler esh = AEApi.instance()
|
||||
.registries()
|
||||
.externalStorage()
|
||||
.getHandler(target, this.getSide().getOpposite(), StorageChannel.FLUIDS, this.source);
|
||||
if (esh != null) {
|
||||
final IMEInventory<?> inv =
|
||||
esh.getInventory(target, this.getSide().getOpposite(), StorageChannel.FLUIDS, this.source);
|
||||
if (inv instanceof MEMonitorIFluidHandler) {
|
||||
final MEMonitorIFluidHandler h = (MEMonitorIFluidHandler) inv;
|
||||
h.setMode((StorageFilter) this.getConfigManager().getSetting(Settings.STORAGE_FILTER));
|
||||
h.setActionSource(new MachineSource(this));
|
||||
this.monitor = (MEMonitorIFluidHandler) inv;
|
||||
}
|
||||
if (inv != null) {
|
||||
this.handler = new MEInventoryHandler(inv, StorageChannel.FLUIDS);
|
||||
this.handler.setBaseAccess(
|
||||
(AccessRestriction) this.getConfigManager().getSetting(Settings.ACCESS));
|
||||
this.handler.setWhitelist(
|
||||
this.getInstalledUpgrades(Upgrades.INVERTER) > 0
|
||||
? IncludeExclude.BLACKLIST
|
||||
: IncludeExclude.WHITELIST);
|
||||
this.handler.setPriority(this.priority);
|
||||
if (inv instanceof IMEMonitor) {
|
||||
((IBaseMonitor) inv).addListener(this, this.handler);
|
||||
}
|
||||
final IItemList<IAEFluidStack> priorityList =
|
||||
AEApi.instance().storage().createFluidList();
|
||||
|
||||
final int slotsToUse = 18 + this.getInstalledUpgrades(Upgrades.CAPACITY) * 9;
|
||||
for (int x = 0; x < this.config.getSizeInventory() && x < slotsToUse; x++) {
|
||||
final IAEItemStack is = this.config.getAEStackInSlot(x);
|
||||
if (is != null) priorityList.add(AEFluidStack.create(ItemFluidPacket.getFluidStack(is)));
|
||||
}
|
||||
this.handler.setPartitionList(new PrecisePriorityList(priorityList));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update sleep state...
|
||||
if (wasSleeping != (this.monitor == null)) {
|
||||
try {
|
||||
final ITickManager tm = this.getProxy().getTick();
|
||||
if (this.monitor == null) {
|
||||
tm.sleepDevice(this.getProxy().getNode());
|
||||
} else {
|
||||
tm.wakeDevice(this.getProxy().getNode());
|
||||
}
|
||||
} catch (final GridAccessException ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// force grid to update handlers...
|
||||
((GridStorageCache) this.getProxy().getGrid().getCache(IStorageGrid.class)).cellUpdate(null);
|
||||
} catch (final GridAccessException ignore) {
|
||||
}
|
||||
|
||||
return this.handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("rawtypes")
|
||||
public List<IMEInventoryHandler> getCellArray(final StorageChannel channel) {
|
||||
if (channel == StorageChannel.FLUIDS) {
|
||||
final IMEInventoryHandler<IAEFluidStack> out = this.getInternalHandler();
|
||||
if (out != null) {
|
||||
return Collections.singletonList(out);
|
||||
}
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return this.priority;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPriority(int newValue) {
|
||||
this.priority = newValue;
|
||||
this.getHost().markForSave();
|
||||
this.resetCache(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void blinkCell(int slot) {
|
||||
// NO-OP
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveChanges(final IMEInventory cellInventory) {
|
||||
// NO-OP
|
||||
}
|
||||
|
||||
public AppEngInternalAEInventory getConfig() {
|
||||
return this.config;
|
||||
}
|
||||
|
||||
public void setFluidInSlot(int id, IAEFluidStack fluid) {
|
||||
ItemStack tmp = ItemFluidPacket.newDisplayStack(fluid == null ? null : fluid.getFluidStack());
|
||||
this.config.setInventorySlotContents(id, tmp);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SideOnly(Side.CLIENT)
|
||||
public void renderInventory(final IPartRenderHelper rh, final RenderBlocks renderer) {
|
||||
rh.setTexture(
|
||||
CableBusTextures.PartStorageSides.getIcon(),
|
||||
CableBusTextures.PartStorageSides.getIcon(),
|
||||
CableBusTextures.PartStorageBack.getIcon(),
|
||||
FCPartsTexture.PartFluidStorageBus.getIcon(),
|
||||
CableBusTextures.PartStorageSides.getIcon(),
|
||||
CableBusTextures.PartStorageSides.getIcon());
|
||||
|
||||
rh.setBounds(3, 3, 15, 13, 13, 16);
|
||||
rh.renderInventoryBox(renderer);
|
||||
|
||||
rh.setBounds(2, 2, 14, 14, 14, 15);
|
||||
rh.renderInventoryBox(renderer);
|
||||
|
||||
rh.setBounds(5, 5, 12, 11, 11, 14);
|
||||
rh.renderInventoryBox(renderer);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SideOnly(Side.CLIENT)
|
||||
public void renderStatic(
|
||||
final int x, final int y, final int z, final IPartRenderHelper rh, final RenderBlocks renderer) {
|
||||
this.setRenderCache(rh.useSimplifiedRendering(x, y, z, this, this.getRenderCache()));
|
||||
rh.setTexture(
|
||||
CableBusTextures.PartStorageSides.getIcon(),
|
||||
CableBusTextures.PartStorageSides.getIcon(),
|
||||
CableBusTextures.PartStorageBack.getIcon(),
|
||||
FCPartsTexture.PartFluidStorageBus.getIcon(),
|
||||
CableBusTextures.PartStorageSides.getIcon(),
|
||||
CableBusTextures.PartStorageSides.getIcon());
|
||||
|
||||
rh.setBounds(3, 3, 15, 13, 13, 16);
|
||||
rh.renderBlock(x, y, z, renderer);
|
||||
|
||||
rh.setBounds(2, 2, 14, 14, 14, 15);
|
||||
rh.renderBlock(x, y, z, renderer);
|
||||
|
||||
rh.setTexture(
|
||||
CableBusTextures.PartStorageSides.getIcon(),
|
||||
CableBusTextures.PartStorageSides.getIcon(),
|
||||
CableBusTextures.PartStorageBack.getIcon(),
|
||||
FCPartsTexture.PartFluidStorageBus.getIcon(),
|
||||
CableBusTextures.PartStorageSides.getIcon(),
|
||||
CableBusTextures.PartStorageSides.getIcon());
|
||||
|
||||
rh.setBounds(5, 5, 12, 11, 11, 13);
|
||||
rh.renderBlock(x, y, z, renderer);
|
||||
|
||||
rh.setTexture(
|
||||
CableBusTextures.PartMonitorSidesStatus.getIcon(),
|
||||
CableBusTextures.PartMonitorSidesStatus.getIcon(),
|
||||
CableBusTextures.PartMonitorBack.getIcon(),
|
||||
FCPartsTexture.PartFluidStorageBus.getIcon(),
|
||||
CableBusTextures.PartMonitorSidesStatus.getIcon(),
|
||||
CableBusTextures.PartMonitorSidesStatus.getIcon());
|
||||
|
||||
rh.setBounds(5, 5, 13, 11, 11, 14);
|
||||
rh.renderBlock(x, y, z, renderer);
|
||||
|
||||
this.renderLights(x, y, z, rh, renderer);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -35,6 +35,9 @@ public class FCClassTransformer implements IClassTransformer {
|
||||
case "appeng.tile.storage.TileIOPort":
|
||||
tform = TitleIOPortTransformer.INSTANCE;
|
||||
break;
|
||||
case "appeng.core.features.registries.ExternalStorageRegistry":
|
||||
tform = ExternalStorageRegistryTransformer.INSTANCE;
|
||||
break;
|
||||
default:
|
||||
return code;
|
||||
}
|
||||
@@ -53,7 +56,7 @@ public class FCClassTransformer implements IClassTransformer {
|
||||
public byte[] transformClass(byte[] code) {
|
||||
ClassReader reader = new ClassReader(code);
|
||||
ClassWriter writer = new ClassWriter(reader, getWriteFlags());
|
||||
reader.accept(getClassMapper(writer), 0);
|
||||
reader.accept(getClassMapper(writer), ClassReader.EXPAND_FRAMES);
|
||||
return writer.toByteArray();
|
||||
}
|
||||
|
||||
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
package com.glodblock.github.coremod.transform;
|
||||
|
||||
import com.glodblock.github.coremod.FCClassTransformer;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
public class ExternalStorageRegistryTransformer extends FCClassTransformer.ClassMapper {
|
||||
|
||||
public static final ExternalStorageRegistryTransformer INSTANCE = new ExternalStorageRegistryTransformer();
|
||||
|
||||
private ExternalStorageRegistryTransformer() {
|
||||
// NO-OP
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ClassVisitor getClassMapper(ClassVisitor downstream) {
|
||||
return new TransformExternalStorageRegistry(Opcodes.ASM5, downstream);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getWriteFlags() {
|
||||
return ClassWriter.COMPUTE_FRAMES;
|
||||
}
|
||||
|
||||
private static class TransformExternalStorageRegistry extends ClassVisitor {
|
||||
|
||||
public TransformExternalStorageRegistry(int api, ClassVisitor cv) {
|
||||
super(api, cv);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
|
||||
if ("getHandler".equals(name)) {
|
||||
return new TransformGetHandler(api, super.visitMethod(access, name, desc, signature, exceptions));
|
||||
} else {
|
||||
return super.visitMethod(access, name, desc, signature, exceptions);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class TransformGetHandler extends MethodVisitor {
|
||||
|
||||
private int cnt_return = 0;
|
||||
private int cnt_if = 0;
|
||||
private Label L6 = null;
|
||||
private final Label L9 = new Label();
|
||||
|
||||
TransformGetHandler(int api, MethodVisitor mv) {
|
||||
super(api, mv);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitJumpInsn(int opcode, Label label) {
|
||||
if (opcode == Opcodes.IFEQ) {
|
||||
cnt_if ++;
|
||||
}
|
||||
if (cnt_if == 3) {
|
||||
L6 = label;
|
||||
cnt_if ++;
|
||||
super.visitJumpInsn(opcode, L9);
|
||||
return;
|
||||
}
|
||||
super.visitJumpInsn(opcode, label);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInsn(int opcode) {
|
||||
if (opcode == Opcodes.ARETURN) {
|
||||
cnt_return ++;
|
||||
}
|
||||
super.visitInsn(opcode);
|
||||
if (cnt_return == 2) {
|
||||
super.visitLabel(L9);
|
||||
super.visitFieldInsn(Opcodes.GETSTATIC, "com/glodblock/github/inventory/external/AEFluidTankHandler",
|
||||
"INSTANCE", "Lcom/glodblock/github/inventory/external/AEFluidTankHandler;");
|
||||
super.visitVarInsn(Opcodes.ALOAD, 1);
|
||||
super.visitVarInsn(Opcodes.ALOAD, 2);
|
||||
super.visitVarInsn(Opcodes.ALOAD, 3);
|
||||
super.visitVarInsn(Opcodes.ALOAD, 4);
|
||||
super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "com/glodblock/github/inventory/external/AEFluidTankHandler",
|
||||
"canHandle",
|
||||
"(Lnet/minecraft/tileentity/TileEntity;Lnet/minecraftforge/common/util/ForgeDirection;Lappeng/api/storage/StorageChannel;Lappeng/api/networking/security/BaseActionSource;)Z",
|
||||
false);
|
||||
super.visitJumpInsn(Opcodes.IFEQ, L6);
|
||||
super.visitFieldInsn(Opcodes.GETSTATIC, "com/glodblock/github/inventory/external/AEFluidTankHandler",
|
||||
"INSTANCE", "Lcom/glodblock/github/inventory/external/AEFluidTankHandler;");
|
||||
super.visitInsn(Opcodes.ARETURN);
|
||||
cnt_return ++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -20,14 +20,22 @@ import net.minecraftforge.fluids.IFluidHandler;
|
||||
|
||||
public class MEMonitorIFluidHandler implements IMEMonitor<IAEFluidStack> {
|
||||
private final IFluidHandler handler;
|
||||
private final ForgeDirection side;
|
||||
private IItemList<IAEFluidStack> cache = AEApi.instance().storage().createFluidList();
|
||||
private final HashMap<IMEMonitorHandlerReceiver<IAEFluidStack>, Object> listeners = new HashMap<>();
|
||||
private BaseActionSource mySource;
|
||||
private StorageFilter mode;
|
||||
|
||||
public MEMonitorIFluidHandler(IFluidHandler handler, ForgeDirection side) {
|
||||
this.mode = StorageFilter.EXTRACTABLE_ONLY;
|
||||
this.handler = handler;
|
||||
this.side = side;
|
||||
}
|
||||
|
||||
public MEMonitorIFluidHandler(IFluidHandler handler) {
|
||||
this.mode = StorageFilter.EXTRACTABLE_ONLY;
|
||||
this.handler = handler;
|
||||
this.side = ForgeDirection.UNKNOWN;
|
||||
}
|
||||
|
||||
public void addListener(IMEMonitorHandlerReceiver<IAEFluidStack> l, Object verificationToken) {
|
||||
@@ -39,7 +47,7 @@ public class MEMonitorIFluidHandler implements IMEMonitor<IAEFluidStack> {
|
||||
}
|
||||
|
||||
public IAEFluidStack injectItems(IAEFluidStack input, Actionable type, BaseActionSource src) {
|
||||
int filled = this.handler.fill(ForgeDirection.UNKNOWN, input.getFluidStack(), type == Actionable.MODULATE);
|
||||
int filled = this.handler.fill(this.side, input.getFluidStack(), type == Actionable.MODULATE);
|
||||
if (filled == 0) {
|
||||
return input.copy();
|
||||
} else if ((long) filled == input.getStackSize()) {
|
||||
@@ -59,7 +67,7 @@ public class MEMonitorIFluidHandler implements IMEMonitor<IAEFluidStack> {
|
||||
|
||||
public IAEFluidStack extractItems(IAEFluidStack request, Actionable type, BaseActionSource src) {
|
||||
FluidStack removed =
|
||||
this.handler.drain(ForgeDirection.UNKNOWN, request.getFluidStack(), type == Actionable.MODULATE);
|
||||
this.handler.drain(this.side, request.getFluidStack(), type == Actionable.MODULATE);
|
||||
if (removed != null && removed.amount != 0) {
|
||||
IAEFluidStack o = request.copy();
|
||||
o.setStackSize(removed.amount);
|
||||
@@ -86,13 +94,15 @@ public class MEMonitorIFluidHandler implements IMEMonitor<IAEFluidStack> {
|
||||
public TickRateModulation onTick() {
|
||||
boolean changed = false;
|
||||
List<IAEFluidStack> changes = new ArrayList<>();
|
||||
FluidTankInfo[] tankProperties = this.handler.getTankInfo(ForgeDirection.UNKNOWN);
|
||||
FluidTankInfo[] tankProperties = this.handler.getTankInfo(this.side);
|
||||
IItemList<IAEFluidStack> currentlyOnStorage = AEApi.instance().storage().createFluidList();
|
||||
|
||||
for (FluidTankInfo tankProperty : tankProperties) {
|
||||
if (this.mode != StorageFilter.EXTRACTABLE_ONLY
|
||||
|| this.handler.drain(ForgeDirection.UNKNOWN, 1, false) != null) {
|
||||
currentlyOnStorage.add(AEFluidStack.create(tankProperty.fluid));
|
||||
if (tankProperties != null) {
|
||||
for (FluidTankInfo tankProperty : tankProperties) {
|
||||
if (this.mode != StorageFilter.EXTRACTABLE_ONLY
|
||||
|| this.handler.drain(this.side, 1, false) != null) {
|
||||
currentlyOnStorage.add(AEFluidStack.create(tankProperty.fluid));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,7 +141,7 @@ public class MEMonitorIFluidHandler implements IMEMonitor<IAEFluidStack> {
|
||||
|
||||
private void postDifference(Iterable<IAEFluidStack> a) {
|
||||
if (a != null) {
|
||||
Iterator i = this.listeners.entrySet().iterator();
|
||||
Iterator<?> i = this.listeners.entrySet().iterator();
|
||||
|
||||
while (i.hasNext()) {
|
||||
Map.Entry<IMEMonitorHandlerReceiver<IAEFluidStack>, Object> l = (Map.Entry) i.next();
|
||||
@@ -170,7 +180,7 @@ public class MEMonitorIFluidHandler implements IMEMonitor<IAEFluidStack> {
|
||||
}
|
||||
|
||||
public IItemList<IAEFluidStack> getAvailableItems(IItemList out) {
|
||||
Iterator var2 = this.cache.iterator();
|
||||
Iterator<?> var2 = this.cache.iterator();
|
||||
|
||||
while (var2.hasNext()) {
|
||||
IAEFluidStack fs = (IAEFluidStack) var2.next();
|
||||
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package com.glodblock.github.inventory.external;
|
||||
|
||||
import appeng.api.implementations.tiles.ITileStorageMonitorable;
|
||||
import appeng.api.networking.security.BaseActionSource;
|
||||
import appeng.api.storage.IExternalStorageHandler;
|
||||
import appeng.api.storage.IMEInventory;
|
||||
import appeng.api.storage.StorageChannel;
|
||||
import appeng.tile.networking.TileCableBus;
|
||||
import com.glodblock.github.common.parts.PartFluidInterface;
|
||||
import com.glodblock.github.common.tile.TileFluidInterface;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraftforge.common.util.ForgeDirection;
|
||||
|
||||
public class AEFluidInterfaceHandler implements IExternalStorageHandler {
|
||||
|
||||
@Override
|
||||
public boolean canHandle(TileEntity te, ForgeDirection d, StorageChannel channel, BaseActionSource mySrc) {
|
||||
if (channel == StorageChannel.FLUIDS) {
|
||||
if (te instanceof ITileStorageMonitorable) {
|
||||
return true;
|
||||
} else return te instanceof TileCableBus && ((TileCableBus) te).getPart(d.getOpposite()) instanceof ITileStorageMonitorable;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("rawtypes")
|
||||
public IMEInventory getInventory(TileEntity te, ForgeDirection d, StorageChannel channel, BaseActionSource src) {
|
||||
if (channel == StorageChannel.FLUIDS) {
|
||||
if (te instanceof ITileStorageMonitorable) {
|
||||
return ((ITileStorageMonitorable) te).getMonitorable(d, src).getFluidInventory();
|
||||
}
|
||||
else if (te instanceof TileCableBus && ((TileCableBus) te).getPart(d.getOpposite()) instanceof ITileStorageMonitorable) {
|
||||
ITileStorageMonitorable part = (ITileStorageMonitorable) ((TileCableBus) te).getPart(d.getOpposite());
|
||||
return part.getMonitorable(d, src).getFluidInventory();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package com.glodblock.github.inventory.external;
|
||||
|
||||
import appeng.api.networking.security.BaseActionSource;
|
||||
import appeng.api.storage.IExternalStorageHandler;
|
||||
import appeng.api.storage.IMEInventory;
|
||||
import appeng.api.storage.StorageChannel;
|
||||
import com.glodblock.github.inventory.MEMonitorIFluidHandler;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraftforge.common.util.ForgeDirection;
|
||||
import net.minecraftforge.fluids.IFluidHandler;
|
||||
|
||||
// This handler is too generic, so it will overlap other mods' fluid handler.
|
||||
// It will be injected into external handler by ASM to make sure it is executed at last.
|
||||
public class AEFluidTankHandler implements IExternalStorageHandler {
|
||||
|
||||
public static final AEFluidTankHandler INSTANCE = new AEFluidTankHandler();
|
||||
|
||||
@Override
|
||||
public boolean canHandle(TileEntity te, ForgeDirection d, StorageChannel channel, BaseActionSource mySrc) {
|
||||
return channel == StorageChannel.FLUIDS && te instanceof IFluidHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("rawtypes")
|
||||
public IMEInventory getInventory(TileEntity te, ForgeDirection d, StorageChannel channel, BaseActionSource src) {
|
||||
if (channel == StorageChannel.FLUIDS) {
|
||||
return new MEMonitorIFluidHandler((IFluidHandler) te, d);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import com.glodblock.github.client.gui.*;
|
||||
import com.glodblock.github.client.gui.container.*;
|
||||
import com.glodblock.github.common.parts.FCBasePart;
|
||||
import com.glodblock.github.common.parts.PartFluidInterface;
|
||||
import com.glodblock.github.common.parts.PartFluidStorageBus;
|
||||
import com.glodblock.github.common.parts.PartSharedFluidBus;
|
||||
import com.glodblock.github.common.tile.*;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
@@ -113,6 +114,18 @@ public enum GuiType {
|
||||
}
|
||||
}),
|
||||
|
||||
FLUID_STORAGE_BUS_PRIORITY(new PartGuiFactory<IPriorityHost>(IPriorityHost.class) {
|
||||
@Override
|
||||
protected Object createServerGui(EntityPlayer player, IPriorityHost inv) {
|
||||
return new ContainerPriority(player.inventory, inv);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object createClientGui(EntityPlayer player, IPriorityHost inv) {
|
||||
return new GuiFCPriority(player.inventory, inv);
|
||||
}
|
||||
}),
|
||||
|
||||
FLUID_BUS_IO(new PartGuiFactory<PartSharedFluidBus>(PartSharedFluidBus.class) {
|
||||
@Override
|
||||
protected Object createServerGui(EntityPlayer player, PartSharedFluidBus inv) {
|
||||
@@ -125,6 +138,18 @@ public enum GuiType {
|
||||
}
|
||||
}),
|
||||
|
||||
FLUID_STORAGE_BUS(new PartGuiFactory<PartFluidStorageBus>(PartFluidStorageBus.class) {
|
||||
@Override
|
||||
protected Object createServerGui(EntityPlayer player, PartFluidStorageBus inv) {
|
||||
return new ContainerFluidStorageBus(player.inventory, inv);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object createClientGui(EntityPlayer player, PartFluidStorageBus inv) {
|
||||
return new GuiFluidStorageBus(player.inventory, inv);
|
||||
}
|
||||
}),
|
||||
|
||||
INGREDIENT_BUFFER(new TileGuiFactory<TileIngredientBuffer>(TileIngredientBuffer.class) {
|
||||
@Override
|
||||
protected Object createServerGui(EntityPlayer player, TileIngredientBuffer inv) {
|
||||
|
||||
@@ -25,6 +25,7 @@ public class ItemAndBlockHolder {
|
||||
public static ItemPartFluidInterface FLUID_INTERFACE = new ItemPartFluidInterface().register();
|
||||
public static ItemFluidImportBus FLUID_IMPORT_BUS = new ItemFluidImportBus().register();
|
||||
public static ItemFluidExportBus FLUID_EXPORT_BUS = new ItemFluidExportBus().register();
|
||||
public static ItemPartFluidStorageBus FLUID_STORAGE_BUS = new ItemPartFluidStorageBus().register();
|
||||
public static ItemFluidPacket PACKET = new ItemFluidPacket().register();
|
||||
public static ItemBasicFluidStorageCell CELL1K = new ItemBasicFluidStorageCell(CellType.Cell1kPart, 1).register();
|
||||
public static ItemBasicFluidStorageCell CELL4K = new ItemBasicFluidStorageCell(CellType.Cell4kPart, 4).register();
|
||||
|
||||
@@ -50,6 +50,7 @@ public class RecipeLoader implements Runnable {
|
||||
public static final ItemStack AE2_CORE_FOM =
|
||||
new ItemStack(GameRegistry.findItem("appliedenergistics2", "item.ItemMultiMaterial"), 1, 43);
|
||||
public static final ItemStack PISTON = new ItemStack(Blocks.piston, 1);
|
||||
public static final ItemStack STICKY_PISTON = new ItemStack(Blocks.sticky_piston, 1);
|
||||
public static final ItemStack AE2_BLANK_PATTERN =
|
||||
new ItemStack(GameRegistry.findItem("appliedenergistics2", "item.ItemMultiMaterial"), 1, 52);
|
||||
public static final ItemStack AE2_TERMINAL =
|
||||
@@ -119,6 +120,8 @@ public class RecipeLoader implements Runnable {
|
||||
AE2_PROCESS_ENG,
|
||||
'W',
|
||||
AE2_WORK_BENCH));
|
||||
GameRegistry.addShapelessRecipe(FLUID_STORAGE_BUS.stack(), FLUID_INTERFACE, STICKY_PISTON, PISTON);
|
||||
GameRegistry.addShapelessRecipe(FLUID_STORAGE_BUS.stack(), INTERFACE, STICKY_PISTON, PISTON);
|
||||
GameRegistry.addShapelessRecipe(FLUID_TERMINAL.stack(), AE2_PATTERN_TERM, ENCODER);
|
||||
GameRegistry.addShapelessRecipe(
|
||||
FLUID_TERMINAL_EX.stack(), FLUID_TERMINAL.stack(), AE2_PROCESS_CAL, AE2_PROCESS_ENG, AE2_PROCESS_LOG);
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.glodblock.github.network;
|
||||
import com.glodblock.github.client.gui.container.ContainerFluidCraftConfirm;
|
||||
import com.glodblock.github.client.gui.container.ContainerFluidPatternTerminal;
|
||||
import com.glodblock.github.client.gui.container.ContainerFluidPatternTerminalEx;
|
||||
import com.glodblock.github.client.gui.container.ContainerFluidStorageBus;
|
||||
import cpw.mods.fml.common.network.simpleimpl.IMessage;
|
||||
import cpw.mods.fml.common.network.simpleimpl.IMessageHandler;
|
||||
import cpw.mods.fml.common.network.simpleimpl.MessageContext;
|
||||
@@ -145,6 +146,15 @@ public class CPacketFluidPatternTermBtns implements IMessage {
|
||||
} else if (Name.equals("Terminal.Start") && c instanceof ContainerFluidCraftConfirm) {
|
||||
final ContainerFluidCraftConfirm qk = (ContainerFluidCraftConfirm) c;
|
||||
qk.startJob();
|
||||
} else if (Name.startsWith("StorageBus.") && c instanceof ContainerFluidStorageBus) {
|
||||
final ContainerFluidStorageBus ccw = (ContainerFluidStorageBus) c;
|
||||
if (Name.equals("StorageBus.Action")) {
|
||||
if (Value.equals("Partition")) {
|
||||
ccw.partition();
|
||||
} else if (Value.equals("Clear")) {
|
||||
ccw.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -111,6 +111,10 @@ public class SPacketFluidUpdate implements IMessage {
|
||||
} else {
|
||||
((GuiFluidTerminal) gs).update(null);
|
||||
}
|
||||
} else if (gs instanceof GuiFluidStorageBus) {
|
||||
for (Map.Entry<Integer, IAEFluidStack> e : message.list.entrySet()) {
|
||||
((GuiFluidStorageBus) gs).update(e.getKey(), e.getValue());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
package com.glodblock.github.proxy;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.config.Upgrades;
|
||||
import com.glodblock.github.FluidCraft;
|
||||
import com.glodblock.github.common.Config;
|
||||
import com.glodblock.github.inventory.external.AEFluidInterfaceHandler;
|
||||
import com.glodblock.github.loader.ItemAndBlockHolder;
|
||||
import com.glodblock.github.util.ModAndClassUtil;
|
||||
import cpw.mods.fml.common.event.FMLInitializationEvent;
|
||||
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
|
||||
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
|
||||
import cpw.mods.fml.common.network.NetworkRegistry;
|
||||
import cpw.mods.fml.common.network.simpleimpl.SimpleNetworkWrapper;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
public class CommonProxy {
|
||||
|
||||
@@ -15,5 +22,27 @@ public class CommonProxy {
|
||||
|
||||
public void init(FMLInitializationEvent event) {}
|
||||
|
||||
public void postInit(FMLPostInitializationEvent event) {}
|
||||
public void postInit(FMLPostInitializationEvent event) {
|
||||
if (ModAndClassUtil.isBigInterface) {
|
||||
Upgrades.PATTERN_CAPACITY.registerItem(new ItemStack(ItemAndBlockHolder.FLUID_INTERFACE), 3);
|
||||
Upgrades.PATTERN_CAPACITY.registerItem(new ItemStack(ItemAndBlockHolder.INTERFACE), 3);
|
||||
}
|
||||
Upgrades.CRAFTING.registerItem(new ItemStack(ItemAndBlockHolder.FLUID_INTERFACE), 1);
|
||||
Upgrades.CRAFTING.registerItem(new ItemStack(ItemAndBlockHolder.INTERFACE), 1);
|
||||
Upgrades.CAPACITY.registerItem(new ItemStack(ItemAndBlockHolder.FLUID_STORAGE_BUS), 5);
|
||||
Upgrades.INVERTER.registerItem(new ItemStack(ItemAndBlockHolder.FLUID_STORAGE_BUS), 1);
|
||||
|
||||
if (Config.fluidIOBus) {
|
||||
Upgrades.CAPACITY.registerItem(new ItemStack(ItemAndBlockHolder.FLUID_EXPORT_BUS), 2);
|
||||
Upgrades.CAPACITY.registerItem(new ItemStack(ItemAndBlockHolder.FLUID_IMPORT_BUS), 2);
|
||||
Upgrades.REDSTONE.registerItem(new ItemStack(ItemAndBlockHolder.FLUID_EXPORT_BUS), 1);
|
||||
Upgrades.REDSTONE.registerItem(new ItemStack(ItemAndBlockHolder.FLUID_IMPORT_BUS), 1);
|
||||
Upgrades.SPEED.registerItem(new ItemStack(ItemAndBlockHolder.FLUID_EXPORT_BUS), 4);
|
||||
Upgrades.SPEED.registerItem(new ItemStack(ItemAndBlockHolder.FLUID_IMPORT_BUS), 4);
|
||||
Upgrades.SUPERSPEED.registerItem(new ItemStack(ItemAndBlockHolder.FLUID_EXPORT_BUS), 4);
|
||||
Upgrades.SUPERSPEED.registerItem(new ItemStack(ItemAndBlockHolder.FLUID_IMPORT_BUS), 4);
|
||||
Upgrades.CRAFTING.registerItem(new ItemStack(ItemAndBlockHolder.FLUID_EXPORT_BUS), 1);
|
||||
}
|
||||
AEApi.instance().registries().externalStorage().addExternalStorageInterface(new AEFluidInterfaceHandler());
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ public class NameConst {
|
||||
public static final String ITEM_PART_FLUID_INTERFACE = "part_fluid_interface";
|
||||
public static final String ITEM_PART_FLUID_IMPORT = "part_fluid_import";
|
||||
public static final String ITEM_PART_FLUID_EXPORT = "part_fluid_export";
|
||||
public static final String ITEM_PART_FLUID_STORAGE_BUS = "part_fluid_storage_bus";
|
||||
public static final String ITEM_FLUID_PACKET = "fluid_packet";
|
||||
public static final String ITEM_FLUID_STORAGE = "fluid_storage";
|
||||
public static final String ITEM_FLUID_PART = "fluid_part";
|
||||
@@ -78,6 +79,7 @@ public class NameConst {
|
||||
public static final String GUI_OC_PATTERN_EDITOR = GUI_KEY + BLOCK_OC_PATTERN_EDITOR;
|
||||
public static final String GUI_FLUID_IMPORT = GUI_KEY + ITEM_PART_FLUID_IMPORT;
|
||||
public static final String GUI_FLUID_EXPORT = GUI_KEY + ITEM_PART_FLUID_EXPORT;
|
||||
public static final String GUI_FLUID_STORAGE_BUS = GUI_KEY + ITEM_PART_FLUID_STORAGE_BUS;
|
||||
|
||||
public static String i18n(String t, String delimiter, boolean hint) {
|
||||
if (!hint) {
|
||||
|
||||
@@ -6,6 +6,7 @@ item.part_fluid_pattern_terminal_ex.name=ME Fluid Processing Pattern Terminal
|
||||
item.part_fluid_interface.name=ME Dual Interface
|
||||
item.part_fluid_import.name=ME Fluid Import Bus
|
||||
item.part_fluid_export.name=ME Fluid Export Bus
|
||||
item.part_fluid_storage_bus.name=ME Fluid Storage Bus
|
||||
item.fluid_packet.name=Fluid Packet
|
||||
item.fluid_storage.1.name=1k ME Fluid Storage Cell
|
||||
item.fluid_storage.4.name=4k ME Fluid Storage Cell
|
||||
@@ -95,7 +96,8 @@ ae2fc.gui.oc_pattern_editor=OC Pattern Editor
|
||||
ae2fc.gui.button.set=Set
|
||||
ae2fc.gui.part_fluid_import=ME Fluid Import Bus
|
||||
ae2fc.gui.part_fluid_export=ME Fluid Export Bus
|
||||
ae2fc.gui.part_fluid_terminal=Fluid Terminal
|
||||
ae2fc.gui.part_fluid_terminal=ME Fluid Terminal
|
||||
ae2fc.gui.part_fluid_storage_bus=ME Fluid Storage Bus
|
||||
|
||||
error.unknown=Unknown
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 334 B |
Reference in new issue
Block a user