Files
Applied-Energistics-2/src/main/java/appeng/fluids/parts/PartFluidLevelEmitter.java
T

335 lines
12 KiB
Java

package appeng.fluids.parts;
import appeng.api.AEApi;
import appeng.api.config.RedstoneMode;
import appeng.api.config.Settings;
import appeng.api.networking.events.MENetworkChannelsChanged;
import appeng.api.networking.events.MENetworkEventSubscribe;
import appeng.api.networking.events.MENetworkPowerStatusChange;
import appeng.api.networking.security.IActionSource;
import appeng.api.networking.storage.IBaseMonitor;
import appeng.api.networking.storage.IStackWatcher;
import appeng.api.networking.storage.IStackWatcherHost;
import appeng.api.parts.IPartCollisionHelper;
import appeng.api.parts.IPartModel;
import appeng.api.storage.IMEMonitor;
import appeng.api.storage.IMEMonitorHandlerReceiver;
import appeng.api.storage.IStorageChannel;
import appeng.api.storage.channels.IFluidStorageChannel;
import appeng.api.storage.data.IAEFluidStack;
import appeng.api.storage.data.IAEStack;
import appeng.api.storage.data.IItemList;
import appeng.api.util.AECableType;
import appeng.api.util.AEPartLocation;
import appeng.api.util.IConfigManager;
import appeng.core.AppEng;
import appeng.core.sync.GuiBridge;
import appeng.fluids.helper.IConfigurableFluidInventory;
import appeng.fluids.util.AEFluidInventory;
import appeng.fluids.util.IAEFluidInventory;
import appeng.fluids.util.IAEFluidTank;
import appeng.items.parts.PartModels;
import appeng.me.GridAccessException;
import appeng.me.cache.NetworkMonitor;
import appeng.parts.PartModel;
import appeng.parts.automation.PartUpgradeable;
import appeng.util.IConfigManagerHost;
import appeng.util.Platform;
import appeng.util.inv.InvOperation;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumHand;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.IFluidHandler;
import java.util.Random;
public class PartFluidLevelEmitter extends PartUpgradeable implements IStackWatcherHost, IConfigManagerHost, IAEFluidInventory, IMEMonitorHandlerReceiver<IAEFluidStack>, IConfigurableFluidInventory {
@PartModels
public static final ResourceLocation MODEL_BASE_OFF = new ResourceLocation(AppEng.MOD_ID, "part/level_emitter_base_off");
@PartModels
public static final ResourceLocation MODEL_BASE_ON = new ResourceLocation(AppEng.MOD_ID, "part/level_emitter_base_on");
@PartModels
public static final ResourceLocation MODEL_STATUS_OFF = new ResourceLocation(AppEng.MOD_ID, "part/level_emitter_status_off");
@PartModels
public static final ResourceLocation MODEL_STATUS_ON = new ResourceLocation(AppEng.MOD_ID, "part/level_emitter_status_on");
@PartModels
public static final ResourceLocation MODEL_STATUS_HAS_CHANNEL = new ResourceLocation(AppEng.MOD_ID, "part/level_emitter_status_has_channel");
public static final PartModel MODEL_OFF_OFF = new PartModel(MODEL_BASE_OFF, MODEL_STATUS_OFF);
public static final PartModel MODEL_OFF_ON = new PartModel(MODEL_BASE_OFF, MODEL_STATUS_ON);
public static final PartModel MODEL_OFF_HAS_CHANNEL = new PartModel(MODEL_BASE_OFF, MODEL_STATUS_HAS_CHANNEL);
public static final PartModel MODEL_ON_OFF = new PartModel(MODEL_BASE_ON, MODEL_STATUS_OFF);
public static final PartModel MODEL_ON_ON = new PartModel(MODEL_BASE_ON, MODEL_STATUS_ON);
public static final PartModel MODEL_ON_HAS_CHANNEL = new PartModel(MODEL_BASE_ON, MODEL_STATUS_HAS_CHANNEL);
private static final int FLAG_ON = 4;
private boolean prevState = false;
private long lastReportedValue = 0;
private long reportingValue = 0;
private IStackWatcher stackWatcher = null;
private final AEFluidInventory config = new AEFluidInventory(this, 1);
public PartFluidLevelEmitter(ItemStack is) {
super(is);
this.getConfigManager().registerSetting(Settings.REDSTONE_EMITTER, RedstoneMode.HIGH_SIGNAL);
}
public long getReportingValue() {
return this.reportingValue;
}
public void setReportingValue(final long v) {
this.reportingValue = v;
this.updateState();
}
@Override
public void updateSetting(IConfigManager manager, Enum settingName, Enum newValue) {
this.configureWatchers();
}
@Override
public void updateWatcher(IStackWatcher newWatcher) {
this.stackWatcher = newWatcher;
this.configureWatchers();
}
@Override
public void onStackChange(IItemList<?> o, IAEStack<?> fullStack, IAEStack<?> diffStack, IActionSource src, IStorageChannel<?> chan) {
if (chan == AEApi.instance().storage().getStorageChannel(IFluidStorageChannel.class) && fullStack.equals(this.config.getFluidInSlot(0))) {
this.lastReportedValue = fullStack.getStackSize();
this.updateState();
}
}
@Override
public void onFluidInventoryChanged(IAEFluidTank inv, int slot) {
this.configureWatchers();
}
@Override
@MENetworkEventSubscribe
public void powerRender(final MENetworkPowerStatusChange powerEvent) {
if (this.getProxy().isActive()) {
onListUpdate();
}
this.updateState();
}
@Override
@MENetworkEventSubscribe
public void chanRender(final MENetworkChannelsChanged c) {
if (this.getProxy().isActive()) {
onListUpdate();
}
this.updateState();
}
@Override
public int isProvidingStrongPower() {
return this.prevState ? 15 : 0;
}
@Override
public int isProvidingWeakPower() {
return this.prevState ? 15 : 0;
}
@Override
protected int populateFlags(final int cf) {
return cf | (this.prevState ? FLAG_ON : 0);
}
@Override
public boolean isValid(final Object effectiveGrid) {
try {
return this.getProxy().getGrid() == effectiveGrid;
} catch (final GridAccessException e) {
return false;
}
}
@Override
public void postChange(final IBaseMonitor<IAEFluidStack> monitor, final Iterable<IAEFluidStack> change, final IActionSource actionSource) {
this.updateReportingValue((IMEMonitor<IAEFluidStack>) monitor);
}
@Override
public void onListUpdate() {
try {
final IStorageChannel<IAEFluidStack> channel = AEApi.instance().storage().getStorageChannel(IFluidStorageChannel.class);
final IMEMonitor<IAEFluidStack> inventory = this.getProxy().getStorage().getInventory(channel);
this.updateReportingValue(inventory);
} catch (final GridAccessException e) {
// ;P
}
}
private void updateState() {
final boolean isOn = this.isLevelEmitterOn();
if (this.prevState != isOn) {
this.getHost().markForUpdate();
final TileEntity te = this.getHost().getTile();
this.prevState = isOn;
Platform.notifyBlocksOfNeighbors(te.getWorld(), te.getPos());
Platform.notifyBlocksOfNeighbors(te.getWorld(), te.getPos().offset(this.getSide().getFacing()));
}
}
private void configureWatchers() {
final IFluidStorageChannel channel = AEApi.instance().storage().getStorageChannel(IFluidStorageChannel.class);
if (this.stackWatcher != null) {
this.stackWatcher.reset();
final IAEFluidStack myStack = this.config.getFluidInSlot(0);
try {
if (myStack != null) {
this.getProxy().getStorage().getInventory(channel).removeListener(this);
this.stackWatcher.add(myStack);
} else {
this.getProxy()
.getStorage()
.getInventory(channel)
.addListener(this, this.getProxy().getGrid());
}
final IMEMonitor<IAEFluidStack> inventory = this.getProxy().getStorage().getInventory(channel);
this.updateReportingValue(inventory);
} catch (GridAccessException e) {
// NOP
}
}
}
private void updateReportingValue(final IMEMonitor<IAEFluidStack> monitor) {
final IAEFluidStack myStack = this.config.getFluidInSlot(0);
if (myStack == null) {
if (monitor instanceof NetworkMonitor) {
this.lastReportedValue = ((NetworkMonitor<IAEFluidStack>) monitor).getGridCurrentCount();
}
} else {
final IAEFluidStack r = monitor.getStorageList().findPrecise(myStack);
if (r == null) {
this.lastReportedValue = 0;
} else {
this.lastReportedValue = r.getStackSize();
}
}
this.updateState();
}
private boolean isLevelEmitterOn() {
if (Platform.isClient()) {
return (this.getClientFlags() & FLAG_ON) == FLAG_ON;
}
if (!this.getProxy().isActive()) {
return false;
}
final boolean flipState = this.getConfigManager().getSetting(Settings.REDSTONE_EMITTER) == RedstoneMode.LOW_SIGNAL;
return flipState == (this.reportingValue > this.lastReportedValue);
}
@Override
public AECableType getCableConnectionType(final AEPartLocation dir) {
return AECableType.SMART;
}
@Override
public float getCableConnectionLength(AECableType cable) {
return 16;
}
@Override
public boolean canConnectRedstone() {
return true;
}
@Override
public void getBoxes(final IPartCollisionHelper bch) {
bch.addBox(7, 7, 11, 9, 9, 16);
}
@Override
public void randomDisplayTick(final World world, final BlockPos pos, final Random r) {
if (this.isLevelEmitterOn()) {
final AEPartLocation d = this.getSide();
final double d0 = d.xOffset * 0.45F + (r.nextFloat() - 0.5F) * 0.2D;
final double d1 = d.yOffset * 0.45F + (r.nextFloat() - 0.5F) * 0.2D;
final double d2 = d.zOffset * 0.45F + (r.nextFloat() - 0.5F) * 0.2D;
world.spawnParticle(EnumParticleTypes.REDSTONE, 0.5 + pos.getX() + d0, 0.5 + pos.getY() + d1, 0.5 + pos.getZ() + d2, 0.0D, 0.0D, 0.0D
);
}
}
@Override
public boolean onPartActivate(final EntityPlayer player, final EnumHand hand, final Vec3d pos) {
if (Platform.isServer()) {
Platform.openGUI(player, this.getHost().getTile(), this.getSide(), GuiBridge.GUI_FLUID_LEVEL_EMITTER);
}
return true;
}
@Override
public IPartModel getStaticModels() {
if (this.isActive() && this.isPowered()) {
return this.isLevelEmitterOn() ? MODEL_ON_HAS_CHANNEL : MODEL_OFF_HAS_CHANNEL;
} else if (this.isPowered()) {
return this.isLevelEmitterOn() ? MODEL_ON_ON : MODEL_OFF_ON;
} else {
return this.isLevelEmitterOn() ? MODEL_ON_OFF : MODEL_OFF_OFF;
}
}
public IAEFluidTank getConfig() {
return this.config;
}
@Override
public IFluidHandler getFluidInventoryByName(final String name) {
if (name.equals("config")) {
return this.config;
}
return null;
}
@Override
public void readFromNBT(final NBTTagCompound data) {
super.readFromNBT(data);
this.lastReportedValue = data.getLong("lastReportedValue");
this.reportingValue = data.getLong("reportingValue");
this.prevState = data.getBoolean("prevState");
this.config.readFromNBT(data, "config");
}
@Override
public void writeToNBT(final NBTTagCompound data) {
super.writeToNBT(data);
data.setLong("lastReportedValue", this.lastReportedValue);
data.setLong("reportingValue", this.reportingValue);
data.setBoolean("prevState", this.prevState);
this.config.writeToNBT(data, "config");
}
}