Moving to source sets
This commit is contained in:
@@ -0,0 +1,458 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Random;
|
||||
|
||||
import alexiil.mc.lib.attributes.Simulation;
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.util.crash.CrashReportSection;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraft.world.World;
|
||||
import net.fabricmc.api.Environment;
|
||||
import alexiil.mc.lib.attributes.item.FixedItemInv;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.config.Upgrades;
|
||||
import appeng.api.definitions.IDefinitions;
|
||||
import appeng.api.implementations.IUpgradeableHost;
|
||||
import appeng.api.implementations.items.IMemoryCard;
|
||||
import appeng.api.implementations.items.MemoryCardMessages;
|
||||
import appeng.api.networking.IGridNode;
|
||||
import appeng.api.networking.security.IActionHost;
|
||||
import appeng.api.parts.BusSupport;
|
||||
import appeng.api.parts.IPart;
|
||||
import appeng.api.parts.IPartCollisionHelper;
|
||||
import appeng.api.parts.IPartHost;
|
||||
import appeng.api.parts.PartItemStack;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.api.util.AEColor;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
import appeng.api.util.DimensionalCoord;
|
||||
import appeng.api.util.IConfigManager;
|
||||
import appeng.helpers.ICustomNameObject;
|
||||
import appeng.helpers.IPriorityHost;
|
||||
import appeng.me.helpers.AENetworkProxy;
|
||||
import appeng.me.helpers.IGridProxyable;
|
||||
import appeng.parts.networking.CablePart;
|
||||
import appeng.tile.inventory.AppEngInternalAEInventory;
|
||||
import appeng.util.Platform;
|
||||
import appeng.util.SettingsFrom;
|
||||
|
||||
public abstract class AEBasePart implements IPart, IGridProxyable, IActionHost, IUpgradeableHost, ICustomNameObject {
|
||||
|
||||
private final AENetworkProxy proxy;
|
||||
private final ItemStack is;
|
||||
private BlockEntity tile = null;
|
||||
private IPartHost host = null;
|
||||
private AEPartLocation side = null;
|
||||
|
||||
public AEBasePart(final ItemStack is) {
|
||||
Preconditions.checkNotNull(is);
|
||||
|
||||
this.is = is;
|
||||
this.proxy = new AENetworkProxy(this, "part", is, this instanceof CablePart);
|
||||
this.proxy.setValidSides(EnumSet.noneOf(Direction.class));
|
||||
}
|
||||
|
||||
public IPartHost getHost() {
|
||||
return this.host;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IGridNode getGridNode(final AEPartLocation dir) {
|
||||
return this.proxy.getNode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AECableType getCableConnectionType(final AEPartLocation dir) {
|
||||
return AECableType.GLASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void securityBreak() {
|
||||
if (this.getItemStack().getCount() > 0 && this.getGridNode() != null) {
|
||||
final List<ItemStack> items = new ArrayList<>();
|
||||
items.add(this.is.copy());
|
||||
this.host.removePart(this.side, false);
|
||||
Platform.spawnDrops(this.tile.getWorld(), this.tile.getPos(), items);
|
||||
this.is.setCount(0);
|
||||
}
|
||||
}
|
||||
|
||||
protected AEColor getColor() {
|
||||
if (this.host == null) {
|
||||
return AEColor.TRANSPARENT;
|
||||
}
|
||||
return this.host.getColor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getBoxes(final IPartCollisionHelper bch) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInstalledUpgrades(final Upgrades u) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntity getTile() {
|
||||
return this.tile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AENetworkProxy getProxy() {
|
||||
return this.proxy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DimensionalCoord getLocation() {
|
||||
return new DimensionalCoord(this.tile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void gridChanged() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public IGridNode getActionableNode() {
|
||||
return this.proxy.getNode();
|
||||
}
|
||||
|
||||
public void saveChanges() {
|
||||
this.host.markForSave();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Text getCustomInventoryName() {
|
||||
return this.getItemStack().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasCustomInventoryName() {
|
||||
return this.getItemStack().hasCustomName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEntityCrashInfo(final CrashReportSection section) {
|
||||
section.add("Part Side", this.getSide());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemStack(final PartItemStack type) {
|
||||
if (type == PartItemStack.NETWORK) {
|
||||
final ItemStack copy = this.is.copy();
|
||||
copy.setTag(null);
|
||||
return copy;
|
||||
}
|
||||
return this.is;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSolid() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onneighborUpdate(BlockView w, BlockPos pos, BlockPos neighbor) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canConnectRedstone() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromNBT(final CompoundTag data) {
|
||||
this.proxy.readFromNBT(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToNBT(final CompoundTag data) {
|
||||
this.proxy.writeToNBT(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int isProvidingStrongPower() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int isProvidingWeakPower() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToStream(final PacketByteBuf data) throws IOException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean readFromStream(final PacketByteBuf data) throws IOException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IGridNode getGridNode() {
|
||||
return this.proxy.getNode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEntityCollision(final Entity entity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeFromWorld() {
|
||||
this.proxy.remove();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addToWorld() {
|
||||
this.proxy.onReady();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPartHostInfo(final AEPartLocation side, final IPartHost host, final BlockEntity tile) {
|
||||
this.setSide(side);
|
||||
this.tile = tile;
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IGridNode getExternalFacingNode() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Environment(EnvType.CLIENT)
|
||||
public void randomDisplayTick(final World world, final BlockPos pos, final Random r) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLightLevel() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getDrops(final List<ItemStack> drops, final boolean wrenched) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getCableConnectionLength(AECableType cable) {
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLadder(final LivingEntity entity) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IConfigManager getConfigManager() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FixedItemInv getInventoryByName(final String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* depending on the from, different settings will be accepted, don't call this
|
||||
* with null
|
||||
*
|
||||
* @param from source of settings
|
||||
* @param compound compound of source
|
||||
*/
|
||||
private void uploadSettings(final SettingsFrom from, final CompoundTag compound) {
|
||||
if (compound != null) {
|
||||
final IConfigManager cm = this.getConfigManager();
|
||||
if (cm != null) {
|
||||
cm.readFromNBT(compound);
|
||||
}
|
||||
}
|
||||
|
||||
if (this instanceof IPriorityHost) {
|
||||
final IPriorityHost pHost = (IPriorityHost) this;
|
||||
pHost.setPriority(compound.getInt("priority"));
|
||||
}
|
||||
|
||||
final FixedItemInv inv = this.getInventoryByName("config");
|
||||
if (inv instanceof AppEngInternalAEInventory) {
|
||||
final AppEngInternalAEInventory target = (AppEngInternalAEInventory) inv;
|
||||
final AppEngInternalAEInventory tmp = new AppEngInternalAEInventory(null, target.getSlotCount());
|
||||
tmp.readFromNBT(compound, "config");
|
||||
for (int x = 0; x < tmp.getSlotCount(); x++) {
|
||||
target.forceSetInvStack(x, tmp.getInvStack(x));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* null means nothing to store...
|
||||
*
|
||||
* @param from source of settings
|
||||
*
|
||||
* @return compound of source
|
||||
*/
|
||||
private CompoundTag downloadSettings(final SettingsFrom from) {
|
||||
final CompoundTag output = new CompoundTag();
|
||||
|
||||
final IConfigManager cm = this.getConfigManager();
|
||||
if (cm != null) {
|
||||
cm.writeToNBT(output);
|
||||
}
|
||||
|
||||
if (this instanceof IPriorityHost) {
|
||||
final IPriorityHost pHost = (IPriorityHost) this;
|
||||
output.putInt("priority", pHost.getPriority());
|
||||
}
|
||||
|
||||
final FixedItemInv inv = this.getInventoryByName("config");
|
||||
if (inv instanceof AppEngInternalAEInventory) {
|
||||
((AppEngInternalAEInventory) inv).writeToNBT(output, "config");
|
||||
}
|
||||
|
||||
return output.isEmpty() ? null : output;
|
||||
}
|
||||
|
||||
public boolean useStandardMemoryCard() {
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean useMemoryCard(final PlayerEntity player) {
|
||||
final ItemStack memCardIS = player.inventory.getMainHandStack();
|
||||
|
||||
if (!memCardIS.isEmpty() && this.useStandardMemoryCard() && memCardIS.getItem() instanceof IMemoryCard) {
|
||||
final IMemoryCard memoryCard = (IMemoryCard) memCardIS.getItem();
|
||||
|
||||
ItemStack is = this.getItemStack(PartItemStack.NETWORK);
|
||||
|
||||
// Blocks and parts share the same soul!
|
||||
final IDefinitions definitions = AEApi.instance().definitions();
|
||||
if (definitions.parts().iface().isSameAs(is)) {
|
||||
Optional<ItemStack> iface = definitions.blocks().iface().maybeStack(1);
|
||||
if (iface.isPresent()) {
|
||||
is = iface.get();
|
||||
}
|
||||
}
|
||||
|
||||
final String name = is.getTranslationKey();
|
||||
|
||||
if (player.isInSneakingPose()) {
|
||||
final CompoundTag data = this.downloadSettings(SettingsFrom.MEMORY_CARD);
|
||||
if (data != null) {
|
||||
memoryCard.setMemoryCardContents(memCardIS, name, data);
|
||||
memoryCard.notifyUser(player, MemoryCardMessages.SETTINGS_SAVED);
|
||||
}
|
||||
} else {
|
||||
final String storedName = memoryCard.getSettingsName(memCardIS);
|
||||
final CompoundTag data = memoryCard.getData(memCardIS);
|
||||
if (name.equals(storedName)) {
|
||||
this.uploadSettings(SettingsFrom.MEMORY_CARD, data);
|
||||
memoryCard.notifyUser(player, MemoryCardMessages.SETTINGS_LOADED);
|
||||
} else {
|
||||
memoryCard.notifyUser(player, MemoryCardMessages.INVALID_MACHINE);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean onActivate(final PlayerEntity player, final Hand hand, final Vec3d pos) {
|
||||
if (this.useMemoryCard(player)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return this.onPartActivate(player, hand, pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean onShiftActivate(final PlayerEntity player, final Hand hand, final Vec3d pos) {
|
||||
if (this.useMemoryCard(player)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return this.onPartShiftActivate(player, hand, pos);
|
||||
}
|
||||
|
||||
public boolean onPartActivate(final PlayerEntity player, final Hand hand, final Vec3d pos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean onPartShiftActivate(final PlayerEntity player, final Hand hand, final Vec3d pos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlacement(final PlayerEntity player, final Hand hand, final ItemStack held,
|
||||
final AEPartLocation side) {
|
||||
this.proxy.setOwner(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBePlacedOn(final BusSupport what) {
|
||||
return what == BusSupport.CABLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requireDynamicRender() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public AEPartLocation getSide() {
|
||||
return this.side;
|
||||
}
|
||||
|
||||
private void setSide(final AEPartLocation side) {
|
||||
this.side = side;
|
||||
}
|
||||
|
||||
public ItemStack getItemStack() {
|
||||
return this.is;
|
||||
}
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
|
||||
import appeng.api.implementations.IPowerChannelState;
|
||||
import appeng.api.networking.GridFlags;
|
||||
import appeng.api.networking.events.MENetworkChannelsChanged;
|
||||
import appeng.api.networking.events.MENetworkEventSubscribe;
|
||||
import appeng.api.networking.events.MENetworkPowerStatusChange;
|
||||
import appeng.me.GridAccessException;
|
||||
|
||||
public abstract class BasicStatePart extends AEBasePart implements IPowerChannelState {
|
||||
|
||||
protected static final int POWERED_FLAG = 1;
|
||||
protected static final int CHANNEL_FLAG = 2;
|
||||
|
||||
private int clientFlags = 0; // sent as byte.
|
||||
|
||||
public BasicStatePart(final ItemStack is) {
|
||||
super(is);
|
||||
this.getProxy().setFlags(GridFlags.REQUIRE_CHANNEL);
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void chanRender(final MENetworkChannelsChanged c) {
|
||||
this.getHost().markForUpdate();
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void powerRender(final MENetworkPowerStatusChange c) {
|
||||
this.getHost().markForUpdate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToStream(final PacketByteBuf data) throws IOException {
|
||||
super.writeToStream(data);
|
||||
|
||||
this.setClientFlags(0);
|
||||
|
||||
try {
|
||||
if (this.getProxy().getEnergy().isNetworkPowered()) {
|
||||
this.setClientFlags(this.getClientFlags() | POWERED_FLAG);
|
||||
}
|
||||
|
||||
if (this.getProxy().getNode().meetsChannelRequirements()) {
|
||||
this.setClientFlags(this.getClientFlags() | CHANNEL_FLAG);
|
||||
}
|
||||
|
||||
this.setClientFlags(this.populateFlags(this.getClientFlags()));
|
||||
} catch (final GridAccessException e) {
|
||||
// meh
|
||||
}
|
||||
|
||||
data.writeByte((byte) this.getClientFlags());
|
||||
}
|
||||
|
||||
protected int populateFlags(final int cf) {
|
||||
return cf;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean readFromStream(final PacketByteBuf data) throws IOException {
|
||||
final boolean eh = super.readFromStream(data);
|
||||
|
||||
final int old = this.getClientFlags();
|
||||
this.setClientFlags(data.readByte());
|
||||
|
||||
return eh || old != this.getClientFlags();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPowered() {
|
||||
return (this.getClientFlags() & POWERED_FLAG) == POWERED_FLAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
return (this.getClientFlags() & CHANNEL_FLAG) == CHANNEL_FLAG;
|
||||
}
|
||||
|
||||
public int getClientFlags() {
|
||||
return this.clientFlags;
|
||||
}
|
||||
|
||||
private void setClientFlags(final int clientFlags) {
|
||||
this.clientFlags = clientFlags;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.util.math.Box;
|
||||
import net.minecraft.util.math.Direction;
|
||||
|
||||
import appeng.api.parts.IPartCollisionHelper;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
|
||||
public class BusCollisionHelper implements IPartCollisionHelper {
|
||||
|
||||
private final List<Box> boxes;
|
||||
|
||||
private final Direction x;
|
||||
private final Direction y;
|
||||
private final Direction z;
|
||||
|
||||
private final boolean isVisual;
|
||||
|
||||
public BusCollisionHelper(final List<Box> boxes, final Direction x, final Direction y, final Direction z,
|
||||
final boolean visual) {
|
||||
this.boxes = boxes;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.isVisual = visual;
|
||||
}
|
||||
|
||||
public BusCollisionHelper(final List<Box> boxes, final AEPartLocation s, final boolean visual) {
|
||||
this.boxes = boxes;
|
||||
this.isVisual = visual;
|
||||
|
||||
switch (s) {
|
||||
case DOWN:
|
||||
this.x = Direction.EAST;
|
||||
this.y = Direction.NORTH;
|
||||
this.z = Direction.DOWN;
|
||||
break;
|
||||
case UP:
|
||||
this.x = Direction.EAST;
|
||||
this.y = Direction.SOUTH;
|
||||
this.z = Direction.UP;
|
||||
break;
|
||||
case EAST:
|
||||
this.x = Direction.SOUTH;
|
||||
this.y = Direction.UP;
|
||||
this.z = Direction.EAST;
|
||||
break;
|
||||
case WEST:
|
||||
this.x = Direction.NORTH;
|
||||
this.y = Direction.UP;
|
||||
this.z = Direction.WEST;
|
||||
break;
|
||||
case NORTH:
|
||||
this.x = Direction.WEST;
|
||||
this.y = Direction.UP;
|
||||
this.z = Direction.NORTH;
|
||||
break;
|
||||
case SOUTH:
|
||||
this.x = Direction.EAST;
|
||||
this.y = Direction.UP;
|
||||
this.z = Direction.SOUTH;
|
||||
break;
|
||||
case INTERNAL:
|
||||
default:
|
||||
this.x = Direction.EAST;
|
||||
this.y = Direction.UP;
|
||||
this.z = Direction.SOUTH;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBox(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) {
|
||||
minX /= 16.0;
|
||||
minY /= 16.0;
|
||||
minZ /= 16.0;
|
||||
maxX /= 16.0;
|
||||
maxY /= 16.0;
|
||||
maxZ /= 16.0;
|
||||
|
||||
double aX = minX * this.x.getOffsetX() + minY * this.y.getOffsetX() + minZ * this.z.getOffsetX();
|
||||
double aY = minX * this.x.getOffsetY() + minY * this.y.getOffsetY() + minZ * this.z.getOffsetY();
|
||||
double aZ = minX * this.x.getOffsetZ() + minY * this.y.getOffsetZ() + minZ * this.z.getOffsetZ();
|
||||
|
||||
double bX = maxX * this.x.getOffsetX() + maxY * this.y.getOffsetX() + maxZ * this.z.getOffsetX();
|
||||
double bY = maxX * this.x.getOffsetY() + maxY * this.y.getOffsetY() + maxZ * this.z.getOffsetY();
|
||||
double bZ = maxX * this.x.getOffsetZ() + maxY * this.y.getOffsetZ() + maxZ * this.z.getOffsetZ();
|
||||
|
||||
if (this.x.getOffsetX() + this.y.getOffsetX() + this.z.getOffsetX() < 0) {
|
||||
aX += 1;
|
||||
bX += 1;
|
||||
}
|
||||
|
||||
if (this.x.getOffsetY() + this.y.getOffsetY() + this.z.getOffsetY() < 0) {
|
||||
aY += 1;
|
||||
bY += 1;
|
||||
}
|
||||
|
||||
if (this.x.getOffsetZ() + this.y.getOffsetZ() + this.z.getOffsetZ() < 0) {
|
||||
aZ += 1;
|
||||
bZ += 1;
|
||||
}
|
||||
|
||||
minX = Math.min(aX, bX);
|
||||
minY = Math.min(aY, bY);
|
||||
minZ = Math.min(aZ, bZ);
|
||||
maxX = Math.max(aX, bX);
|
||||
maxY = Math.max(aY, bY);
|
||||
maxZ = Math.max(aZ, bZ);
|
||||
|
||||
this.boxes.add(new Box(minX, minY, minZ, maxX, maxY, maxZ));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Direction getWorldX() {
|
||||
return this.x;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Direction getWorldY() {
|
||||
return this.y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Direction getWorldZ() {
|
||||
return this.z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBBCollision() {
|
||||
return !this.isVisual;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2015, 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.parts;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import appeng.api.implementations.parts.ICablePart;
|
||||
import appeng.api.parts.IFacadePart;
|
||||
import appeng.api.parts.IPart;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
|
||||
/**
|
||||
* Thin data storage to optimize memory usage for cables.
|
||||
*/
|
||||
public class CableBusStorage {
|
||||
|
||||
private ICablePart center;
|
||||
private IPart[] sides;
|
||||
private IFacadePart[] facades;
|
||||
|
||||
protected ICablePart getCenter() {
|
||||
return this.center;
|
||||
}
|
||||
|
||||
protected void setCenter(final ICablePart center) {
|
||||
this.center = center;
|
||||
}
|
||||
|
||||
protected IPart getSide(final AEPartLocation side) {
|
||||
final int x = side.ordinal();
|
||||
if (this.sides != null && this.sides.length > x) {
|
||||
return this.sides[x];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void setSide(final AEPartLocation side, final IPart part) {
|
||||
final int x = side.ordinal();
|
||||
|
||||
if (this.sides != null && this.sides.length > x && part == null) {
|
||||
this.sides[x] = null;
|
||||
this.sides = this.shrink(this.sides, true);
|
||||
} else if (part != null) {
|
||||
this.sides = this.grow(this.sides, x, true);
|
||||
this.sides[x] = part;
|
||||
}
|
||||
}
|
||||
|
||||
private <T> T[] shrink(final T[] in, final boolean parts) {
|
||||
int newSize = -1;
|
||||
for (int x = 0; x < in.length; x++) {
|
||||
if (in[x] != null) {
|
||||
newSize = x;
|
||||
}
|
||||
}
|
||||
|
||||
if (newSize == -1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
newSize++;
|
||||
if (newSize == in.length) {
|
||||
return in;
|
||||
}
|
||||
|
||||
final T[] newArray = (T[]) (parts ? new IPart[newSize] : new IFacadePart[newSize]);
|
||||
System.arraycopy(in, 0, newArray, 0, newSize);
|
||||
|
||||
return newArray;
|
||||
}
|
||||
|
||||
private <T> T[] grow(final T[] in, final int newValue, final boolean parts) {
|
||||
if (in != null && in.length > newValue) {
|
||||
return in;
|
||||
}
|
||||
|
||||
final int newSize = newValue + 1;
|
||||
|
||||
final T[] newArray = (T[]) (parts ? new IPart[newSize] : new IFacadePart[newSize]);
|
||||
if (in != null) {
|
||||
System.arraycopy(in, 0, newArray, 0, in.length);
|
||||
}
|
||||
|
||||
return newArray;
|
||||
}
|
||||
|
||||
public IFacadePart getFacade(final int x) {
|
||||
if (this.facades != null && this.facades.length > x) {
|
||||
return this.facades[x];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setFacade(final int x, @Nullable final IFacadePart facade) {
|
||||
if (this.facades != null && this.facades.length > x && facade == null) {
|
||||
this.facades[x] = null;
|
||||
this.facades = this.shrink(this.facades, false);
|
||||
} else {
|
||||
this.facades = this.grow(this.facades, x, false);
|
||||
this.facades[x] = facade;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.Random;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraft.world.World;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
import appeng.api.parts.SelectedPart;
|
||||
import appeng.api.util.AEColor;
|
||||
import appeng.client.render.cablebus.CableBusRenderState;
|
||||
|
||||
public interface ICableBusContainer {
|
||||
|
||||
int isProvidingStrongPower(Direction opposite);
|
||||
|
||||
int isProvidingWeakPower(Direction opposite);
|
||||
|
||||
boolean canConnectRedstone(EnumSet<Direction> of);
|
||||
|
||||
void onEntityCollision(Entity e);
|
||||
|
||||
boolean activate(PlayerEntity player, Hand hand, Vec3d vecFromPool);
|
||||
|
||||
boolean clicked(PlayerEntity player, Hand hand, Vec3d hitVec);
|
||||
|
||||
void onneighborUpdate(BlockView w, BlockPos pos, BlockPos neighbor);
|
||||
|
||||
boolean isEmpty();
|
||||
|
||||
SelectedPart selectPart(Vec3d v3);
|
||||
|
||||
boolean recolourBlock(Direction side, AEColor colour, PlayerEntity who);
|
||||
|
||||
boolean isLadder(LivingEntity entity);
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
void randomDisplayTick(World world, BlockPos pos, Random r);
|
||||
|
||||
int getLightValue();
|
||||
|
||||
CableBusRenderState getRenderState();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.Random;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import appeng.api.parts.SelectedPart;
|
||||
import appeng.api.util.AEColor;
|
||||
import appeng.client.render.cablebus.CableBusRenderState;
|
||||
|
||||
public class NullCableBusContainer implements ICableBusContainer {
|
||||
|
||||
@Override
|
||||
public int isProvidingStrongPower(final Direction opposite) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int isProvidingWeakPower(final Direction opposite) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canConnectRedstone(final EnumSet<Direction> of) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEntityCollision(final Entity e) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean activate(final PlayerEntity player, final Hand hand, final Vec3d vecFromPool) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onneighborUpdate(BlockView w, BlockPos pos, BlockPos neighbor) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SelectedPart selectPart(final Vec3d v3) {
|
||||
return new SelectedPart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean recolourBlock(final Direction side, final AEColor colour, final PlayerEntity who) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLadder(final LivingEntity entity) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void randomDisplayTick(final World world, final BlockPos pos, final Random r) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLightValue() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CableBusRenderState getRenderState() {
|
||||
return new CableBusRenderState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clicked(PlayerEntity player, Hand hand, Vec3d hitVec) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import appeng.api.parts.IPartModel;
|
||||
|
||||
public class PartModel implements IPartModel {
|
||||
private final boolean isSolid;
|
||||
|
||||
private final List<Identifier> resources;
|
||||
|
||||
public PartModel(Identifier resource) {
|
||||
this(true, resource);
|
||||
}
|
||||
|
||||
public PartModel(Identifier... resources) {
|
||||
this(true, resources);
|
||||
}
|
||||
|
||||
public PartModel(boolean isSolid, Identifier resource) {
|
||||
this(isSolid, ImmutableList.of(resource));
|
||||
}
|
||||
|
||||
public PartModel(boolean isSolid, Identifier... resources) {
|
||||
this(isSolid, ImmutableList.copyOf(resources));
|
||||
}
|
||||
|
||||
public PartModel(List<Identifier> resources) {
|
||||
this(true, resources);
|
||||
}
|
||||
|
||||
public PartModel(boolean isSolid, List<Identifier> resources) {
|
||||
this.isSolid = isSolid;
|
||||
this.resources = resources;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requireCableConnection() {
|
||||
return this.isSolid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Identifier> getModels() {
|
||||
return this.resources;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,417 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2015, 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.parts;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.definitions.IBlockDefinition;
|
||||
import appeng.api.definitions.IItems;
|
||||
import appeng.api.parts.*;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
import appeng.api.util.DimensionalCoord;
|
||||
import appeng.core.AppEng;
|
||||
import appeng.core.sync.network.NetworkHandler;
|
||||
import appeng.core.sync.packets.PartPlacementPacket;
|
||||
import appeng.facade.IFacadeItem;
|
||||
import appeng.util.LookDirection;
|
||||
import appeng.util.Platform;
|
||||
import net.fabricmc.fabric.api.event.player.UseBlockCallback;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.*;
|
||||
import net.minecraft.sound.BlockSoundGroup;
|
||||
import net.minecraft.sound.SoundCategory;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.util.hit.HitResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.RayTraceContext;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class PartPlacement {
|
||||
|
||||
private static float eyeHeight = 0.0f;
|
||||
private static final ThreadLocal<Object> placing = new ThreadLocal<>();
|
||||
private static boolean wasCanceled = false;
|
||||
|
||||
static {
|
||||
|
||||
UseBlockCallback.EVENT.register(PartPlacement::onPlayerUseBlock);
|
||||
|
||||
}
|
||||
|
||||
public static ActionResult place(final ItemStack held, final BlockPos pos, Direction side,
|
||||
final PlayerEntity player, final Hand hand, final World world, PlaceType pass, final int depth) {
|
||||
if (depth > 3) {
|
||||
return ActionResult.FAIL;
|
||||
}
|
||||
|
||||
// FIXME: This was changed alot.
|
||||
final LookDirection dir = Platform.getPlayerRay(player);
|
||||
RayTraceContext rtc = new RayTraceContext(dir.getA(), dir.getB(), RayTraceContext.ShapeType.OUTLINE,
|
||||
RayTraceContext.FluidHandling.NONE, player);
|
||||
final BlockHitResult mop = world.rayTrace(rtc);
|
||||
ItemPlacementContext useContext = new ItemPlacementContext(new ItemUsageContext(player, hand, mop));
|
||||
|
||||
if (!held.isEmpty() && Platform.isWrench(player, held, pos) && player.isInSneakingPose()) {
|
||||
if (!Platform.hasPermissions(new DimensionalCoord(world, pos), player)) {
|
||||
return ActionResult.FAIL;
|
||||
}
|
||||
|
||||
final BlockEntity tile = world.getBlockEntity(pos);
|
||||
IPartHost host = null;
|
||||
|
||||
if (tile instanceof IPartHost) {
|
||||
host = (IPartHost) tile;
|
||||
}
|
||||
|
||||
if (host != null) {
|
||||
if (!world.isClient) {
|
||||
if (mop.getType() == HitResult.Type.BLOCK) {
|
||||
final List<ItemStack> is = new ArrayList<>();
|
||||
final SelectedPart sp = selectPart(player, host,
|
||||
mop.getPos().add(-mop.getPos().getX(), -mop.getPos().getY(), -mop.getPos().getZ()));
|
||||
|
||||
if (sp.part != null) {
|
||||
is.add(sp.part.getItemStack(PartItemStack.WRENCH));
|
||||
sp.part.getDrops(is, true);
|
||||
host.removePart(sp.side, false);
|
||||
}
|
||||
|
||||
if (sp.facade != null) {
|
||||
is.add(sp.facade.getItemStack());
|
||||
host.getFacadeContainer().removeFacade(host, sp.side);
|
||||
Platform.notifyBlocksOfNeighbors(world, pos);
|
||||
}
|
||||
|
||||
if (host.isEmpty()) {
|
||||
host.cleanup();
|
||||
}
|
||||
|
||||
if (!is.isEmpty()) {
|
||||
Platform.spawnDrops(world, pos, is);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
player.swingHand(hand);
|
||||
NetworkHandler.instance()
|
||||
.sendToServer(new PartPlacementPacket(pos, side, getEyeOffset(player), hand));
|
||||
}
|
||||
return ActionResult.SUCCESS;
|
||||
}
|
||||
|
||||
return ActionResult.FAIL;
|
||||
}
|
||||
|
||||
BlockEntity tile = world.getBlockEntity(pos);
|
||||
IPartHost host = null;
|
||||
|
||||
if (tile instanceof IPartHost) {
|
||||
host = (IPartHost) tile;
|
||||
}
|
||||
|
||||
if (!held.isEmpty()) {
|
||||
final IFacadePart fp = isFacade(held, AEPartLocation.fromFacing(side));
|
||||
if (fp != null) {
|
||||
if (host != null) {
|
||||
if (!world.isClient) {
|
||||
if (host.getPart(AEPartLocation.INTERNAL) == null) {
|
||||
return ActionResult.FAIL;
|
||||
}
|
||||
|
||||
if (host.canAddPart(held, AEPartLocation.fromFacing(side))) {
|
||||
if (host.getFacadeContainer().addFacade(fp)) {
|
||||
host.markForSave();
|
||||
host.markForUpdate();
|
||||
if (!player.isCreative()) {
|
||||
held.increment(-1);
|
||||
if (held.getCount() == 0) {
|
||||
player.inventory.main.set(player.inventory.selectedSlot,
|
||||
ItemStack.EMPTY);
|
||||
}
|
||||
}
|
||||
return ActionResult.CONSUME;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
player.swingHand(hand);
|
||||
NetworkHandler.instance()
|
||||
.sendToServer(new PartPlacementPacket(pos, side, getEyeOffset(player), hand));
|
||||
return ActionResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
return ActionResult.FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
if (held.isEmpty()) {
|
||||
if (host != null && player.isInSneakingPose() && world.isAir(pos)) {
|
||||
if (mop.getType() == HitResult.Type.BLOCK) {
|
||||
Vec3d hitVec = mop.getPos().add(-mop.getPos().getX(), -mop.getPos().getY(),
|
||||
-mop.getPos().getZ());
|
||||
final SelectedPart sPart = selectPart(player, host, hitVec);
|
||||
if (sPart != null && sPart.part != null) {
|
||||
if (sPart.part.onShiftActivate(player, hand, hitVec)) {
|
||||
if (world.isClient) {
|
||||
NetworkHandler.instance()
|
||||
.sendToServer(new PartPlacementPacket(pos, side, getEyeOffset(player), hand));
|
||||
}
|
||||
return ActionResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (held.isEmpty() || !(held.getItem() instanceof IPartItem)) {
|
||||
return ActionResult.PASS;
|
||||
}
|
||||
|
||||
BlockPos te_pos = pos;
|
||||
|
||||
final IBlockDefinition multiPart = AEApi.instance().definitions().blocks().multiPart();
|
||||
if (host == null && pass == PlaceType.PLACE_ITEM) {
|
||||
Direction offset = null;
|
||||
|
||||
BlockState blockState = world.getBlockState(pos);
|
||||
// FIXME isReplacable on the block state allows for more control, but requires
|
||||
// an item use context
|
||||
if (!blockState.isAir() && !blockState.canReplace(useContext)) {
|
||||
offset = side;
|
||||
if (Platform.isServer()) {
|
||||
side = side.getOpposite();
|
||||
}
|
||||
}
|
||||
|
||||
te_pos = offset == null ? pos : pos.offset(offset);
|
||||
|
||||
tile = world.getBlockEntity(te_pos);
|
||||
if (tile instanceof IPartHost) {
|
||||
host = (IPartHost) tile;
|
||||
}
|
||||
|
||||
final Optional<ItemStack> maybeMultiPartStack = multiPart.maybeStack(1);
|
||||
final Optional<Block> maybeMultiPartBlock = multiPart.maybeBlock();
|
||||
final Optional<BlockItem> maybeMultiPartBlockItem = multiPart.maybeBlockItem();
|
||||
|
||||
final boolean hostIsNotPresent = host == null;
|
||||
final boolean multiPartPresent = maybeMultiPartBlock.isPresent() && maybeMultiPartStack.isPresent()
|
||||
&& maybeMultiPartBlockItem.isPresent();
|
||||
BlockState multiPartBlockState = maybeMultiPartBlock.get().getDefaultState();
|
||||
final boolean canMultiPartBePlaced = multiPartBlockState.canPlaceAt(world, te_pos);
|
||||
|
||||
// We cannot override the item stack of normal use context, so we use this hack
|
||||
ItemPlacementContext mpUseCtx = new ItemPlacementContext(
|
||||
new AutomaticItemPlacementContext(world, te_pos, side, maybeMultiPartStack.get(), side));
|
||||
|
||||
// FIXME: This is super-fishy and all needs to be re-checked. what does this
|
||||
// even do???
|
||||
if (hostIsNotPresent && multiPartPresent && canMultiPartBePlaced
|
||||
&& maybeMultiPartBlockItem.get().place(mpUseCtx) == ActionResult.SUCCESS) {
|
||||
if (!world.isClient) {
|
||||
tile = world.getBlockEntity(te_pos);
|
||||
|
||||
if (tile instanceof IPartHost) {
|
||||
host = (IPartHost) tile;
|
||||
}
|
||||
|
||||
pass = PlaceType.INTERACT_SECOND_PASS;
|
||||
} else {
|
||||
player.swingHand(hand);
|
||||
NetworkHandler.instance()
|
||||
.sendToServer(new PartPlacementPacket(pos, side, getEyeOffset(player), hand));
|
||||
return ActionResult.SUCCESS;
|
||||
}
|
||||
} else if (host != null && !host.canAddPart(held, AEPartLocation.fromFacing(side))) {
|
||||
return ActionResult.FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
if (host == null) {
|
||||
return ActionResult.PASS;
|
||||
}
|
||||
|
||||
if (!host.canAddPart(held, AEPartLocation.fromFacing(side))) {
|
||||
if (pass == PlaceType.INTERACT_FIRST_PASS || pass == PlaceType.PLACE_ITEM) {
|
||||
te_pos = pos.offset(side);
|
||||
|
||||
final BlockState blkState = world.getBlockState(te_pos);
|
||||
|
||||
// FIXME: this is always true (host was de-referenced above)
|
||||
if (blkState.isAir() || blkState.canReplace(useContext) || host != null) {
|
||||
return place(held, te_pos, side.getOpposite(), player, hand, world,
|
||||
pass == PlaceType.INTERACT_FIRST_PASS ? PlaceType.INTERACT_SECOND_PASS
|
||||
: PlaceType.PLACE_ITEM,
|
||||
depth + 1);
|
||||
}
|
||||
}
|
||||
return ActionResult.PASS;
|
||||
}
|
||||
|
||||
if (!world.isClient) {
|
||||
if (mop.getType() != HitResult.Type.MISS) {
|
||||
final SelectedPart sp = selectPart(player, host,
|
||||
mop.getPos().add(-mop.getPos().getX(), -mop.getPos().getY(), -mop.getPos().getZ()));
|
||||
|
||||
if (sp.part != null) {
|
||||
if (!player.isInSneakingPose() && sp.part.onActivate(player, hand, mop.getPos())) {
|
||||
return ActionResult.FAIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final DimensionalCoord dc = host.getLocation();
|
||||
if (!Platform.hasPermissions(dc, player)) {
|
||||
return ActionResult.FAIL;
|
||||
}
|
||||
|
||||
final AEPartLocation mySide = host.addPart(held, AEPartLocation.fromFacing(side), player, hand);
|
||||
if (mySide != null) {
|
||||
multiPart.maybeBlock().ifPresent(multiPartBlock -> {
|
||||
BlockState blockState = world.getBlockState(pos);
|
||||
final BlockSoundGroup ss = multiPartBlock.getSoundGroup(blockState);
|
||||
|
||||
world.playSound(null, pos, ss.getPlaceSound(), SoundCategory.BLOCKS, (ss.getVolume() + 1.0F) / 2.0F,
|
||||
ss.getPitch() * 0.8F);
|
||||
});
|
||||
|
||||
if (!player.isCreative()) {
|
||||
held.increment(-1);
|
||||
if (held.getCount() == 0) {
|
||||
player.setStackInHand(hand, ItemStack.EMPTY);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
player.swingHand(hand);
|
||||
}
|
||||
return ActionResult.SUCCESS;
|
||||
}
|
||||
|
||||
private static float getEyeOffset(final PlayerEntity p) {
|
||||
if (p.world.isClient) {
|
||||
return Platform.getEyeOffset(p);
|
||||
}
|
||||
|
||||
return getEyeHeight();
|
||||
}
|
||||
|
||||
private static SelectedPart selectPart(final PlayerEntity player, final IPartHost host, final Vec3d pos) {
|
||||
AppEng.instance().updateRenderMode(player);
|
||||
final SelectedPart sp = host.selectPart(pos);
|
||||
AppEng.instance().updateRenderMode(null);
|
||||
|
||||
return sp;
|
||||
}
|
||||
|
||||
public static IFacadePart isFacade(final ItemStack held, final AEPartLocation side) {
|
||||
if (held.getItem() instanceof IFacadeItem) {
|
||||
return ((IFacadeItem) held.getItem()).createPartFromItemStack(held, side);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void playerInteract(final MinecraftClient client) {
|
||||
wasCanceled = false;
|
||||
}
|
||||
|
||||
private static ActionResult onPlayerUseBlock(PlayerEntity player, World world, Hand hand, BlockHitResult hit) {
|
||||
|
||||
if (world.isClient || player.isSpectator()) {
|
||||
return ActionResult.PASS;
|
||||
}
|
||||
|
||||
if (placing.get() != null) {
|
||||
return ActionResult.PASS;
|
||||
}
|
||||
|
||||
placing.set(true);
|
||||
|
||||
final ItemStack held = player.getStackInHand(hand);
|
||||
if (place(held, hit.getBlockPos(), hit.getSide(), player, hand,
|
||||
player.world, PlaceType.INTERACT_FIRST_PASS, 0) == ActionResult.SUCCESS) {
|
||||
return ActionResult.SUCCESS;
|
||||
}
|
||||
|
||||
placing.set(null);
|
||||
return ActionResult.PASS;
|
||||
}
|
||||
|
||||
// FIXME FABRIC public static void playerInteract(final PlayerInteractEvent event) {
|
||||
// FIXME FABRIC // Only handle the main hand event
|
||||
// FIXME FABRIC if (event.getHand() != Hand.MAIN_HAND) {
|
||||
// FIXME FABRIC return;
|
||||
// FIXME FABRIC }
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC if (event instanceof PlayerInteractEvent.RightClickEmpty && event.getPlayer().world.isClient) {
|
||||
// FIXME FABRIC // re-check to see if this event was already channeled, cause these two events
|
||||
// FIXME FABRIC // are really stupid...
|
||||
// FIXME FABRIC final HitResult mop = Platform.rayTrace(event.getPlayer(), true, false);
|
||||
// FIXME FABRIC final MinecraftClient mc = MinecraftClient.getInstance();
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC final float f = 1.0F;
|
||||
// FIXME FABRIC final double d0 = mc.playerController.getBlockReachDistance();
|
||||
// FIXME FABRIC final Vec3d vec3 = mc.getRenderViewEntity().getEyePosition(f);
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC if (mop instanceof BlockHitResult && mop.getPos().distanceTo(vec3) < d0) {
|
||||
// FIXME FABRIC BlockHitResult brtr = (BlockHitResult) mop;
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC final World w = event.getEntity().world;
|
||||
// FIXME FABRIC final BlockEntity te = w.getBlockEntity(brtr.getPos());
|
||||
// FIXME FABRIC if (te instanceof IPartHost && this.wasCanceled) {
|
||||
// FIXME FABRIC event.setCanceled(true);
|
||||
// FIXME FABRIC }
|
||||
// FIXME FABRIC } else {
|
||||
// FIXME FABRIC final ItemStack held = event.getPlayer().getStackInHand(event.getHand());
|
||||
// FIXME FABRIC final IItems items = AEApi.instance().definitions().items();
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC boolean supportedItem = items.memoryCard().isSameAs(held);
|
||||
// FIXME FABRIC supportedItem |= items.colorApplicator().isSameAs(held);
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC if (event.getPlayer().isInSneakingPose() && !held.isEmpty() && supportedItem) {
|
||||
// FIXME FABRIC NetworkHandler.instance().sendToServer(new ClickPacket(event.getHand()));
|
||||
// FIXME FABRIC }
|
||||
// FIXME FABRIC }
|
||||
// FIXME FABRIC } else if (event instanceof PlayerInteractEvent.RightClickBlock && !event.getPlayer().world.isClient) {
|
||||
// FIXME FABRIC
|
||||
// FIXME FABRIC }
|
||||
// FIXME FABRIC }
|
||||
|
||||
private static float getEyeHeight() {
|
||||
return eyeHeight;
|
||||
}
|
||||
|
||||
public static void setEyeHeight(final float eyeHeight) {
|
||||
PartPlacement.eyeHeight = eyeHeight;
|
||||
}
|
||||
|
||||
public enum PlaceType {
|
||||
PLACE_ITEM, INTERACT_FIRST_PASS, INTERACT_SECOND_PASS
|
||||
}
|
||||
}
|
||||
@@ -1,234 +0,0 @@
|
||||
|
||||
package appeng.parts.automation;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockView;
|
||||
|
||||
import appeng.api.config.Actionable;
|
||||
import appeng.api.config.Settings;
|
||||
import appeng.api.networking.security.IActionSource;
|
||||
import appeng.api.parts.IPart;
|
||||
import appeng.api.parts.IPartCollisionHelper;
|
||||
import appeng.api.parts.IPartHost;
|
||||
import appeng.api.storage.IMEInventory;
|
||||
import appeng.api.storage.cells.ICellContainer;
|
||||
import appeng.api.storage.cells.ICellInventory;
|
||||
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.helpers.IPriorityHost;
|
||||
|
||||
public abstract class AbstractFormationPlanePart<T extends IAEStack<T>> extends UpgradeablePart
|
||||
implements ICellContainer, IPriorityHost, IMEInventory<T> {
|
||||
|
||||
private boolean wasActive = false;
|
||||
private int priority = 0;
|
||||
protected boolean blocked = false;
|
||||
|
||||
public AbstractFormationPlanePart(ItemStack is) {
|
||||
super(is);
|
||||
}
|
||||
|
||||
protected abstract void updateHandler();
|
||||
|
||||
@Override
|
||||
protected int getUpgradeSlots() {
|
||||
return 5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void upgradesChanged() {
|
||||
this.updateHandler();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSetting(final IConfigManager manager, final Settings settingName, final Enum<?> newValue) {
|
||||
this.updateHandler();
|
||||
this.getHost().markForSave();
|
||||
}
|
||||
|
||||
public void stateChanged() {
|
||||
final boolean currentActive = this.getProxy().isActive();
|
||||
if (this.wasActive != currentActive) {
|
||||
this.wasActive = currentActive;
|
||||
this.updateHandler();
|
||||
this.getHost().markForUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getBoxes(final IPartCollisionHelper bch) {
|
||||
int minX = 1;
|
||||
int minY = 1;
|
||||
int maxX = 15;
|
||||
int maxY = 15;
|
||||
|
||||
final IPartHost host = this.getHost();
|
||||
if (host != null) {
|
||||
final BlockEntity te = host.getTile();
|
||||
|
||||
final BlockPos pos = te.getPos();
|
||||
|
||||
final Direction e = bch.getWorldX();
|
||||
final Direction u = bch.getWorldY();
|
||||
|
||||
if (this.isTransitionPlane(te.getWorld().getBlockEntity(pos.offset(e.getOpposite())), this.getSide())) {
|
||||
minX = 0;
|
||||
}
|
||||
|
||||
if (this.isTransitionPlane(te.getWorld().getBlockEntity(pos.offset(e)), this.getSide())) {
|
||||
maxX = 16;
|
||||
}
|
||||
|
||||
if (this.isTransitionPlane(te.getWorld().getBlockEntity(pos.offset(u.getOpposite())), this.getSide())) {
|
||||
minY = 0;
|
||||
}
|
||||
|
||||
if (this.isTransitionPlane(te.getWorld().getBlockEntity(pos.offset(u)), this.getSide())) {
|
||||
maxY = 16;
|
||||
}
|
||||
}
|
||||
|
||||
bch.addBox(5, 5, 14, 11, 11, 15);
|
||||
bch.addBox(minX, minY, 15, maxX, maxY, 16);
|
||||
}
|
||||
|
||||
public PlaneConnections getConnections() {
|
||||
|
||||
final Direction facingRight, facingUp;
|
||||
AEPartLocation location = this.getSide();
|
||||
switch (location) {
|
||||
case UP:
|
||||
facingRight = Direction.EAST;
|
||||
facingUp = Direction.NORTH;
|
||||
break;
|
||||
case DOWN:
|
||||
facingRight = Direction.WEST;
|
||||
facingUp = Direction.NORTH;
|
||||
break;
|
||||
case NORTH:
|
||||
facingRight = Direction.WEST;
|
||||
facingUp = Direction.UP;
|
||||
break;
|
||||
case SOUTH:
|
||||
facingRight = Direction.EAST;
|
||||
facingUp = Direction.UP;
|
||||
break;
|
||||
case WEST:
|
||||
facingRight = Direction.SOUTH;
|
||||
facingUp = Direction.UP;
|
||||
break;
|
||||
case EAST:
|
||||
facingRight = Direction.NORTH;
|
||||
facingUp = Direction.UP;
|
||||
break;
|
||||
default:
|
||||
case INTERNAL:
|
||||
return PlaneConnections.of(false, false, false, false);
|
||||
}
|
||||
|
||||
boolean left = false, right = false, down = false, up = false;
|
||||
|
||||
final IPartHost host = this.getHost();
|
||||
if (host != null) {
|
||||
final BlockEntity te = host.getTile();
|
||||
|
||||
final BlockPos pos = te.getPos();
|
||||
|
||||
if (this.isTransitionPlane(te.getWorld().getBlockEntity(pos.offset(facingRight.getOpposite())),
|
||||
this.getSide())) {
|
||||
left = true;
|
||||
}
|
||||
|
||||
if (this.isTransitionPlane(te.getWorld().getBlockEntity(pos.offset(facingRight)), this.getSide())) {
|
||||
right = true;
|
||||
}
|
||||
|
||||
if (this.isTransitionPlane(te.getWorld().getBlockEntity(pos.offset(facingUp.getOpposite())),
|
||||
this.getSide())) {
|
||||
down = true;
|
||||
}
|
||||
|
||||
if (this.isTransitionPlane(te.getWorld().getBlockEntity(pos.offset(facingUp)), this.getSide())) {
|
||||
up = true;
|
||||
}
|
||||
}
|
||||
|
||||
return PlaneConnections.of(up, right, down, left);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onneighborUpdate(BlockView w, BlockPos pos, BlockPos neighbor) {
|
||||
if (pos.offset(this.getSide().getFacing()).equals(neighbor)) {
|
||||
final BlockEntity te = this.getHost().getTile();
|
||||
final AEPartLocation side = this.getSide();
|
||||
|
||||
final BlockPos tePos = te.getPos().offset(side.getFacing());
|
||||
|
||||
this.blocked = !w.getBlockState(tePos).getMaterial().isReplaceable();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getCableConnectionLength(AECableType cable) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
protected boolean isTransitionPlane(final BlockEntity blockTileEntity, final AEPartLocation side) {
|
||||
if (blockTileEntity instanceof IPartHost) {
|
||||
final IPart p = ((IPartHost) blockTileEntity).getPart(side);
|
||||
return p != null && this.getClass() == p.getClass();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T extractItems(final T request, final Actionable mode, final IActionSource src) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IItemList<T> getAvailableItems(final IItemList<T> out) {
|
||||
return out;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromNBT(final CompoundTag data) {
|
||||
super.readFromNBT(data);
|
||||
this.priority = data.getInt("priority");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToNBT(final CompoundTag data) {
|
||||
super.writeToNBT(data);
|
||||
data.putInt("priority", this.getPriority());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return this.priority;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPriority(final int newValue) {
|
||||
this.priority = newValue;
|
||||
this.getHost().markForSave();
|
||||
this.updateHandler();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void blinkCell(final int slot) {
|
||||
// :P
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveChanges(final ICellInventory<?> cell) {
|
||||
// nope!
|
||||
}
|
||||
}
|
||||
@@ -1,632 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.automation;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import appeng.util.FakePlayer;
|
||||
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Material;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.ItemEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.tag.Tag;
|
||||
import net.minecraft.tag.BlockTags;
|
||||
import net.minecraft.tag.ItemTags;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.Box;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
|
||||
import net.minecraftforge.common.util.FakePlayerFactory;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.config.Actionable;
|
||||
import appeng.api.config.PowerMultiplier;
|
||||
import appeng.api.networking.IGridNode;
|
||||
import appeng.api.networking.energy.IEnergyGrid;
|
||||
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.IStorageGrid;
|
||||
import appeng.api.networking.ticking.IGridTickable;
|
||||
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.IPartHost;
|
||||
import appeng.api.parts.IPartModel;
|
||||
import appeng.api.storage.channels.IItemStorageChannel;
|
||||
import appeng.api.storage.data.IAEItemStack;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
import appeng.core.AppEng;
|
||||
import appeng.core.settings.TickRates;
|
||||
import appeng.core.sync.packets.BlockTransitionEffectPacket;
|
||||
import appeng.core.sync.packets.ItemTransitionEffectPacket;
|
||||
import appeng.hooks.TickHandler;
|
||||
import appeng.items.parts.PartModels;
|
||||
import appeng.me.GridAccessException;
|
||||
import appeng.me.helpers.MachineSource;
|
||||
import appeng.parts.BasicStatePart;
|
||||
import appeng.util.IWorldCallable;
|
||||
import appeng.util.Platform;
|
||||
import appeng.util.item.AEItemStack;
|
||||
|
||||
public class AnnihilationPlanePart extends BasicStatePart implements IGridTickable, IWorldCallable<TickRateModulation> {
|
||||
|
||||
public static final Identifier TAG_BLACKLIST = new Identifier(AppEng.MOD_ID,
|
||||
"blacklisted/annihilation_plane");
|
||||
|
||||
private static final PlaneModels MODELS = new PlaneModels("part/annihilation_plane", "part/annihilation_plane_on");
|
||||
|
||||
@PartModels
|
||||
public static List<IPartModel> getModels() {
|
||||
return MODELS.getModels();
|
||||
}
|
||||
|
||||
private final IActionSource mySrc = new MachineSource(this);
|
||||
private boolean isAccepting = true;
|
||||
private boolean breaking = false;
|
||||
|
||||
public AnnihilationPlanePart(final ItemStack is) {
|
||||
super(is);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickRateModulation call(final World world) throws Exception {
|
||||
this.breaking = false;
|
||||
return this.breakBlock(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getBoxes(final IPartCollisionHelper bch) {
|
||||
int minX = 1;
|
||||
int minY = 1;
|
||||
int maxX = 15;
|
||||
int maxY = 15;
|
||||
|
||||
final IPartHost host = this.getHost();
|
||||
if (host != null) {
|
||||
final BlockEntity te = host.getTile();
|
||||
|
||||
final BlockPos pos = te.getPos();
|
||||
|
||||
final Direction e = bch.getWorldX();
|
||||
final Direction u = bch.getWorldY();
|
||||
|
||||
if (this.isAnnihilationPlane(te.getWorld().getBlockEntity(pos.offset(e.getOpposite())), this.getSide())) {
|
||||
minX = 0;
|
||||
}
|
||||
|
||||
if (this.isAnnihilationPlane(te.getWorld().getBlockEntity(pos.offset(e)), this.getSide())) {
|
||||
maxX = 16;
|
||||
}
|
||||
|
||||
if (this.isAnnihilationPlane(te.getWorld().getBlockEntity(pos.offset(u.getOpposite())), this.getSide())) {
|
||||
minY = 0;
|
||||
}
|
||||
|
||||
if (this.isAnnihilationPlane(te.getWorld().getBlockEntity(pos.offset(e)), this.getSide())) {
|
||||
maxY = 16;
|
||||
}
|
||||
}
|
||||
|
||||
bch.addBox(5, 5, 14, 11, 11, 15);
|
||||
// The smaller collision hitbox here is needed to allow for the entity collision
|
||||
// event
|
||||
bch.addBox(minX, minY, 15, maxX, maxY, bch.isBBCollision() ? 15 : 16);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return An object describing which adjacent planes this plane connects to
|
||||
* visually.
|
||||
*/
|
||||
public PlaneConnections getConnections() {
|
||||
|
||||
final Direction facingRight, facingUp;
|
||||
AEPartLocation location = this.getSide();
|
||||
switch (location) {
|
||||
case UP:
|
||||
facingRight = Direction.EAST;
|
||||
facingUp = Direction.NORTH;
|
||||
break;
|
||||
case DOWN:
|
||||
facingRight = Direction.WEST;
|
||||
facingUp = Direction.NORTH;
|
||||
break;
|
||||
case NORTH:
|
||||
facingRight = Direction.WEST;
|
||||
facingUp = Direction.UP;
|
||||
break;
|
||||
case SOUTH:
|
||||
facingRight = Direction.EAST;
|
||||
facingUp = Direction.UP;
|
||||
break;
|
||||
case WEST:
|
||||
facingRight = Direction.SOUTH;
|
||||
facingUp = Direction.UP;
|
||||
break;
|
||||
case EAST:
|
||||
facingRight = Direction.NORTH;
|
||||
facingUp = Direction.UP;
|
||||
break;
|
||||
default:
|
||||
case INTERNAL:
|
||||
return PlaneConnections.of(false, false, false, false);
|
||||
}
|
||||
|
||||
boolean left = false, right = false, down = false, up = false;
|
||||
|
||||
final IPartHost host = this.getHost();
|
||||
if (host != null) {
|
||||
final BlockEntity te = host.getTile();
|
||||
|
||||
final BlockPos pos = te.getPos();
|
||||
|
||||
if (this.isAnnihilationPlane(te.getWorld().getBlockEntity(pos.offset(facingRight.getOpposite())),
|
||||
this.getSide())) {
|
||||
left = true;
|
||||
}
|
||||
|
||||
if (this.isAnnihilationPlane(te.getWorld().getBlockEntity(pos.offset(facingRight)), this.getSide())) {
|
||||
right = true;
|
||||
}
|
||||
|
||||
if (this.isAnnihilationPlane(te.getWorld().getBlockEntity(pos.offset(facingUp.getOpposite())),
|
||||
this.getSide())) {
|
||||
down = true;
|
||||
}
|
||||
|
||||
if (this.isAnnihilationPlane(te.getWorld().getBlockEntity(pos.offset(facingUp)), this.getSide())) {
|
||||
up = true;
|
||||
}
|
||||
}
|
||||
|
||||
return PlaneConnections.of(up, right, down, left);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onneighborUpdate(BlockView w, BlockPos pos, BlockPos neighbor) {
|
||||
if (pos.offset(this.getSide().getFacing()).equals(neighbor)) {
|
||||
this.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEntityCollision(final Entity entity) {
|
||||
if (this.isAccepting && entity instanceof ItemEntity && entity.isAlive() && Platform.isServer()
|
||||
&& this.getProxy().isActive()) {
|
||||
|
||||
ItemEntity itemEntity = (ItemEntity) entity;
|
||||
if (isItemBlacklisted(itemEntity.getStack().getItem())) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean capture = false;
|
||||
final BlockPos pos = this.getTile().getPos();
|
||||
|
||||
// This is the middle point of the entities BB, which is better suited for
|
||||
// comparisons that don't rely on it
|
||||
// "touching" the plane
|
||||
double posYMiddle = (entity.getBoundingBox().minY + entity.getBoundingBox().maxY) / 2.0D;
|
||||
|
||||
switch (this.getSide()) {
|
||||
case DOWN:
|
||||
case UP:
|
||||
if (entity.getX() > pos.getX() && entity.getX() < pos.getX() + 1) {
|
||||
if (entity.getZ() > pos.getZ() && entity.getZ() < pos.getZ() + 1) {
|
||||
if ((entity.getY() > pos.getY() + 0.9 && this.getSide() == AEPartLocation.UP)
|
||||
|| (entity.getY() < pos.getY() + 0.1 && this.getSide() == AEPartLocation.DOWN)) {
|
||||
capture = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SOUTH:
|
||||
case NORTH:
|
||||
if (entity.getX() > pos.getX() && entity.getX() < pos.getX() + 1) {
|
||||
if (posYMiddle > pos.getY() && posYMiddle < pos.getY() + 1) {
|
||||
if ((entity.getZ() > pos.getZ() + 0.9 && this.getSide() == AEPartLocation.SOUTH)
|
||||
|| (entity.getZ() < pos.getZ() + 0.1
|
||||
&& this.getSide() == AEPartLocation.NORTH)) {
|
||||
capture = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EAST:
|
||||
case WEST:
|
||||
if (entity.getZ() > pos.getZ() && entity.getZ() < pos.getZ() + 1) {
|
||||
if (posYMiddle > pos.getY() && posYMiddle < pos.getY() + 1) {
|
||||
if ((entity.getX() > pos.getX() + 0.9 && this.getSide() == AEPartLocation.EAST)
|
||||
|| (entity.getX() < pos.getX() + 0.1 && this.getSide() == AEPartLocation.WEST)) {
|
||||
capture = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// umm?
|
||||
break;
|
||||
}
|
||||
|
||||
if (capture) {
|
||||
final boolean changed = this.storeEntityItem(itemEntity);
|
||||
|
||||
if (changed) {
|
||||
AppEng.instance().sendToAllNearExcept(null, pos.getX(), pos.getY(), pos.getZ(), 64,
|
||||
this.getTile().getWorld(), new ItemTransitionEffectPacket(entity.getX(),
|
||||
entity.getY(), entity.getZ(), this.getSide().getOpposite()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getCableConnectionLength(AECableType cable) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores an {@link ItemEntity} inside the network and either marks it as dead
|
||||
* or sets it to the leftover stackSize.
|
||||
*
|
||||
* @param entityItem {@link ItemEntity} to store
|
||||
*/
|
||||
private boolean storeEntityItem(final ItemEntity entityItem) {
|
||||
if (entityItem.isAlive()) {
|
||||
final IAEItemStack overflow = this.storeItemStack(entityItem.getStack());
|
||||
|
||||
return this.handleOverflow(entityItem, overflow);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores an {@link ItemStack} inside the network.
|
||||
*
|
||||
* @param item {@link ItemStack} to store
|
||||
*
|
||||
* @return the leftover items, which could not be stored inside the network
|
||||
*/
|
||||
private IAEItemStack storeItemStack(final ItemStack item) {
|
||||
final IAEItemStack itemToStore = AEItemStack.fromItemStack(item);
|
||||
try {
|
||||
final IStorageGrid storage = this.getProxy().getStorage();
|
||||
final IEnergyGrid energy = this.getProxy().getEnergy();
|
||||
final IAEItemStack overflow = Platform.poweredInsert(energy,
|
||||
storage.getInventory(AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class)),
|
||||
itemToStore, this.mySrc);
|
||||
|
||||
this.isAccepting = overflow == null;
|
||||
|
||||
return overflow;
|
||||
} catch (final GridAccessException e1) {
|
||||
// :P
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a possible overflow or none at all. It will update the entity to
|
||||
* match the leftover stack size as well as mark it as dead without any leftover
|
||||
* amount.
|
||||
*
|
||||
* @param entityItem the entity to update or destroy
|
||||
* @param overflow the leftover {@link IAEItemStack}
|
||||
*
|
||||
* @return true, if the entity was changed otherwise false.
|
||||
*/
|
||||
private boolean handleOverflow(final ItemEntity entityItem, final IAEItemStack overflow) {
|
||||
if (overflow == null || overflow.getStackSize() == 0) {
|
||||
entityItem.remove();
|
||||
return true;
|
||||
}
|
||||
|
||||
final int oldStackSize = entityItem.getStack().getCount();
|
||||
final int newStackSize = (int) overflow.getStackSize();
|
||||
final boolean changed = oldStackSize != newStackSize;
|
||||
|
||||
entityItem.getStack().setCount(newStackSize);
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
protected boolean isAnnihilationPlane(final BlockEntity blockTileEntity, final AEPartLocation side) {
|
||||
if (blockTileEntity instanceof IPartHost) {
|
||||
final IPart p = ((IPartHost) blockTileEntity).getPart(side);
|
||||
return p != null && p.getClass() == this.getClass();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@MENetworkEventSubscribe
|
||||
public void chanRender(final MENetworkChannelsChanged c) {
|
||||
this.refresh();
|
||||
this.getHost().markForUpdate();
|
||||
}
|
||||
|
||||
@Override
|
||||
@MENetworkEventSubscribe
|
||||
public void powerRender(final MENetworkPowerStatusChange c) {
|
||||
this.refresh();
|
||||
this.getHost().markForUpdate();
|
||||
}
|
||||
|
||||
private TickRateModulation breakBlock(final boolean modulate) {
|
||||
if (this.isAccepting && this.getProxy().isActive()) {
|
||||
try {
|
||||
final BlockEntity te = this.getTile();
|
||||
final ServerWorld w = (ServerWorld) te.getWorld();
|
||||
|
||||
final BlockPos pos = te.getPos().offset(this.getSide().getFacing());
|
||||
final IEnergyGrid energy = this.getProxy().getEnergy();
|
||||
|
||||
final BlockState blockState = w.getBlockState(pos);
|
||||
if (this.canHandleBlock(w, pos, blockState)) {
|
||||
// Query the loot-table and get a potential outcome of the loot-table evaluation
|
||||
final List<ItemStack> items = this.obtainBlockDrops(w, pos);
|
||||
final float requiredPower = this.calculateEnergyUsage(w, pos, items);
|
||||
|
||||
final boolean hasPower = energy.extractAEPower(requiredPower, Actionable.SIMULATE,
|
||||
PowerMultiplier.CONFIG) > requiredPower - 0.1;
|
||||
final boolean canStore = this.canStoreItemStacks(items);
|
||||
|
||||
if (hasPower && canStore) {
|
||||
if (modulate) {
|
||||
performBreakBlock(w, pos, blockState, energy, requiredPower, items);
|
||||
} else {
|
||||
this.breaking = true;
|
||||
TickHandler.INSTANCE.addCallable(this.getTile().getWorld(), this);
|
||||
}
|
||||
return TickRateModulation.URGENT;
|
||||
}
|
||||
}
|
||||
} catch (final GridAccessException e1) {
|
||||
// :P
|
||||
}
|
||||
}
|
||||
|
||||
// nothing to do here :)
|
||||
return TickRateModulation.IDLE;
|
||||
}
|
||||
|
||||
private void performBreakBlock(ServerWorld w, BlockPos pos, BlockState blockState, IEnergyGrid energy,
|
||||
float requiredPower, List<ItemStack> items) {
|
||||
|
||||
if (!this.breakBlockAndStoreExtraItems(w, pos)) {
|
||||
// We failed to actually replace the block with air or it already was the case
|
||||
return;
|
||||
}
|
||||
|
||||
for (ItemStack item : items) {
|
||||
IAEItemStack overflow = storeItemStack(item);
|
||||
// If inserting the item fully was not possible, drop it as an item entity
|
||||
// instead
|
||||
// if the storage clears up, we'll pick it up that way
|
||||
if (overflow != null) {
|
||||
Platform.spawnDrops(w, pos, Collections.singletonList(overflow.createItemStack()));
|
||||
}
|
||||
}
|
||||
|
||||
energy.extractAEPower(requiredPower, Actionable.MODULATE, PowerMultiplier.CONFIG);
|
||||
|
||||
AppEng.instance().sendToAllNearExcept(null, pos.getX(), pos.getY(), pos.getZ(), 64, w,
|
||||
new BlockTransitionEffectPacket(pos, blockState, this.getSide().getOpposite(),
|
||||
BlockTransitionEffectPacket.SoundMode.NONE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickingRequest getTickingRequest(final IGridNode node) {
|
||||
return new TickingRequest(TickRates.AnnihilationPlane.getMin(), TickRates.AnnihilationPlane.getMax(), false,
|
||||
true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickRateModulation tickingRequest(final IGridNode node, final int ticksSinceLastCall) {
|
||||
if (this.breaking) {
|
||||
return TickRateModulation.URGENT;
|
||||
}
|
||||
|
||||
this.isAccepting = true;
|
||||
return this.breakBlock(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this plane can handle the block at the specific coordinates.
|
||||
*/
|
||||
private boolean canHandleBlock(final ServerWorld w, final BlockPos pos, final BlockState state) {
|
||||
if (state.isAir(w, pos)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isBlockBlacklisted(state.getBlock())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final Material material = state.getMaterial();
|
||||
final float hardness = state.getBlockHardness(w, pos);
|
||||
final boolean ignoreMaterials = material == Material.AIR || material == Material.LAVA
|
||||
|| material == Material.WATER || material.isLiquid();
|
||||
|
||||
return !ignoreMaterials && hardness >= 0f && w.isChunkLoaded(pos)
|
||||
&& w.canPlayerModifyAt((PlayerEntity) FakePlayer.getOrCreate(w), pos);
|
||||
}
|
||||
|
||||
protected List<ItemStack> obtainBlockDrops(final ServerWorld w, final BlockPos pos) {
|
||||
|
||||
Entity fakePlayer = FakePlayerFactory.getMinecraft(w);
|
||||
|
||||
final BlockState state = w.getBlockState(pos);
|
||||
|
||||
ItemStack harvestTool = createHarvestTool(state);
|
||||
|
||||
if (harvestTool == null) {
|
||||
if (!state.getMaterial().isToolNotRequired()) {
|
||||
harvestTool = ItemStack.EMPTY;
|
||||
} else {
|
||||
// In case the block does NOT allow us to harvest it without a tool, or the
|
||||
// proper tool, do not return anything.
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
BlockEntity te = w.getBlockEntity(pos);
|
||||
return Block.getDroppedStacks(state, w, pos, te, fakePlayer, harvestTool);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this plane can handle the block at the specific coordinates.
|
||||
*/
|
||||
protected float calculateEnergyUsage(final ServerWorld w, final BlockPos pos, final List<ItemStack> items) {
|
||||
final BlockState state = w.getBlockState(pos);
|
||||
final float hardness = state.getBlockHardness(w, pos);
|
||||
|
||||
float requiredEnergy = 1 + hardness;
|
||||
for (final ItemStack is : items) {
|
||||
requiredEnergy += is.getCount();
|
||||
}
|
||||
|
||||
return requiredEnergy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the network can store the possible drops.
|
||||
*
|
||||
* It also sets isAccepting to false, if the item can not be stored.
|
||||
*
|
||||
* @param itemStacks an array of {@link ItemStack} to test
|
||||
*
|
||||
* @return true, if the network can store at least a single item of all drops or
|
||||
* no drops are reported
|
||||
*/
|
||||
private boolean canStoreItemStacks(final List<ItemStack> itemStacks) {
|
||||
boolean canStore = itemStacks.isEmpty();
|
||||
|
||||
try {
|
||||
final IStorageGrid storage = this.getProxy().getStorage();
|
||||
|
||||
for (final ItemStack itemStack : itemStacks) {
|
||||
final IAEItemStack itemToTest = AEItemStack.fromItemStack(itemStack);
|
||||
final IAEItemStack overflow = storage
|
||||
.getInventory(AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class))
|
||||
.injectItems(itemToTest, Actionable.SIMULATE, this.mySrc);
|
||||
if (overflow == null || itemToTest.getStackSize() > overflow.getStackSize()) {
|
||||
canStore = true;
|
||||
}
|
||||
}
|
||||
} catch (final GridAccessException e) {
|
||||
// :P
|
||||
}
|
||||
|
||||
this.isAccepting = canStore;
|
||||
return canStore;
|
||||
}
|
||||
|
||||
private boolean breakBlockAndStoreExtraItems(final ServerWorld w, final BlockPos pos) {
|
||||
// Kill the block, but signal no drops
|
||||
if (!w.breakBlock(pos, false)) {
|
||||
// The block was no longer there
|
||||
return false;
|
||||
}
|
||||
|
||||
// This handles items that do not spawn via loot-tables but rather normal block
|
||||
// breaking
|
||||
// i.e. our cable-buses do this (bad practice, really)
|
||||
final Box box = new Box(pos).grow(0.2);
|
||||
for (final Object ei : w.getEntitiesWithinAABB(ItemEntity.class, box)) {
|
||||
if (ei instanceof ItemEntity) {
|
||||
final ItemEntity entityItem = (ItemEntity) ei;
|
||||
this.storeEntityItem(entityItem);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void refresh() {
|
||||
this.isAccepting = true;
|
||||
|
||||
getTile().requestModelDataUpdate();
|
||||
|
||||
try {
|
||||
this.getProxy().getTick().alertDevice(this.getProxy().getNode());
|
||||
} catch (final GridAccessException e) {
|
||||
// :P
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPartModel getStaticModels() {
|
||||
return MODELS.getModel(this.isPowered(), this.isActive());
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public IModelData getModelData() {
|
||||
return new PlaneModelData(getConnections());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the fake (and temporary) tool that will be used to calculate the loot
|
||||
* tables of a block this plane wants to break.
|
||||
*
|
||||
* @param state The state of the block about to be broken.
|
||||
*/
|
||||
protected ItemStack createHarvestTool(BlockState state) {
|
||||
// Try to use the right tool...
|
||||
Tag<Item> harvestToolType = state.getBlock().getHarvestTool(state);
|
||||
if (harvestToolType == FabricToolTags.AXES) {
|
||||
return new ItemStack(Items.DIAMOND_AXE, 1);
|
||||
} else if (harvestToolType == FabricToolTags.SHOVELS) {
|
||||
return new ItemStack(Items.DIAMOND_SHOVEL, 1);
|
||||
} else if (harvestToolType == FabricToolTags.PICKAXES) {
|
||||
return new ItemStack(Items.DIAMOND_PICKAXE, 1);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isBlockBlacklisted(Block b) {
|
||||
Tag<Block> tag = BlockTags.getContainer().getOrCreate(TAG_BLACKLIST);
|
||||
return b.isIn(tag);
|
||||
}
|
||||
|
||||
public static boolean isItemBlacklisted(Item i) {
|
||||
Tag<Item> tag = ItemTags.getCollection().getOrCreate(TAG_BLACKLIST);
|
||||
return i.isIn(tag);
|
||||
}
|
||||
|
||||
}
|
||||
+8
-7
@@ -18,25 +18,26 @@
|
||||
|
||||
package appeng.parts.automation;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.item.BlockItem;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import appeng.api.config.Upgrades;
|
||||
import appeng.api.definitions.IItemDefinition;
|
||||
import appeng.util.inv.IAEAppEngInventory;
|
||||
|
||||
public final class DefinitionUpgradeInventory extends UpgradeInventory {
|
||||
private final IItemDefinition definition;
|
||||
public class BlockUpgradeInventory extends UpgradeInventory {
|
||||
private final Block block;
|
||||
|
||||
public DefinitionUpgradeInventory(final IItemDefinition definition, final IAEAppEngInventory parent, final int s) {
|
||||
public BlockUpgradeInventory(final Block block, final IAEAppEngInventory parent, final int s) {
|
||||
super(parent, s);
|
||||
|
||||
this.definition = definition;
|
||||
this.block = block;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxInstalled(final Upgrades upgrades) {
|
||||
for (final Upgrades.Supported supported : upgrades.getSupported()) {
|
||||
if (supported.isSupported(definition.item())) {
|
||||
if (supported.isSupported(block)) {
|
||||
return supported.getMaxCount();
|
||||
}
|
||||
}
|
||||
@@ -1,323 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.automation;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.config.Actionable;
|
||||
import appeng.api.config.FuzzyMode;
|
||||
import appeng.api.config.PowerMultiplier;
|
||||
import appeng.api.config.RedstoneMode;
|
||||
import appeng.api.config.SchedulingMode;
|
||||
import appeng.api.config.Settings;
|
||||
import appeng.api.config.Upgrades;
|
||||
import appeng.api.config.YesNo;
|
||||
import appeng.api.networking.IGridNode;
|
||||
import appeng.api.networking.crafting.ICraftingGrid;
|
||||
import appeng.api.networking.crafting.ICraftingLink;
|
||||
import appeng.api.networking.crafting.ICraftingRequester;
|
||||
import appeng.api.networking.energy.IEnergyGrid;
|
||||
import appeng.api.networking.security.IActionSource;
|
||||
import appeng.api.networking.ticking.TickRateModulation;
|
||||
import appeng.api.networking.ticking.TickingRequest;
|
||||
import appeng.api.parts.IPartCollisionHelper;
|
||||
import appeng.api.parts.IPartModel;
|
||||
import appeng.api.storage.IMEInventory;
|
||||
import appeng.api.storage.IMEMonitor;
|
||||
import appeng.api.storage.channels.IItemStorageChannel;
|
||||
import appeng.api.storage.data.IAEItemStack;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.container.ContainerLocator;
|
||||
import appeng.container.ContainerOpener;
|
||||
import appeng.container.implementations.UpgradeableContainer;
|
||||
import appeng.core.AELog;
|
||||
import appeng.core.AppEng;
|
||||
import appeng.core.settings.TickRates;
|
||||
import appeng.helpers.MultiCraftingTracker;
|
||||
import appeng.helpers.Reflected;
|
||||
import appeng.items.parts.PartModels;
|
||||
import appeng.me.GridAccessException;
|
||||
import appeng.me.helpers.MachineSource;
|
||||
import appeng.parts.PartModel;
|
||||
import appeng.util.InventoryAdaptor;
|
||||
import appeng.util.Platform;
|
||||
import appeng.util.item.AEItemStack;
|
||||
|
||||
public class ExportBusPart extends SharedItemBusPart implements ICraftingRequester {
|
||||
|
||||
public static final Identifier MODEL_BASE = new Identifier(AppEng.MOD_ID, "part/export_bus_base");
|
||||
|
||||
@PartModels
|
||||
public static final IPartModel MODELS_OFF = new PartModel(MODEL_BASE,
|
||||
new Identifier(AppEng.MOD_ID, "part/export_bus_off"));
|
||||
|
||||
@PartModels
|
||||
public static final IPartModel MODELS_ON = new PartModel(MODEL_BASE,
|
||||
new Identifier(AppEng.MOD_ID, "part/export_bus_on"));
|
||||
|
||||
@PartModels
|
||||
public static final IPartModel MODELS_HAS_CHANNEL = new PartModel(MODEL_BASE,
|
||||
new Identifier(AppEng.MOD_ID, "part/export_bus_has_channel"));
|
||||
|
||||
private final MultiCraftingTracker craftingTracker = new MultiCraftingTracker(this, 9);
|
||||
private final IActionSource mySrc;
|
||||
private long itemToSend = 1;
|
||||
private boolean didSomething = false;
|
||||
private int nextSlot = 0;
|
||||
|
||||
@Reflected
|
||||
public ExportBusPart(final ItemStack is) {
|
||||
super(is);
|
||||
|
||||
this.getConfigManager().registerSetting(Settings.REDSTONE_CONTROLLED, RedstoneMode.IGNORE);
|
||||
this.getConfigManager().registerSetting(Settings.FUZZY_MODE, FuzzyMode.IGNORE_ALL);
|
||||
this.getConfigManager().registerSetting(Settings.CRAFT_ONLY, YesNo.NO);
|
||||
this.getConfigManager().registerSetting(Settings.SCHEDULING_MODE, SchedulingMode.DEFAULT);
|
||||
this.mySrc = new MachineSource(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromNBT(final CompoundTag extra) {
|
||||
super.readFromNBT(extra);
|
||||
this.craftingTracker.readFromNBT(extra);
|
||||
this.nextSlot = extra.getInt("nextSlot");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToNBT(final CompoundTag extra) {
|
||||
super.writeToNBT(extra);
|
||||
this.craftingTracker.writeToNBT(extra);
|
||||
extra.putInt("nextSlot", this.nextSlot);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TickRateModulation doBusWork() {
|
||||
if (!this.getProxy().isActive() || !this.canDoBusWork()) {
|
||||
return TickRateModulation.IDLE;
|
||||
}
|
||||
|
||||
this.itemToSend = this.calculateItemsToSend();
|
||||
this.didSomething = false;
|
||||
|
||||
try {
|
||||
final InventoryAdaptor destination = this.getHandler();
|
||||
final IMEMonitor<IAEItemStack> inv = this.getProxy().getStorage()
|
||||
.getInventory(AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class));
|
||||
final IEnergyGrid energy = this.getProxy().getEnergy();
|
||||
final ICraftingGrid cg = this.getProxy().getCrafting();
|
||||
final FuzzyMode fzMode = (FuzzyMode) this.getConfigManager().getSetting(Settings.FUZZY_MODE);
|
||||
final SchedulingMode schedulingMode = (SchedulingMode) this.getConfigManager()
|
||||
.getSetting(Settings.SCHEDULING_MODE);
|
||||
|
||||
if (destination != null) {
|
||||
int x = 0;
|
||||
|
||||
for (x = 0; x < this.availableSlots() && this.itemToSend > 0; x++) {
|
||||
final int slotToExport = this.getStartingSlot(schedulingMode, x);
|
||||
|
||||
final IAEItemStack ais = this.getConfig().getAEStackInSlot(slotToExport);
|
||||
|
||||
if (ais == null || this.itemToSend <= 0 || this.craftOnly()) {
|
||||
if (this.isCraftingEnabled()) {
|
||||
this.didSomething = this.craftingTracker.handleCrafting(slotToExport, this.itemToSend, ais,
|
||||
destination, this.getTile().getWorld(), this.getProxy().getGrid(), cg, this.mySrc)
|
||||
|| this.didSomething;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
final long before = this.itemToSend;
|
||||
|
||||
if (this.getInstalledUpgrades(Upgrades.FUZZY) > 0) {
|
||||
for (final IAEItemStack o : ImmutableList.copyOf(inv.getStorageList().findFuzzy(ais, fzMode))) {
|
||||
this.pushItemIntoTarget(destination, energy, inv, o);
|
||||
if (this.itemToSend <= 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.pushItemIntoTarget(destination, energy, inv, ais);
|
||||
}
|
||||
|
||||
if (this.itemToSend == before && this.isCraftingEnabled()) {
|
||||
this.didSomething = this.craftingTracker.handleCrafting(slotToExport, this.itemToSend, ais,
|
||||
destination, this.getTile().getWorld(), this.getProxy().getGrid(), cg, this.mySrc)
|
||||
|| this.didSomething;
|
||||
}
|
||||
}
|
||||
|
||||
this.updateSchedulingMode(schedulingMode, x);
|
||||
} else {
|
||||
return TickRateModulation.SLEEP;
|
||||
}
|
||||
} catch (final GridAccessException e) {
|
||||
// :P
|
||||
}
|
||||
|
||||
return this.didSomething ? TickRateModulation.FASTER : TickRateModulation.SLOWER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getBoxes(final IPartCollisionHelper bch) {
|
||||
bch.addBox(4, 4, 12, 12, 12, 14);
|
||||
bch.addBox(5, 5, 14, 11, 11, 15);
|
||||
bch.addBox(6, 6, 15, 10, 10, 16);
|
||||
bch.addBox(6, 6, 11, 10, 10, 12);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getCableConnectionLength(AECableType cable) {
|
||||
return 5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPartActivate(final PlayerEntity player, final Hand hand, final Vec3d pos) {
|
||||
if (Platform.isServer()) {
|
||||
ContainerOpener.openContainer(UpgradeableContainer.TYPE, player, ContainerLocator.forPart(this));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickingRequest getTickingRequest(final IGridNode node) {
|
||||
return new TickingRequest(TickRates.ExportBus.getMin(), TickRates.ExportBus.getMax(), this.isSleeping(), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RedstoneMode getRSMode() {
|
||||
return (RedstoneMode) this.getConfigManager().getSetting(Settings.REDSTONE_CONTROLLED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickRateModulation tickingRequest(final IGridNode node, final int ticksSinceLastCall) {
|
||||
return this.doBusWork();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableSet<ICraftingLink> getRequestedJobs() {
|
||||
return this.craftingTracker.getRequestedJobs();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAEItemStack injectCraftedItems(final ICraftingLink link, final IAEItemStack items, final Actionable mode) {
|
||||
final InventoryAdaptor d = this.getHandler();
|
||||
|
||||
try {
|
||||
if (d != null && this.getProxy().isActive()) {
|
||||
final IEnergyGrid energy = this.getProxy().getEnergy();
|
||||
final double power = items.getStackSize();
|
||||
|
||||
if (energy.extractAEPower(power, mode, PowerMultiplier.CONFIG) > power - 0.01) {
|
||||
if (mode == Actionable.MODULATE) {
|
||||
return AEItemStack.fromItemStack(d.addItems(items.createItemStack()));
|
||||
}
|
||||
return AEItemStack.fromItemStack(d.simulateAdd(items.createItemStack()));
|
||||
}
|
||||
}
|
||||
} catch (final GridAccessException e) {
|
||||
AELog.debug(e);
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jobStateChange(final ICraftingLink link) {
|
||||
this.craftingTracker.jobStateChange(link);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isSleeping() {
|
||||
return this.getHandler() == null || super.isSleeping();
|
||||
}
|
||||
|
||||
private boolean craftOnly() {
|
||||
return this.getConfigManager().getSetting(Settings.CRAFT_ONLY) == YesNo.YES;
|
||||
}
|
||||
|
||||
private boolean isCraftingEnabled() {
|
||||
return this.getInstalledUpgrades(Upgrades.CRAFTING) > 0;
|
||||
}
|
||||
|
||||
private void pushItemIntoTarget(final InventoryAdaptor d, final IEnergyGrid energy,
|
||||
final IMEInventory<IAEItemStack> inv, IAEItemStack ais) {
|
||||
final ItemStack is = ais.createItemStack();
|
||||
is.setCount((int) this.itemToSend);
|
||||
|
||||
final ItemStack o = d.simulateAdd(is);
|
||||
final long canFit = o.isEmpty() ? this.itemToSend : this.itemToSend - o.getCount();
|
||||
|
||||
if (canFit > 0) {
|
||||
ais = ais.copy();
|
||||
ais.setStackSize(canFit);
|
||||
final IAEItemStack itemsToAdd = Platform.poweredExtraction(energy, inv, ais, this.mySrc);
|
||||
|
||||
if (itemsToAdd != null) {
|
||||
this.itemToSend -= itemsToAdd.getStackSize();
|
||||
|
||||
final ItemStack failed = d.addItems(itemsToAdd.createItemStack());
|
||||
if (!failed.isEmpty()) {
|
||||
ais.setStackSize(failed.getCount());
|
||||
inv.injectItems(ais, Actionable.MODULATE, this.mySrc);
|
||||
} else {
|
||||
this.didSomething = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int getStartingSlot(final SchedulingMode schedulingMode, final int x) {
|
||||
if (schedulingMode == SchedulingMode.RANDOM) {
|
||||
return Platform.getRandom().nextInt(this.availableSlots());
|
||||
}
|
||||
|
||||
if (schedulingMode == SchedulingMode.ROUNDROBIN) {
|
||||
return (this.nextSlot + x) % this.availableSlots();
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
private void updateSchedulingMode(final SchedulingMode schedulingMode, final int x) {
|
||||
if (schedulingMode == SchedulingMode.ROUNDROBIN) {
|
||||
this.nextSlot = (this.nextSlot + x) % this.availableSlots();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPartModel getStaticModels() {
|
||||
if (this.isActive() && this.isPowered()) {
|
||||
return MODELS_HAS_CHANNEL;
|
||||
} else if (this.isPowered()) {
|
||||
return MODELS_ON;
|
||||
} else {
|
||||
return MODELS_OFF;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,375 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.automation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import appeng.util.FakePlayer;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.ItemEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.screen.ScreenHandlerType;
|
||||
import net.minecraft.item.BlockItem;
|
||||
import net.minecraft.item.AutomaticItemPlacementContext;
|
||||
import net.minecraft.item.FireworkRocketItem;
|
||||
import net.minecraft.item.FireworkStarItem;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.ItemUsageContext;
|
||||
import net.minecraft.item.WallOrFloorItem;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.math.Box;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
|
||||
import net.minecraftforge.common.IPlantable;
|
||||
import alexiil.mc.lib.attributes.item.FixedItemInv;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.config.AccessRestriction;
|
||||
import appeng.api.config.Actionable;
|
||||
import appeng.api.config.FuzzyMode;
|
||||
import appeng.api.config.IncludeExclude;
|
||||
import appeng.api.config.Settings;
|
||||
import appeng.api.config.Upgrades;
|
||||
import appeng.api.config.YesNo;
|
||||
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.IActionSource;
|
||||
import appeng.api.parts.IPartItem;
|
||||
import appeng.api.parts.IPartModel;
|
||||
import appeng.api.storage.IMEInventoryHandler;
|
||||
import appeng.api.storage.IStorageChannel;
|
||||
import appeng.api.storage.channels.IItemStorageChannel;
|
||||
import appeng.api.storage.data.IAEItemStack;
|
||||
import appeng.api.storage.data.IItemList;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
import appeng.container.ContainerLocator;
|
||||
import appeng.container.ContainerOpener;
|
||||
import appeng.container.implementations.FormationPlaneContainer;
|
||||
import appeng.core.AEConfig;
|
||||
import appeng.items.parts.PartModels;
|
||||
import appeng.me.GridAccessException;
|
||||
import appeng.me.storage.MEInventoryHandler;
|
||||
import appeng.tile.inventory.AppEngInternalAEInventory;
|
||||
import appeng.util.Platform;
|
||||
import appeng.util.inv.InvOperation;
|
||||
import appeng.util.prioritylist.FuzzyPriorityList;
|
||||
import appeng.util.prioritylist.PrecisePriorityList;
|
||||
|
||||
public class FormationPlanePart extends AbstractFormationPlanePart<IAEItemStack> {
|
||||
|
||||
private static final PlaneModels MODELS = new PlaneModels("part/formation_plane", "part/formation_plane_on");
|
||||
|
||||
@PartModels
|
||||
public static List<IPartModel> getModels() {
|
||||
return MODELS.getModels();
|
||||
}
|
||||
|
||||
private final MEInventoryHandler<IAEItemStack> myHandler = new MEInventoryHandler<>(this,
|
||||
AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class));
|
||||
private final AppEngInternalAEInventory Config = new AppEngInternalAEInventory(this, 63);
|
||||
|
||||
public FormationPlanePart(final ItemStack is) {
|
||||
super(is);
|
||||
|
||||
this.getConfigManager().registerSetting(Settings.FUZZY_MODE, FuzzyMode.IGNORE_ALL);
|
||||
this.getConfigManager().registerSetting(Settings.PLACE_BLOCK, YesNo.YES);
|
||||
this.updateHandler();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateHandler() {
|
||||
this.myHandler.setBaseAccess(AccessRestriction.WRITE);
|
||||
this.myHandler.setWhitelist(
|
||||
this.getInstalledUpgrades(Upgrades.INVERTER) > 0 ? IncludeExclude.BLACKLIST : IncludeExclude.WHITELIST);
|
||||
this.myHandler.setPriority(this.getPriority());
|
||||
|
||||
final IItemList<IAEItemStack> priorityList = AEApi.instance().storage()
|
||||
.getStorageChannel(IItemStorageChannel.class).createList();
|
||||
|
||||
final int slotsToUse = 18 + this.getInstalledUpgrades(Upgrades.CAPACITY) * 9;
|
||||
for (int x = 0; x < this.Config.getSlotCount() && x < slotsToUse; x++) {
|
||||
final IAEItemStack is = this.Config.getAEStackInSlot(x);
|
||||
if (is != null) {
|
||||
priorityList.add(is);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.getInstalledUpgrades(Upgrades.FUZZY) > 0) {
|
||||
this.myHandler.setPartitionList(new FuzzyPriorityList<IAEItemStack>(priorityList,
|
||||
(FuzzyMode) this.getConfigManager().getSetting(Settings.FUZZY_MODE)));
|
||||
} else {
|
||||
this.myHandler.setPartitionList(new PrecisePriorityList<IAEItemStack>(priorityList));
|
||||
}
|
||||
|
||||
try {
|
||||
this.getProxy().getGrid().postEvent(new MENetworkCellArrayUpdate());
|
||||
} catch (final GridAccessException e) {
|
||||
// :P
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeInventory(final FixedItemInv 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.updateHandler();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromNBT(final CompoundTag data) {
|
||||
super.readFromNBT(data);
|
||||
this.Config.readFromNBT(data, "config");
|
||||
this.updateHandler();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToNBT(final CompoundTag data) {
|
||||
super.writeToNBT(data);
|
||||
this.Config.writeToNBT(data, "config");
|
||||
}
|
||||
|
||||
@Override
|
||||
public FixedItemInv getInventoryByName(final String name) {
|
||||
if (name.equals("config")) {
|
||||
return this.Config;
|
||||
}
|
||||
|
||||
return super.getInventoryByName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
@MENetworkEventSubscribe
|
||||
public void powerRender(final MENetworkPowerStatusChange c) {
|
||||
this.stateChanged();
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void updateChannels(final MENetworkChannelsChanged changedChannels) {
|
||||
this.stateChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPartActivate(final PlayerEntity player, final Hand hand, final Vec3d pos) {
|
||||
if (Platform.isServer()) {
|
||||
ContainerOpener.openContainer(FormationPlaneContainer.TYPE, player, ContainerLocator.forPart(this));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IMEInventoryHandler> getCellArray(final IStorageChannel channel) {
|
||||
if (this.getProxy().isActive()
|
||||
&& channel == AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class)) {
|
||||
final List<IMEInventoryHandler> handler = new ArrayList<>(1);
|
||||
handler.add(this.myHandler);
|
||||
return handler;
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAEItemStack injectItems(final IAEItemStack input, final Actionable type, final IActionSource src) {
|
||||
if (this.blocked || input == null || input.getStackSize() <= 0) {
|
||||
return input;
|
||||
}
|
||||
|
||||
final YesNo placeBlock = (YesNo) this.getConfigManager().getSetting(Settings.PLACE_BLOCK);
|
||||
|
||||
final ItemStack is = input.createItemStack();
|
||||
final Item i = is.getItem();
|
||||
|
||||
long maxStorage = Math.min(input.getStackSize(), is.getMaxCount());
|
||||
boolean worked = false;
|
||||
|
||||
final BlockEntity te = this.getHost().getTile();
|
||||
final World w = te.getWorld();
|
||||
final AEPartLocation side = this.getSide();
|
||||
|
||||
final BlockPos placePos = te.getPos().offset(side.getFacing());
|
||||
|
||||
if (w.getBlockState(placePos).getMaterial().isReplaceable()) {
|
||||
if (placeBlock == YesNo.YES && (i instanceof BlockItem || i instanceof IPlantable
|
||||
|| i instanceof FireworkStarItem || i instanceof FireworkRocketItem || i instanceof IPartItem)) {
|
||||
final PlayerEntity player = FakePlayer.getOrCreate((ServerWorld) w);
|
||||
Platform.configurePlayer(player, side, this.getTile());
|
||||
Hand hand = player.getActiveHand();
|
||||
player.setStackInHand(hand, is);
|
||||
|
||||
maxStorage = is.getCount();
|
||||
worked = true;
|
||||
if (type == Actionable.MODULATE) {
|
||||
// The side the plane is attached to will be considered the look direction
|
||||
// in terms of placing an item
|
||||
Direction lookDirection = side.getFacing();
|
||||
|
||||
// FIXME No idea what any of this is _supposed_ to do, comment badly needed
|
||||
if (i instanceof IPlantable || i instanceof WallOrFloorItem) {
|
||||
boolean Worked = false;
|
||||
|
||||
// Up or Down, Attempt 1??
|
||||
if (side.xOffset == 0 && side.zOffset == 0) {
|
||||
Worked = i.onItemUse(new AutomaticItemPlacementContext(w, placePos.offset(side.getFacing()),
|
||||
lookDirection, is, side.getFacing())) == ActionResult.SUCCESS;
|
||||
}
|
||||
|
||||
// Up or Down, Attempt 2??
|
||||
if (!Worked && side.xOffset == 0 && side.zOffset == 0) {
|
||||
Worked = i.onItemUse(new AutomaticItemPlacementContext(w,
|
||||
placePos.offset(side.getFacing().getOpposite()), lookDirection, is,
|
||||
side.getFacing().getOpposite())) == ActionResult.SUCCESS;
|
||||
}
|
||||
|
||||
// Horizontal, attempt 1??
|
||||
if (!Worked && side.yOffset == 0) {
|
||||
Worked = i.onItemUse(new AutomaticItemPlacementContext(w, placePos.offset(Direction.DOWN),
|
||||
lookDirection, is, Direction.DOWN)) == ActionResult.SUCCESS;
|
||||
}
|
||||
|
||||
if (!Worked) {
|
||||
i.onItemUse(new AutomaticItemPlacementContext(w, placePos, lookDirection, is,
|
||||
lookDirection.getOpposite()));
|
||||
}
|
||||
|
||||
maxStorage -= is.getCount();
|
||||
} else {
|
||||
i.onItemUse(new AutomaticItemPlacementContext(w, placePos, lookDirection, is,
|
||||
lookDirection.getOpposite()));
|
||||
maxStorage -= is.getCount();
|
||||
}
|
||||
} else {
|
||||
maxStorage = 1;
|
||||
}
|
||||
|
||||
// Safe keeping
|
||||
player.setStackInHand(hand, ItemStack.EMPTY);
|
||||
} else {
|
||||
worked = true;
|
||||
|
||||
final int sum = this.countEntitesAround(w, placePos);
|
||||
|
||||
if (sum < AEConfig.instance().getFormationPlaneEntityLimit()) {
|
||||
if (type == Actionable.MODULATE) {
|
||||
is.setCount((int) maxStorage);
|
||||
final double x = (side.xOffset != 0 ? 0 : .7 * (Platform.getRandomFloat() - .5)) + side.xOffset
|
||||
+ .5 + te.getPos().getX();
|
||||
final double y = (side.yOffset != 0 ? 0 : .7 * (Platform.getRandomFloat() - .5)) + side.yOffset
|
||||
+ .5 + te.getPos().getY();
|
||||
final double z = (side.zOffset != 0 ? 0 : .7 * (Platform.getRandomFloat() - .5)) + side.zOffset
|
||||
+ .5 + te.getPos().getZ();
|
||||
|
||||
final ItemEntity ei = new ItemEntity(w, x, y, z, is.copy());
|
||||
|
||||
Entity result = ei;
|
||||
|
||||
ei.setVelocity(side.xOffset * 0.2, side.yOffset * 0.2, side.zOffset * 0.2);
|
||||
|
||||
if (is.getItem().hasCustomEntity(is)) {
|
||||
result = is.getItem().createEntity(w, ei, is);
|
||||
if (result != null) {
|
||||
ei.remove();
|
||||
} else {
|
||||
result = ei;
|
||||
}
|
||||
}
|
||||
|
||||
if (!w.spawnEntity(result)) {
|
||||
result.remove();
|
||||
worked = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
worked = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.blocked = !w.getBlockState(placePos).getMaterial().isReplaceable();
|
||||
|
||||
if (worked) {
|
||||
final IAEItemStack out = input.copy();
|
||||
out.decStackSize(maxStorage);
|
||||
if (out.getStackSize() == 0) {
|
||||
return null;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IStorageChannel<IAEItemStack> getChannel() {
|
||||
return AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPartModel getStaticModels() {
|
||||
return MODELS.getModel(this.isPowered(), this.isActive());
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public IModelData getModelData() {
|
||||
return new PlaneModelData(getConnections());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemStackRepresentation() {
|
||||
return AEApi.instance().definitions().parts().formationPlane().maybeStack(1).orElse(ItemStack.EMPTY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScreenHandlerType<?> getContainerType() {
|
||||
return FormationPlaneContainer.TYPE;
|
||||
}
|
||||
|
||||
private int countEntitesAround(World world, BlockPos pos) {
|
||||
final Box t = new Box(pos).grow(8);
|
||||
final List<Entity> list = world.getEntitiesWithinAABB(Entity.class, t);
|
||||
|
||||
return list.size();
|
||||
}
|
||||
|
||||
private class ForcedItemUseContext extends ItemUsageContext {
|
||||
protected ForcedItemUseContext(World worldIn, @Nullable PlayerEntity player, Hand handIn, ItemStack heldItem,
|
||||
BlockHitResult rayTraceResultIn) {
|
||||
super(worldIn, player, handIn, heldItem, rayTraceResultIn);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.automation;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.enchantment.EnchantmentHelper;
|
||||
import net.minecraft.enchantment.Enchantments;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
|
||||
|
||||
import appeng.api.parts.IPart;
|
||||
import appeng.api.parts.IPartHost;
|
||||
import appeng.api.parts.IPartModel;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
import appeng.items.parts.PartModels;
|
||||
|
||||
public class IdentityAnnihilationPlanePart extends AnnihilationPlanePart {
|
||||
|
||||
private static final PlaneModels MODELS = new PlaneModels("part/identity_annihilation_plane",
|
||||
"part/identity_annihilation_plane_on");
|
||||
|
||||
@PartModels
|
||||
public static List<IPartModel> getModels() {
|
||||
return MODELS.getModels();
|
||||
}
|
||||
|
||||
private static final float SILK_TOUCH_FACTOR = 16;
|
||||
|
||||
public IdentityAnnihilationPlanePart(final ItemStack is) {
|
||||
super(is);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isAnnihilationPlane(final BlockEntity blockTileEntity, final AEPartLocation side) {
|
||||
if (blockTileEntity instanceof IPartHost) {
|
||||
final IPart p = ((IPartHost) blockTileEntity).getPart(side);
|
||||
return p != null && p.getClass() == this.getClass();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float calculateEnergyUsage(final ServerWorld w, final BlockPos pos, final List<ItemStack> items) {
|
||||
final float requiredEnergy = super.calculateEnergyUsage(w, pos, items);
|
||||
|
||||
return requiredEnergy * SILK_TOUCH_FACTOR;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ItemStack createHarvestTool(BlockState state) {
|
||||
ItemStack harvestTool = super.createHarvestTool(state);
|
||||
|
||||
// For silk touch purposes, enchant the fake tool
|
||||
if (harvestTool != null) {
|
||||
EnchantmentHelper.setEnchantments(ImmutableMap.of(Enchantments.SILK_TOUCH, 1), harvestTool);
|
||||
}
|
||||
|
||||
return harvestTool;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPartModel getStaticModels() {
|
||||
return MODELS.getModel(this.isPowered(), this.isActive());
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public IModelData getModelData() {
|
||||
return new PlaneModelData(getConnections());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,276 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.automation;
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.config.Actionable;
|
||||
import appeng.api.config.FuzzyMode;
|
||||
import appeng.api.config.RedstoneMode;
|
||||
import appeng.api.config.Settings;
|
||||
import appeng.api.config.Upgrades;
|
||||
import appeng.api.networking.IGridNode;
|
||||
import appeng.api.networking.energy.IEnergyGrid;
|
||||
import appeng.api.networking.energy.IEnergySource;
|
||||
import appeng.api.networking.security.IActionSource;
|
||||
import appeng.api.networking.ticking.TickRateModulation;
|
||||
import appeng.api.networking.ticking.TickingRequest;
|
||||
import appeng.api.parts.IPartCollisionHelper;
|
||||
import appeng.api.parts.IPartModel;
|
||||
import appeng.api.storage.IMEMonitor;
|
||||
import appeng.api.storage.channels.IItemStorageChannel;
|
||||
import appeng.api.storage.data.IAEItemStack;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.container.ContainerLocator;
|
||||
import appeng.container.ContainerOpener;
|
||||
import appeng.container.implementations.UpgradeableContainer;
|
||||
import appeng.core.AppEng;
|
||||
import appeng.core.settings.TickRates;
|
||||
import appeng.helpers.Reflected;
|
||||
import appeng.items.parts.PartModels;
|
||||
import appeng.me.GridAccessException;
|
||||
import appeng.me.helpers.MachineSource;
|
||||
import appeng.parts.PartModel;
|
||||
import appeng.util.InventoryAdaptor;
|
||||
import appeng.util.Platform;
|
||||
import appeng.util.inv.IInventoryDestination;
|
||||
import appeng.util.item.AEItemStack;
|
||||
|
||||
public class ImportBusPart extends SharedItemBusPart implements IInventoryDestination {
|
||||
|
||||
public static final Identifier MODEL_BASE = new Identifier(AppEng.MOD_ID, "part/import_bus_base");
|
||||
@PartModels
|
||||
public static final IPartModel MODELS_OFF = new PartModel(MODEL_BASE,
|
||||
new Identifier(AppEng.MOD_ID, "part/import_bus_off"));
|
||||
@PartModels
|
||||
public static final IPartModel MODELS_ON = new PartModel(MODEL_BASE,
|
||||
new Identifier(AppEng.MOD_ID, "part/import_bus_on"));
|
||||
@PartModels
|
||||
public static final IPartModel MODELS_HAS_CHANNEL = new PartModel(MODEL_BASE,
|
||||
new Identifier(AppEng.MOD_ID, "part/import_bus_has_channel"));
|
||||
|
||||
private final IActionSource source;
|
||||
private int itemsToSend; // used in tickingRequest
|
||||
private boolean worked; // used in tickingRequest
|
||||
|
||||
@Reflected
|
||||
public ImportBusPart(final ItemStack is) {
|
||||
super(is);
|
||||
|
||||
this.getConfigManager().registerSetting(Settings.REDSTONE_CONTROLLED, RedstoneMode.IGNORE);
|
||||
this.getConfigManager().registerSetting(Settings.FUZZY_MODE, FuzzyMode.IGNORE_ALL);
|
||||
this.source = new MachineSource(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canInsert(final ItemStack stack) {
|
||||
if (stack.isEmpty() || stack.getItem() == Items.AIR) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
final IMEMonitor<IAEItemStack> inv = this.getProxy().getStorage()
|
||||
.getInventory(AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class));
|
||||
|
||||
final IAEItemStack out = inv.injectItems(
|
||||
AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class).createStack(stack),
|
||||
Actionable.SIMULATE, this.source);
|
||||
if (out == null) {
|
||||
return true;
|
||||
}
|
||||
return out.getStackSize() != stack.getCount();
|
||||
} catch (GridAccessException ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getBoxes(final IPartCollisionHelper bch) {
|
||||
bch.addBox(6, 6, 11, 10, 10, 13);
|
||||
bch.addBox(5, 5, 13, 11, 11, 14);
|
||||
bch.addBox(4, 4, 14, 12, 12, 16);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getCableConnectionLength(AECableType cable) {
|
||||
return 5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPartActivate(final PlayerEntity player, final Hand hand, final Vec3d pos) {
|
||||
if (Platform.isServer()) {
|
||||
ContainerOpener.openContainer(UpgradeableContainer.TYPE, player, ContainerLocator.forPart(this));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickingRequest getTickingRequest(final IGridNode node) {
|
||||
return new TickingRequest(TickRates.ImportBus.getMin(), TickRates.ImportBus.getMax(), this.isSleeping(), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickRateModulation tickingRequest(final IGridNode node, final int ticksSinceLastCall) {
|
||||
return this.doBusWork();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TickRateModulation doBusWork() {
|
||||
if (!this.getProxy().isActive() || !this.canDoBusWork()) {
|
||||
return TickRateModulation.IDLE;
|
||||
}
|
||||
|
||||
this.worked = false;
|
||||
|
||||
final InventoryAdaptor myAdaptor = this.getHandler();
|
||||
final FuzzyMode fzMode = (FuzzyMode) this.getConfigManager().getSetting(Settings.FUZZY_MODE);
|
||||
|
||||
if (myAdaptor != null) {
|
||||
try {
|
||||
this.itemsToSend = this.calculateItemsToSend();
|
||||
|
||||
final IMEMonitor<IAEItemStack> inv = this.getProxy().getStorage()
|
||||
.getInventory(AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class));
|
||||
final IEnergyGrid energy = this.getProxy().getEnergy();
|
||||
|
||||
boolean Configured = false;
|
||||
for (int x = 0; x < this.availableSlots(); x++) {
|
||||
final IAEItemStack ais = this.getConfig().getAEStackInSlot(x);
|
||||
if (ais != null && this.itemsToSend > 0) {
|
||||
Configured = true;
|
||||
while (this.itemsToSend > 0) {
|
||||
if (this.importStuff(myAdaptor, ais, inv, energy, fzMode)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!Configured) {
|
||||
while (this.itemsToSend > 0) {
|
||||
if (this.importStuff(myAdaptor, null, inv, energy, fzMode)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (final GridAccessException e) {
|
||||
// :3
|
||||
}
|
||||
} else {
|
||||
return TickRateModulation.SLEEP;
|
||||
}
|
||||
|
||||
return this.worked ? TickRateModulation.FASTER : TickRateModulation.SLOWER;
|
||||
}
|
||||
|
||||
private boolean importStuff(final InventoryAdaptor myAdaptor, final IAEItemStack whatToImport,
|
||||
final IMEMonitor<IAEItemStack> inv, final IEnergySource energy, final FuzzyMode fzMode) {
|
||||
final int toSend = this.calculateMaximumAmountToImport(myAdaptor, whatToImport, inv, fzMode);
|
||||
final ItemStack newItems;
|
||||
|
||||
if (this.getInstalledUpgrades(Upgrades.FUZZY) > 0) {
|
||||
newItems = myAdaptor.removeSimilarItems(toSend,
|
||||
whatToImport == null ? ItemStack.EMPTY : whatToImport.getDefinition(), fzMode, this);
|
||||
} else {
|
||||
newItems = myAdaptor.removeItems(toSend,
|
||||
whatToImport == null ? ItemStack.EMPTY : whatToImport.getDefinition(), this);
|
||||
}
|
||||
|
||||
if (!newItems.isEmpty()) {
|
||||
final IAEItemStack aeStack = AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class)
|
||||
.createStack(newItems);
|
||||
final IAEItemStack failed = Platform.poweredInsert(energy, inv, aeStack, this.source);
|
||||
|
||||
if (failed != null) {
|
||||
// try unpowered insert, better be a bit lenient then void items
|
||||
final IAEItemStack spill = inv.injectItems(failed, Actionable.MODULATE, this.source);
|
||||
if (spill != null) {
|
||||
// last resort try to put it back .. lets hope it's a chest type of thing
|
||||
myAdaptor.addItems(spill.createItemStack());
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
this.itemsToSend -= newItems.getCount();
|
||||
this.worked = true;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private int calculateMaximumAmountToImport(final InventoryAdaptor myAdaptor, final IAEItemStack whatToImport,
|
||||
final IMEMonitor<IAEItemStack> inv, final FuzzyMode fzMode) {
|
||||
final int toSend = Math.min(this.itemsToSend, 64);
|
||||
final ItemStack itemStackToImport;
|
||||
|
||||
if (whatToImport == null) {
|
||||
itemStackToImport = ItemStack.EMPTY;
|
||||
} else {
|
||||
itemStackToImport = whatToImport.getDefinition();
|
||||
}
|
||||
|
||||
final IAEItemStack itemAmountNotStorable;
|
||||
final ItemStack simResult;
|
||||
if (this.getInstalledUpgrades(Upgrades.FUZZY) > 0) {
|
||||
simResult = myAdaptor.simulateSimilarRemove(toSend, itemStackToImport, fzMode, this);
|
||||
itemAmountNotStorable = inv.injectItems(AEItemStack.fromItemStack(simResult), Actionable.SIMULATE,
|
||||
this.source);
|
||||
} else {
|
||||
simResult = myAdaptor.simulateRemove(toSend, itemStackToImport, this);
|
||||
itemAmountNotStorable = inv.injectItems(AEItemStack.fromItemStack(simResult), Actionable.SIMULATE,
|
||||
this.source);
|
||||
}
|
||||
|
||||
if (itemAmountNotStorable != null) {
|
||||
return (int) Math.min(simResult.getCount() - itemAmountNotStorable.getStackSize(), toSend);
|
||||
}
|
||||
|
||||
return toSend;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isSleeping() {
|
||||
return this.getHandler() == null || super.isSleeping();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RedstoneMode getRSMode() {
|
||||
return (RedstoneMode) this.getConfigManager().getSetting(Settings.REDSTONE_CONTROLLED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPartModel getStaticModels() {
|
||||
if (this.isActive() && this.isPowered()) {
|
||||
return MODELS_HAS_CHANNEL;
|
||||
} else if (this.isPowered()) {
|
||||
return MODELS_ON;
|
||||
} else {
|
||||
return MODELS_OFF;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,498 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.automation;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Random;
|
||||
|
||||
import alexiil.mc.lib.attributes.item.FixedItemInv;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.inventory.CraftingInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.particle.DustParticleEffect;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.config.FuzzyMode;
|
||||
import appeng.api.config.LevelType;
|
||||
import appeng.api.config.RedstoneMode;
|
||||
import appeng.api.config.Settings;
|
||||
import appeng.api.config.Upgrades;
|
||||
import appeng.api.config.YesNo;
|
||||
import appeng.api.networking.crafting.ICraftingGrid;
|
||||
import appeng.api.networking.crafting.ICraftingPatternDetails;
|
||||
import appeng.api.networking.crafting.ICraftingProvider;
|
||||
import appeng.api.networking.crafting.ICraftingProviderHelper;
|
||||
import appeng.api.networking.crafting.ICraftingWatcher;
|
||||
import appeng.api.networking.crafting.ICraftingWatcherHost;
|
||||
import appeng.api.networking.energy.IEnergyGrid;
|
||||
import appeng.api.networking.energy.IEnergyWatcher;
|
||||
import appeng.api.networking.energy.IEnergyWatcherHost;
|
||||
import appeng.api.networking.events.MENetworkChannelsChanged;
|
||||
import appeng.api.networking.events.MENetworkCraftingPatternChange;
|
||||
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.IItemStorageChannel;
|
||||
import appeng.api.storage.data.IAEItemStack;
|
||||
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.container.ContainerLocator;
|
||||
import appeng.container.ContainerOpener;
|
||||
import appeng.container.implementations.LevelEmitterContainer;
|
||||
import appeng.core.AppEng;
|
||||
import appeng.helpers.Reflected;
|
||||
import appeng.items.parts.PartModels;
|
||||
import appeng.me.GridAccessException;
|
||||
import appeng.parts.PartModel;
|
||||
import appeng.tile.inventory.AppEngInternalAEInventory;
|
||||
import appeng.util.Platform;
|
||||
import appeng.util.inv.InvOperation;
|
||||
|
||||
public class LevelEmitterPart extends UpgradeablePart implements IEnergyWatcherHost, IStackWatcherHost,
|
||||
ICraftingWatcherHost, IMEMonitorHandlerReceiver<IAEItemStack>, ICraftingProvider {
|
||||
|
||||
@PartModels
|
||||
public static final Identifier MODEL_BASE_OFF = new Identifier(AppEng.MOD_ID,
|
||||
"part/level_emitter_base_off");
|
||||
@PartModels
|
||||
public static final Identifier MODEL_BASE_ON = new Identifier(AppEng.MOD_ID,
|
||||
"part/level_emitter_base_on");
|
||||
@PartModels
|
||||
public static final Identifier MODEL_STATUS_OFF = new Identifier(AppEng.MOD_ID,
|
||||
"part/level_emitter_status_off");
|
||||
@PartModels
|
||||
public static final Identifier MODEL_STATUS_ON = new Identifier(AppEng.MOD_ID,
|
||||
"part/level_emitter_status_on");
|
||||
@PartModels
|
||||
public static final Identifier MODEL_STATUS_HAS_CHANNEL = new Identifier(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 final AppEngInternalAEInventory config = new AppEngInternalAEInventory(this, 1);
|
||||
|
||||
private boolean prevState = false;
|
||||
|
||||
private long lastReportedValue = 0;
|
||||
private long reportingValue = 0;
|
||||
|
||||
private IStackWatcher myWatcher;
|
||||
private IEnergyWatcher myEnergyWatcher;
|
||||
private ICraftingWatcher myCraftingWatcher;
|
||||
private double centerX;
|
||||
private double centerY;
|
||||
private double centerZ;
|
||||
|
||||
@Reflected
|
||||
public LevelEmitterPart(final ItemStack is) {
|
||||
super(is);
|
||||
|
||||
this.getConfigManager().registerSetting(Settings.REDSTONE_EMITTER, RedstoneMode.HIGH_SIGNAL);
|
||||
this.getConfigManager().registerSetting(Settings.FUZZY_MODE, FuzzyMode.IGNORE_ALL);
|
||||
this.getConfigManager().registerSetting(Settings.LEVEL_TYPE, LevelType.ITEM_LEVEL);
|
||||
this.getConfigManager().registerSetting(Settings.CRAFT_VIA_REDSTONE, YesNo.NO);
|
||||
}
|
||||
|
||||
public long getReportingValue() {
|
||||
return this.reportingValue;
|
||||
}
|
||||
|
||||
public void setReportingValue(final long v) {
|
||||
this.reportingValue = v;
|
||||
if (this.getConfigManager().getSetting(Settings.LEVEL_TYPE) == LevelType.ENERGY_LEVEL) {
|
||||
this.configureWatchers();
|
||||
} else {
|
||||
this.updateState();
|
||||
}
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void powerChanged(final MENetworkPowerStatusChange c) {
|
||||
this.updateState();
|
||||
}
|
||||
|
||||
private void updateState() {
|
||||
final boolean isOn = this.isLevelEmitterOn();
|
||||
if (this.prevState != isOn) {
|
||||
this.getHost().markForUpdate();
|
||||
final BlockEntity te = this.getHost().getTile();
|
||||
this.prevState = isOn;
|
||||
Platform.notifyBlocksOfNeighbors(te.getWorld(), te.getPos());
|
||||
Platform.notifyBlocksOfNeighbors(te.getWorld(), te.getPos().offset(this.getSide().getFacing()));
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Make private again
|
||||
public boolean isLevelEmitterOn() {
|
||||
if (Platform.isClient()) {
|
||||
return (this.getClientFlags() & FLAG_ON) == FLAG_ON;
|
||||
}
|
||||
|
||||
if (!this.getProxy().isActive()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.getInstalledUpgrades(Upgrades.CRAFTING) > 0) {
|
||||
try {
|
||||
return this.getProxy().getCrafting().isRequesting(this.config.getAEStackInSlot(0));
|
||||
} catch (final GridAccessException e) {
|
||||
// :P
|
||||
}
|
||||
|
||||
return this.prevState;
|
||||
}
|
||||
|
||||
final boolean flipState = this.getConfigManager()
|
||||
.getSetting(Settings.REDSTONE_EMITTER) == RedstoneMode.LOW_SIGNAL;
|
||||
return flipState ? this.reportingValue >= this.lastReportedValue + 1
|
||||
: this.reportingValue < this.lastReportedValue + 1;
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void channelChanged(final MENetworkChannelsChanged c) {
|
||||
this.updateState();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int populateFlags(final int cf) {
|
||||
return cf | (this.prevState ? FLAG_ON : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateWatcher(final ICraftingWatcher newWatcher) {
|
||||
this.myCraftingWatcher = newWatcher;
|
||||
this.configureWatchers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestChange(final ICraftingGrid craftingGrid, final IAEItemStack what) {
|
||||
this.updateState();
|
||||
}
|
||||
|
||||
// update the system...
|
||||
private void configureWatchers() {
|
||||
final IAEItemStack myStack = this.config.getAEStackInSlot(0);
|
||||
|
||||
if (this.myWatcher != null) {
|
||||
this.myWatcher.reset();
|
||||
}
|
||||
|
||||
if (this.myEnergyWatcher != null) {
|
||||
this.myEnergyWatcher.reset();
|
||||
}
|
||||
|
||||
if (this.myCraftingWatcher != null) {
|
||||
this.myCraftingWatcher.reset();
|
||||
}
|
||||
|
||||
try {
|
||||
this.getProxy().getGrid().postEvent(new MENetworkCraftingPatternChange(this, this.getProxy().getNode()));
|
||||
} catch (final GridAccessException e1) {
|
||||
// :/
|
||||
}
|
||||
|
||||
if (this.getInstalledUpgrades(Upgrades.CRAFTING) > 0) {
|
||||
if (this.myCraftingWatcher != null && myStack != null) {
|
||||
this.myCraftingWatcher.add(myStack);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.getConfigManager().getSetting(Settings.LEVEL_TYPE) == LevelType.ENERGY_LEVEL) {
|
||||
if (this.myEnergyWatcher != null) {
|
||||
this.myEnergyWatcher.add(this.reportingValue);
|
||||
}
|
||||
|
||||
try {
|
||||
// update to power...
|
||||
this.lastReportedValue = (long) this.getProxy().getEnergy().getStoredPower();
|
||||
this.updateState();
|
||||
|
||||
// no more item stuff..
|
||||
this.getProxy().getStorage()
|
||||
.getInventory(AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class))
|
||||
.removeListener(this);
|
||||
} catch (final GridAccessException e) {
|
||||
// :P
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (this.getInstalledUpgrades(Upgrades.FUZZY) > 0 || myStack == null) {
|
||||
this.getProxy().getStorage()
|
||||
.getInventory(AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class))
|
||||
.addListener(this, this.getProxy().getGrid());
|
||||
} else {
|
||||
this.getProxy().getStorage()
|
||||
.getInventory(AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class))
|
||||
.removeListener(this);
|
||||
|
||||
if (this.myWatcher != null) {
|
||||
this.myWatcher.add(myStack);
|
||||
}
|
||||
}
|
||||
|
||||
this.updateReportingValue(this.getProxy().getStorage()
|
||||
.getInventory(AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class)));
|
||||
} catch (final GridAccessException e) {
|
||||
// >.>
|
||||
}
|
||||
}
|
||||
|
||||
private void updateReportingValue(final IMEMonitor<IAEItemStack> monitor) {
|
||||
final IAEItemStack myStack = this.config.getAEStackInSlot(0);
|
||||
|
||||
if (myStack == null) {
|
||||
this.lastReportedValue = 0;
|
||||
for (final IAEItemStack st : monitor.getStorageList()) {
|
||||
this.lastReportedValue += st.getStackSize();
|
||||
}
|
||||
} else if (this.getInstalledUpgrades(Upgrades.FUZZY) > 0) {
|
||||
this.lastReportedValue = 0;
|
||||
final FuzzyMode fzMode = (FuzzyMode) this.getConfigManager().getSetting(Settings.FUZZY_MODE);
|
||||
final Collection<IAEItemStack> fuzzyList = monitor.getStorageList().findFuzzy(myStack, fzMode);
|
||||
for (final IAEItemStack st : fuzzyList) {
|
||||
this.lastReportedValue += st.getStackSize();
|
||||
}
|
||||
} else {
|
||||
final IAEItemStack r = monitor.getStorageList().findPrecise(myStack);
|
||||
if (r == null) {
|
||||
this.lastReportedValue = 0;
|
||||
} else {
|
||||
this.lastReportedValue = r.getStackSize();
|
||||
}
|
||||
}
|
||||
|
||||
this.updateState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateWatcher(final IStackWatcher newWatcher) {
|
||||
this.myWatcher = newWatcher;
|
||||
this.configureWatchers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStackChange(final IItemList o, final IAEStack fullStack, final IAEStack diffStack,
|
||||
final IActionSource src, final IStorageChannel chan) {
|
||||
if (chan == AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class)
|
||||
&& fullStack.equals(this.config.getAEStackInSlot(0))
|
||||
&& this.getInstalledUpgrades(Upgrades.FUZZY) == 0) {
|
||||
this.lastReportedValue = fullStack.getStackSize();
|
||||
this.updateState();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateWatcher(final IEnergyWatcher newWatcher) {
|
||||
this.myEnergyWatcher = newWatcher;
|
||||
this.configureWatchers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onThresholdPass(final IEnergyGrid energyGrid) {
|
||||
this.lastReportedValue = (long) energyGrid.getStoredPower();
|
||||
this.updateState();
|
||||
}
|
||||
|
||||
@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<IAEItemStack> monitor, final Iterable<IAEItemStack> change,
|
||||
final IActionSource actionSource) {
|
||||
this.updateReportingValue((IMEMonitor<IAEItemStack>) monitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onListUpdate() {
|
||||
try {
|
||||
this.updateReportingValue(this.getProxy().getStorage()
|
||||
.getInventory(AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class)));
|
||||
} catch (final GridAccessException e) {
|
||||
// ;P
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AECableType getCableConnectionType(final AEPartLocation dir) {
|
||||
return AECableType.SMART;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getBoxes(final IPartCollisionHelper bch) {
|
||||
bch.addBox(7, 7, 11, 9, 9, 16);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int isProvidingStrongPower() {
|
||||
return this.prevState ? 15 : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int isProvidingWeakPower() {
|
||||
return this.prevState ? 15 : 0;
|
||||
}
|
||||
|
||||
@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.addParticle(DustParticleEffect.REDSTONE_DUST, 0.5 + pos.getX() + d0, 0.5 + pos.getY() + d1,
|
||||
0.5 + pos.getZ() + d2, 0.0D, 0.0D, 0.0D);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getCableConnectionLength(AECableType cable) {
|
||||
return 16;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPartActivate(final PlayerEntity player, final Hand hand, final Vec3d pos) {
|
||||
if (Platform.isServer()) {
|
||||
ContainerOpener.openContainer(LevelEmitterContainer.TYPE, player, ContainerLocator.forPart(this));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSetting(final IConfigManager manager, final Settings settingName, final Enum<?> newValue) {
|
||||
this.configureWatchers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeInventory(final FixedItemInv inv, final int slot, final InvOperation mc,
|
||||
final ItemStack removedStack, final ItemStack newStack) {
|
||||
if (inv == this.config) {
|
||||
this.configureWatchers();
|
||||
}
|
||||
|
||||
super.onChangeInventory(inv, slot, mc, removedStack, newStack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void upgradesChanged() {
|
||||
this.configureWatchers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canConnectRedstone() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromNBT(final CompoundTag 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 CompoundTag data) {
|
||||
super.writeToNBT(data);
|
||||
data.putLong("lastReportedValue", this.lastReportedValue);
|
||||
data.putLong("reportingValue", this.reportingValue);
|
||||
data.putBoolean("prevState", this.prevState);
|
||||
this.config.writeToNBT(data, "config");
|
||||
}
|
||||
|
||||
@Override
|
||||
public FixedItemInv getInventoryByName(final String name) {
|
||||
if (name.equals("config")) {
|
||||
return this.config;
|
||||
}
|
||||
|
||||
return super.getInventoryByName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean pushPattern(final ICraftingPatternDetails patternDetails, final CraftingInventory table) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBusy() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void provideCrafting(final ICraftingProviderHelper craftingTracker) {
|
||||
if (this.getInstalledUpgrades(Upgrades.CRAFTING) > 0) {
|
||||
if (this.getConfigManager().getSetting(Settings.CRAFT_VIA_REDSTONE) == YesNo.YES) {
|
||||
final IAEItemStack what = this.config.getAEStackInSlot(0);
|
||||
if (what != null) {
|
||||
craftingTracker.setEmitable(what);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2015, 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.parts.automation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.render.model.BakedQuad;
|
||||
import net.minecraft.client.render.model.json.ModelOverrideList;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraftforge.client.model.data.IDynamicBakedModel;
|
||||
|
||||
|
||||
import appeng.client.render.cablebus.CubeBuilder;
|
||||
|
||||
/**
|
||||
* Built-in model for annihilation planes that supports connected textures.
|
||||
*/
|
||||
public class PlaneBakedModel implements IDynamicBakedModel {
|
||||
|
||||
private static final PlaneConnections DEFAULT_PERMUTATION = PlaneConnections.of(false, false, false, false);
|
||||
|
||||
private final Sprite frontTexture;
|
||||
|
||||
private final Map<PlaneConnections, List<BakedQuad>> quads;
|
||||
|
||||
PlaneBakedModel(Sprite frontTexture, Sprite sidesTexture, Sprite backTexture) {
|
||||
this.frontTexture = frontTexture;
|
||||
|
||||
quads = new HashMap<>(PlaneConnections.PERMUTATIONS.size());
|
||||
// Create all possible permutations (16)
|
||||
for (PlaneConnections permutation : PlaneConnections.PERMUTATIONS) {
|
||||
List<BakedQuad> quads = new ArrayList<>(4 * 6);
|
||||
|
||||
CubeBuilder builder = new CubeBuilder(quads);
|
||||
|
||||
builder.setTextures(sidesTexture, sidesTexture, frontTexture, backTexture, sidesTexture, sidesTexture);
|
||||
|
||||
// Keep the orientation of the X axis in mind here. When looking at a quad
|
||||
// facing north from the front,
|
||||
// The X-axis points left
|
||||
int minX = permutation.isRight() ? 0 : 1;
|
||||
int maxX = permutation.isLeft() ? 16 : 15;
|
||||
int minY = permutation.isDown() ? 0 : 1;
|
||||
int maxY = permutation.isUp() ? 16 : 15;
|
||||
|
||||
builder.addCube(minX, minY, 0, maxX, maxY, 1);
|
||||
|
||||
this.quads.put(permutation, ImmutableList.copyOf(quads));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand,
|
||||
IModelData modelData) {
|
||||
if (side == null) {
|
||||
PlaneConnections connections = DEFAULT_PERMUTATION;
|
||||
if (modelData instanceof PlaneModelData) {
|
||||
connections = ((PlaneModelData) modelData).getConnections();
|
||||
}
|
||||
return this.quads.get(connections);
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useAmbientOcclusion() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDepth() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSideLit() {
|
||||
return false;// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBuiltin() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sprite getSprite() {
|
||||
return this.frontTexture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelOverrideList getOverrides() {
|
||||
return ModelOverrideList.EMPTY;
|
||||
}
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2015, 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.parts.automation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
|
||||
/**
|
||||
* Models in which directions - looking at the front face - a plane
|
||||
* (annihilation, formation, etc.) is connected to other planes of the same
|
||||
* type.
|
||||
*/
|
||||
public final class PlaneConnections {
|
||||
|
||||
private final boolean up;
|
||||
private final boolean right;
|
||||
private final boolean down;
|
||||
private final boolean left;
|
||||
|
||||
private static final int BITMASK_UP = 8;
|
||||
private static final int BITMASK_RIGHT = 4;
|
||||
private static final int BITMASK_DOWN = 2;
|
||||
private static final int BITMASK_LEFT = 1;
|
||||
|
||||
public static final List<PlaneConnections> PERMUTATIONS = generatePermutations();
|
||||
|
||||
private static List<PlaneConnections> generatePermutations() {
|
||||
List<PlaneConnections> connections = new ArrayList<>(16);
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
boolean up = (i & BITMASK_UP) != 0;
|
||||
boolean right = (i & BITMASK_RIGHT) != 0;
|
||||
boolean down = (i & BITMASK_DOWN) != 0;
|
||||
boolean left = (i & BITMASK_LEFT) != 0;
|
||||
|
||||
connections.add(new PlaneConnections(up, right, down, left));
|
||||
}
|
||||
|
||||
return connections;
|
||||
}
|
||||
|
||||
private PlaneConnections(boolean up, boolean right, boolean down, boolean left) {
|
||||
this.up = up;
|
||||
this.right = right;
|
||||
this.down = down;
|
||||
this.left = left;
|
||||
}
|
||||
|
||||
public static PlaneConnections of(boolean up, boolean right, boolean down, boolean left) {
|
||||
return PERMUTATIONS.get(getIndex(up, right, down, left));
|
||||
}
|
||||
|
||||
public boolean isUp() {
|
||||
return this.up;
|
||||
}
|
||||
|
||||
public boolean isRight() {
|
||||
return this.right;
|
||||
}
|
||||
|
||||
public boolean isDown() {
|
||||
return this.down;
|
||||
}
|
||||
|
||||
public boolean isLeft() {
|
||||
return this.left;
|
||||
}
|
||||
|
||||
// The combination of connections expressed as a number ranging from [0,15]
|
||||
public int getIndex() {
|
||||
return getIndex(this.up, this.right, this.down, this.left);
|
||||
}
|
||||
|
||||
private static int getIndex(boolean up, boolean right, boolean down, boolean left) {
|
||||
return (up ? BITMASK_UP : 0) + (right ? BITMASK_RIGHT : 0) + (left ? BITMASK_LEFT : 0)
|
||||
+ (down ? BITMASK_DOWN : 0);
|
||||
}
|
||||
|
||||
// Returns a suffix that expresses the connection states as a string
|
||||
public String getFilenameSuffix() {
|
||||
String suffix = Integer.toBinaryString(this.getIndex());
|
||||
return Strings.padStart(suffix, 4, '0');
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || this.getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PlaneConnections that = (PlaneConnections) o;
|
||||
return this.up == that.up && this.right == that.right && this.down == that.down && this.left == that.left;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = (this.up ? 1 : 0);
|
||||
result = 31 * result + (this.right ? 1 : 0);
|
||||
result = 31 * result + (this.down ? 1 : 0);
|
||||
result = 31 * result + (this.left ? 1 : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2015, 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.parts.automation;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.model.IModelTransform;
|
||||
import net.minecraft.client.render.model.IUnbakedModel;
|
||||
import net.minecraft.client.render.model.json.ModelOverrideList;
|
||||
import net.minecraft.client.util.SpriteIdentifier;
|
||||
import net.minecraft.client.render.model.ModelLoader;
|
||||
import net.minecraft.client.texture.SpriteAtlasTexture;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraftforge.client.model.IModelConfiguration;
|
||||
import net.minecraftforge.client.model.geometry.IModelGeometry;
|
||||
|
||||
/**
|
||||
* Built-in model for annihilation planes that supports connected textures.
|
||||
*/
|
||||
public class PlaneModel implements IModelGeometry<PlaneModel> {
|
||||
|
||||
private final SpriteIdentifier frontTexture;
|
||||
private final SpriteIdentifier sidesTexture;
|
||||
private final SpriteIdentifier backTexture;
|
||||
|
||||
public PlaneModel(Identifier frontTexture, Identifier sidesTexture, Identifier backTexture) {
|
||||
this.frontTexture = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX, frontTexture);
|
||||
this.sidesTexture = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX, sidesTexture);
|
||||
this.backTexture = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX, backTexture);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BakedModel bake(IModelConfiguration owner, ModelLoader bakery,
|
||||
Function<SpriteIdentifier, Sprite> spriteGetter, IModelTransform modelTransform,
|
||||
ModelOverrideList overrides, Identifier modelLocation) {
|
||||
Sprite frontSprite = spriteGetter.apply(this.frontTexture);
|
||||
Sprite sidesSprite = spriteGetter.apply(this.sidesTexture);
|
||||
Sprite backSprite = spriteGetter.apply(this.backTexture);
|
||||
|
||||
return new PlaneBakedModel(frontSprite, sidesSprite, backSprite);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<SpriteIdentifier> getTextures(IModelConfiguration owner,
|
||||
Function<Identifier, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
|
||||
return Arrays.asList(frontTexture, sidesTexture, backTexture);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package appeng.parts.automation;
|
||||
|
||||
import appeng.client.render.model.AEInternalModelData;
|
||||
|
||||
public class PlaneModelData extends AEInternalModelData {
|
||||
|
||||
private final PlaneConnections connections;
|
||||
|
||||
public PlaneModelData(PlaneConnections connections) {
|
||||
this.connections = connections;
|
||||
}
|
||||
|
||||
public PlaneConnections getConnections() {
|
||||
return connections;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package appeng.parts.automation;
|
||||
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import net.minecraft.resources.IResourceManager;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraftforge.client.model.IModelLoader;
|
||||
|
||||
public class PlaneModelLoader implements IModelLoader<PlaneModel> {
|
||||
|
||||
public static final PlaneModelLoader INSTANCE = new PlaneModelLoader();
|
||||
|
||||
@Override
|
||||
public void onResourceManagerReload(IResourceManager resourceManager) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlaneModel read(JsonDeserializationContext deserializationContext, JsonObject modelContents) {
|
||||
String frontTexture = modelContents.get("front").getAsString();
|
||||
String sidesTexture = modelContents.get("sides").getAsString();
|
||||
String backTexture = modelContents.get("back").getAsString();
|
||||
|
||||
return new PlaneModel(new Identifier(frontTexture), new Identifier(sidesTexture),
|
||||
new Identifier(backTexture));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2015, 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.parts.automation;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import appeng.api.parts.IPartModel;
|
||||
import appeng.core.AppEng;
|
||||
import appeng.parts.PartModel;
|
||||
|
||||
/**
|
||||
* Contains a mapping from a Plane's connections to the models to use for that
|
||||
* state.
|
||||
*/
|
||||
public class PlaneModels {
|
||||
|
||||
public static final Identifier MODEL_CHASSIS_OFF = new Identifier(AppEng.MOD_ID,
|
||||
"part/transition_plane_off");
|
||||
public static final Identifier MODEL_CHASSIS_ON = new Identifier(AppEng.MOD_ID,
|
||||
"part/transition_plane_on");
|
||||
public static final Identifier MODEL_CHASSIS_HAS_CHANNEL = new Identifier(AppEng.MOD_ID,
|
||||
"part/transition_plane_has_channel");
|
||||
|
||||
private final IPartModel modelOff;
|
||||
|
||||
private final IPartModel modelOn;
|
||||
|
||||
private final IPartModel modelHasChannel;
|
||||
|
||||
public PlaneModels(String planeOffLocation, String planeOnLocation) {
|
||||
Identifier planeOff = new Identifier(AppEng.MOD_ID, planeOffLocation);
|
||||
Identifier planeOn = new Identifier(AppEng.MOD_ID, planeOnLocation);
|
||||
|
||||
this.modelOff = new PartModel(MODEL_CHASSIS_OFF, planeOff);
|
||||
this.modelOn = new PartModel(MODEL_CHASSIS_ON, planeOff);
|
||||
this.modelHasChannel = new PartModel(MODEL_CHASSIS_HAS_CHANNEL, planeOn);
|
||||
}
|
||||
|
||||
public IPartModel getModel(boolean hasPower, boolean hasChannel) {
|
||||
if (hasPower && hasChannel) {
|
||||
return modelHasChannel;
|
||||
} else if (hasPower) {
|
||||
return modelOn;
|
||||
} else {
|
||||
return modelOff;
|
||||
}
|
||||
}
|
||||
|
||||
public List<IPartModel> getModels() {
|
||||
return ImmutableList.of(modelOff, modelOn, modelHasChannel);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,152 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.automation;
|
||||
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraft.world.World;
|
||||
import alexiil.mc.lib.attributes.item.FixedItemInv;
|
||||
|
||||
import appeng.api.config.RedstoneMode;
|
||||
import appeng.api.config.Upgrades;
|
||||
import appeng.api.networking.ticking.IGridTickable;
|
||||
import appeng.api.networking.ticking.TickRateModulation;
|
||||
import appeng.me.GridAccessException;
|
||||
import appeng.tile.inventory.AppEngInternalAEInventory;
|
||||
import appeng.util.InventoryAdaptor;
|
||||
|
||||
public abstract class SharedItemBusPart extends UpgradeablePart implements IGridTickable {
|
||||
|
||||
private final AppEngInternalAEInventory config = new AppEngInternalAEInventory(this, 9);
|
||||
private boolean lastRedstone = false;
|
||||
|
||||
public SharedItemBusPart(final ItemStack is) {
|
||||
super(is);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void upgradesChanged() {
|
||||
this.updateState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromNBT(final net.minecraft.nbt.CompoundTag extra) {
|
||||
super.readFromNBT(extra);
|
||||
this.getConfig().readFromNBT(extra, "config");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToNBT(final net.minecraft.nbt.CompoundTag extra) {
|
||||
super.writeToNBT(extra);
|
||||
this.getConfig().writeToNBT(extra, "config");
|
||||
}
|
||||
|
||||
@Override
|
||||
public FixedItemInv getInventoryByName(final String name) {
|
||||
if (name.equals("config")) {
|
||||
return this.getConfig();
|
||||
}
|
||||
|
||||
return super.getInventoryByName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onneighborUpdate(BlockView w, BlockPos pos, BlockPos neighbor) {
|
||||
this.updateState();
|
||||
if (this.lastRedstone != this.getHost().hasRedstone(this.getSide())) {
|
||||
this.lastRedstone = !this.lastRedstone;
|
||||
if (this.lastRedstone && this.getRSMode() == RedstoneMode.SIGNAL_PULSE) {
|
||||
this.doBusWork();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected InventoryAdaptor getHandler() {
|
||||
final BlockEntity self = this.getHost().getTile();
|
||||
final BlockEntity target = this.getBlockEntity(self, self.getPos().offset(this.getSide().getFacing()));
|
||||
|
||||
return InventoryAdaptor.getAdaptor(target, this.getSide().getFacing().getOpposite());
|
||||
}
|
||||
|
||||
private BlockEntity getBlockEntity(final BlockEntity self, final BlockPos pos) {
|
||||
final World w = self.getWorld();
|
||||
|
||||
if (w.getChunkManager().isChunkLoaded(new ChunkPos(pos))) {
|
||||
return w.getBlockEntity(pos);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected int availableSlots() {
|
||||
return Math.min(1 + this.getInstalledUpgrades(Upgrades.CAPACITY) * 4, this.getConfig().getSlotCount());
|
||||
}
|
||||
|
||||
protected int calculateItemsToSend() {
|
||||
switch (this.getInstalledUpgrades(Upgrades.SPEED)) {
|
||||
default:
|
||||
case 0:
|
||||
return 1;
|
||||
case 1:
|
||||
return 8;
|
||||
case 2:
|
||||
return 32;
|
||||
case 3:
|
||||
return 64;
|
||||
case 4:
|
||||
return 96;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the bus can actually do something.
|
||||
*
|
||||
* Currently this tests if the chunk for the target is actually loaded.
|
||||
*
|
||||
* @return true, if the the bus should do its work.
|
||||
*/
|
||||
protected boolean canDoBusWork() {
|
||||
final BlockEntity self = this.getHost().getTile();
|
||||
final BlockPos selfPos = self.getPos().offset(this.getSide().getFacing());
|
||||
final World world = self.getWorld();
|
||||
|
||||
return world != null && world.getChunkManager().isChunkLoaded(new ChunkPos(selfPos));
|
||||
}
|
||||
|
||||
private void updateState() {
|
||||
try {
|
||||
if (!this.isSleeping()) {
|
||||
this.getProxy().getTick().wakeDevice(this.getProxy().getNode());
|
||||
} else {
|
||||
this.getProxy().getTick().sleepDevice(this.getProxy().getNode());
|
||||
}
|
||||
} catch (final GridAccessException e) {
|
||||
// :P
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract TickRateModulation doBusWork();
|
||||
|
||||
AppEngInternalAEInventory getConfig() {
|
||||
return this.config;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2015, 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.parts.automation;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import appeng.api.config.Upgrades;
|
||||
import appeng.util.inv.IAEAppEngInventory;
|
||||
|
||||
public class StackUpgradeInventory extends UpgradeInventory {
|
||||
private final ItemStack stack;
|
||||
|
||||
public StackUpgradeInventory(final ItemStack stack, final IAEAppEngInventory inventory, final int s) {
|
||||
super(inventory, s);
|
||||
this.stack = stack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxInstalled(final Upgrades upgrades) {
|
||||
for (final Upgrades.Supported supported : upgrades.getSupported()) {
|
||||
if (supported.isSupported(stack.getItem())) {
|
||||
return supported.getMaxCount();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.automation;
|
||||
|
||||
import alexiil.mc.lib.attributes.item.FixedItemInv;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
|
||||
import appeng.api.config.Upgrades;
|
||||
import appeng.api.implementations.items.IUpgradeModule;
|
||||
import appeng.tile.inventory.AppEngInternalInventory;
|
||||
import appeng.util.Platform;
|
||||
import appeng.util.inv.IAEAppEngInventory;
|
||||
import appeng.util.inv.InvOperation;
|
||||
import appeng.util.inv.filter.IAEItemFilter;
|
||||
|
||||
public abstract class UpgradeInventory extends AppEngInternalInventory implements IAEAppEngInventory {
|
||||
private final IAEAppEngInventory parent;
|
||||
|
||||
private boolean cached = false;
|
||||
private int fuzzyUpgrades = 0;
|
||||
private int speedUpgrades = 0;
|
||||
private int redstoneUpgrades = 0;
|
||||
private int capacityUpgrades = 0;
|
||||
private int inverterUpgrades = 0;
|
||||
private int craftingUpgrades = 0;
|
||||
|
||||
public UpgradeInventory(final IAEAppEngInventory parent, final int s) {
|
||||
super(null, s, 1);
|
||||
this.setTileEntity(this);
|
||||
this.parent = parent;
|
||||
this.setFilter(new UpgradeInvFilter());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean eventsEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public int getInstalledUpgrades(final Upgrades u) {
|
||||
if (!this.cached) {
|
||||
this.updateUpgradeInfo();
|
||||
}
|
||||
|
||||
switch (u) {
|
||||
case CAPACITY:
|
||||
return this.capacityUpgrades;
|
||||
case FUZZY:
|
||||
return this.fuzzyUpgrades;
|
||||
case REDSTONE:
|
||||
return this.redstoneUpgrades;
|
||||
case SPEED:
|
||||
return this.speedUpgrades;
|
||||
case INVERTER:
|
||||
return this.inverterUpgrades;
|
||||
case CRAFTING:
|
||||
return this.craftingUpgrades;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract int getMaxInstalled(Upgrades upgrades);
|
||||
|
||||
private void updateUpgradeInfo() {
|
||||
this.cached = true;
|
||||
this.inverterUpgrades = this.capacityUpgrades = this.redstoneUpgrades = this.speedUpgrades = this.fuzzyUpgrades = this.craftingUpgrades = 0;
|
||||
|
||||
for (final ItemStack is : this) {
|
||||
if (is == null || is.getItem() == Items.AIR || !(is.getItem() instanceof IUpgradeModule)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final Upgrades myUpgrade = ((IUpgradeModule) is.getItem()).getType(is);
|
||||
switch (myUpgrade) {
|
||||
case CAPACITY:
|
||||
this.capacityUpgrades++;
|
||||
break;
|
||||
case FUZZY:
|
||||
this.fuzzyUpgrades++;
|
||||
break;
|
||||
case REDSTONE:
|
||||
this.redstoneUpgrades++;
|
||||
break;
|
||||
case SPEED:
|
||||
this.speedUpgrades++;
|
||||
break;
|
||||
case INVERTER:
|
||||
this.inverterUpgrades++;
|
||||
break;
|
||||
case CRAFTING:
|
||||
this.craftingUpgrades++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.capacityUpgrades = Math.min(this.capacityUpgrades, this.getMaxInstalled(Upgrades.CAPACITY));
|
||||
this.fuzzyUpgrades = Math.min(this.fuzzyUpgrades, this.getMaxInstalled(Upgrades.FUZZY));
|
||||
this.redstoneUpgrades = Math.min(this.redstoneUpgrades, this.getMaxInstalled(Upgrades.REDSTONE));
|
||||
this.speedUpgrades = Math.min(this.speedUpgrades, this.getMaxInstalled(Upgrades.SPEED));
|
||||
this.inverterUpgrades = Math.min(this.inverterUpgrades, this.getMaxInstalled(Upgrades.INVERTER));
|
||||
this.craftingUpgrades = Math.min(this.craftingUpgrades, this.getMaxInstalled(Upgrades.CRAFTING));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromNBT(final CompoundTag target) {
|
||||
super.readFromNBT(target);
|
||||
this.updateUpgradeInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveChanges() {
|
||||
if (this.parent != null) {
|
||||
this.parent.saveChanges();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeInventory(final FixedItemInv inv, final int slot, final InvOperation mc,
|
||||
final ItemStack removedStack, final ItemStack newStack) {
|
||||
this.cached = false;
|
||||
if (this.parent != null && Platform.isServer()) {
|
||||
this.parent.onChangeInventory(inv, slot, mc, removedStack, newStack);
|
||||
}
|
||||
}
|
||||
|
||||
private class UpgradeInvFilter implements IAEItemFilter {
|
||||
|
||||
@Override
|
||||
public boolean allowExtract(FixedItemInv inv, int slot, int amount) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowInsert(FixedItemInv inv, int slot, ItemStack itemstack) {
|
||||
if (itemstack.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
final Item it = itemstack.getItem();
|
||||
if (it instanceof IUpgradeModule) {
|
||||
final Upgrades u = ((IUpgradeModule) it).getType(itemstack);
|
||||
if (u != null) {
|
||||
return UpgradeInventory.this.getInstalledUpgrades(u) < UpgradeInventory.this.getMaxInstalled(u);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,148 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.automation;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import alexiil.mc.lib.attributes.item.FixedItemInv;
|
||||
|
||||
import appeng.api.config.RedstoneMode;
|
||||
import appeng.api.config.Settings;
|
||||
import appeng.api.config.Upgrades;
|
||||
import appeng.api.util.IConfigManager;
|
||||
import appeng.parts.BasicStatePart;
|
||||
import appeng.util.ConfigManager;
|
||||
import appeng.util.IConfigManagerHost;
|
||||
import appeng.util.inv.IAEAppEngInventory;
|
||||
import appeng.util.inv.InvOperation;
|
||||
|
||||
public abstract class UpgradeablePart extends BasicStatePart implements IAEAppEngInventory, IConfigManagerHost {
|
||||
private final IConfigManager manager;
|
||||
private final UpgradeInventory upgrades;
|
||||
|
||||
public UpgradeablePart(final ItemStack is) {
|
||||
super(is);
|
||||
this.upgrades = new StackUpgradeInventory(this.getItemStack(), this, this.getUpgradeSlots());
|
||||
this.manager = new ConfigManager(this);
|
||||
}
|
||||
|
||||
protected int getUpgradeSlots() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSetting(final IConfigManager manager, final Settings settingName, final Enum<?> newValue) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeInventory(final FixedItemInv inv, final int slot, final InvOperation mc,
|
||||
final ItemStack removedStack, final ItemStack newStack) {
|
||||
if (inv == this.upgrades) {
|
||||
this.upgradesChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public void upgradesChanged() {
|
||||
|
||||
}
|
||||
|
||||
protected boolean isSleeping() {
|
||||
if (this.getInstalledUpgrades(Upgrades.REDSTONE) > 0) {
|
||||
switch (this.getRSMode()) {
|
||||
case IGNORE:
|
||||
return false;
|
||||
|
||||
case HIGH_SIGNAL:
|
||||
if (this.getHost().hasRedstone(this.getSide())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case LOW_SIGNAL:
|
||||
if (!this.getHost().hasRedstone(this.getSide())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SIGNAL_PULSE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInstalledUpgrades(final Upgrades u) {
|
||||
return this.upgrades.getInstalledUpgrades(u);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canConnectRedstone() {
|
||||
return this.upgrades.getMaxInstalled(Upgrades.REDSTONE) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromNBT(final net.minecraft.nbt.CompoundTag extra) {
|
||||
super.readFromNBT(extra);
|
||||
this.manager.readFromNBT(extra);
|
||||
this.upgrades.readFromNBT(extra, "upgrades");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToNBT(final net.minecraft.nbt.CompoundTag extra) {
|
||||
super.writeToNBT(extra);
|
||||
this.manager.writeToNBT(extra);
|
||||
this.upgrades.writeToNBT(extra, "upgrades");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getDrops(final List<ItemStack> drops, final boolean wrenched) {
|
||||
for (final ItemStack is : this.upgrades) {
|
||||
if (!is.isEmpty()) {
|
||||
drops.add(is);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IConfigManager getConfigManager() {
|
||||
return this.manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FixedItemInv getInventoryByName(final String name) {
|
||||
if (name.equals("upgrades")) {
|
||||
return this.upgrades;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public RedstoneMode getRSMode() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.misc;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import appeng.api.networking.IGridNode;
|
||||
import appeng.api.parts.BusSupport;
|
||||
import appeng.api.parts.IPart;
|
||||
import appeng.api.parts.IPartCollisionHelper;
|
||||
import appeng.api.parts.IPartHost;
|
||||
import appeng.api.parts.IPartModel;
|
||||
import appeng.api.parts.PartItemStack;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
import appeng.core.AppEng;
|
||||
import appeng.items.parts.PartModels;
|
||||
import appeng.parts.PartModel;
|
||||
|
||||
public class CableAnchorPart implements IPart {
|
||||
|
||||
@PartModels
|
||||
public static final PartModel DEFAULT_MODELS = new PartModel(false,
|
||||
new Identifier(AppEng.MOD_ID, "part/cable_anchor"));
|
||||
|
||||
@PartModels
|
||||
public static final PartModel FACADE_MODELS = new PartModel(false,
|
||||
new Identifier(AppEng.MOD_ID, "part/cable_anchor_short"));
|
||||
|
||||
private ItemStack is = ItemStack.EMPTY;
|
||||
private IPartHost host = null;
|
||||
private AEPartLocation mySide = AEPartLocation.UP;
|
||||
|
||||
public CableAnchorPart(final ItemStack is) {
|
||||
this.is = is;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getBoxes(final IPartCollisionHelper bch) {
|
||||
if (this.host != null && this.host.getFacadeContainer().getFacade(this.mySide) != null) {
|
||||
bch.addBox(7, 7, 10, 9, 9, 14);
|
||||
} else {
|
||||
bch.addBox(7, 7, 10, 9, 9, 16);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemStack(final PartItemStack wrenched) {
|
||||
return this.is;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requireDynamicRender() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSolid() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canConnectRedstone() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToNBT(final CompoundTag data) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromNBT(final CompoundTag data) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLightLevel() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLadder(final LivingEntity entity) {
|
||||
return this.mySide.yOffset == 0 && (entity.horizontalCollision || !entity.isOnGround());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onneighborUpdate(BlockView w, BlockPos pos, BlockPos neighbor) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int isProvidingStrongPower() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int isProvidingWeakPower() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToStream(final PacketByteBuf data) throws IOException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean readFromStream(final PacketByteBuf data) throws IOException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IGridNode getGridNode() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEntityCollision(final Entity entity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeFromWorld() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addToWorld() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public IGridNode getExternalFacingNode() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPartHostInfo(final AEPartLocation side, final IPartHost host, final BlockEntity tile) {
|
||||
this.host = host;
|
||||
this.mySide = side;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onActivate(final PlayerEntity player, final Hand hand, final Vec3d pos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onShiftActivate(final PlayerEntity player, final Hand hand, final Vec3d pos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getDrops(final List<ItemStack> drops, final boolean wrenched) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getCableConnectionLength(AECableType cable) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void randomDisplayTick(final World world, final BlockPos pos, final Random r) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlacement(final PlayerEntity player, final Hand hand, final ItemStack held,
|
||||
final AEPartLocation side) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBePlacedOn(final BusSupport what) {
|
||||
return what == BusSupport.CABLE || what == BusSupport.DENSE_CABLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPartModel getStaticModels() {
|
||||
if (this.host != null && this.host.getFacadeContainer().getFacade(this.mySide) != null) {
|
||||
return FACADE_MODELS;
|
||||
} else {
|
||||
return DEFAULT_MODELS;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,280 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.misc;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
import alexiil.mc.lib.attributes.item.FixedItemInv;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.inventory.CraftingInventory;
|
||||
import net.minecraft.screen.ScreenHandlerType;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.config.Actionable;
|
||||
import appeng.api.config.Upgrades;
|
||||
import appeng.api.networking.IGridNode;
|
||||
import appeng.api.networking.crafting.ICraftingLink;
|
||||
import appeng.api.networking.crafting.ICraftingPatternDetails;
|
||||
import appeng.api.networking.crafting.ICraftingProviderHelper;
|
||||
import appeng.api.networking.events.MENetworkChannelsChanged;
|
||||
import appeng.api.networking.events.MENetworkEventSubscribe;
|
||||
import appeng.api.networking.events.MENetworkPowerStatusChange;
|
||||
import appeng.api.networking.ticking.IGridTickable;
|
||||
import appeng.api.networking.ticking.TickRateModulation;
|
||||
import appeng.api.networking.ticking.TickingRequest;
|
||||
import appeng.api.parts.IPartCollisionHelper;
|
||||
import appeng.api.parts.IPartModel;
|
||||
import appeng.api.storage.IMEMonitor;
|
||||
import appeng.api.storage.IStorageChannel;
|
||||
import appeng.api.storage.IStorageMonitorable;
|
||||
import appeng.api.storage.data.IAEItemStack;
|
||||
import appeng.api.storage.data.IAEStack;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.api.util.IConfigManager;
|
||||
import appeng.container.ContainerLocator;
|
||||
import appeng.container.ContainerOpener;
|
||||
import appeng.container.implementations.InterfaceContainer;
|
||||
import appeng.core.AppEng;
|
||||
import appeng.helpers.DualityInterface;
|
||||
import appeng.helpers.IInterfaceHost;
|
||||
import appeng.helpers.IPriorityHost;
|
||||
import appeng.helpers.Reflected;
|
||||
import appeng.items.parts.PartModels;
|
||||
import appeng.parts.BasicStatePart;
|
||||
import appeng.parts.PartModel;
|
||||
import appeng.util.Platform;
|
||||
import appeng.util.inv.IAEAppEngInventory;
|
||||
import appeng.util.inv.IInventoryDestination;
|
||||
import appeng.util.inv.InvOperation;
|
||||
|
||||
public class InterfacePart extends BasicStatePart implements IGridTickable, IStorageMonitorable, IInventoryDestination,
|
||||
IInterfaceHost, IAEAppEngInventory, IPriorityHost {
|
||||
|
||||
public static final Identifier MODEL_BASE = new Identifier(AppEng.MOD_ID, "part/interface_base");
|
||||
|
||||
@PartModels
|
||||
public static final PartModel MODELS_OFF = new PartModel(MODEL_BASE,
|
||||
new Identifier(AppEng.MOD_ID, "part/interface_off"));
|
||||
|
||||
@PartModels
|
||||
public static final PartModel MODELS_ON = new PartModel(MODEL_BASE,
|
||||
new Identifier(AppEng.MOD_ID, "part/interface_on"));
|
||||
|
||||
@PartModels
|
||||
public static final PartModel MODELS_HAS_CHANNEL = new PartModel(MODEL_BASE,
|
||||
new Identifier(AppEng.MOD_ID, "part/interface_has_channel"));
|
||||
|
||||
private final DualityInterface duality = new DualityInterface(this.getProxy(), this);
|
||||
|
||||
@Reflected
|
||||
public InterfacePart(final ItemStack is) {
|
||||
super(is);
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void stateChange(final MENetworkChannelsChanged c) {
|
||||
this.duality.notifyNeighbors();
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void stateChange(final MENetworkPowerStatusChange c) {
|
||||
this.duality.notifyNeighbors();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getBoxes(final IPartCollisionHelper bch) {
|
||||
bch.addBox(2, 2, 14, 14, 14, 16);
|
||||
bch.addBox(5, 5, 12, 11, 11, 14);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInstalledUpgrades(final Upgrades u) {
|
||||
return this.duality.getInstalledUpgrades(u);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void gridChanged() {
|
||||
this.duality.gridChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromNBT(final CompoundTag data) {
|
||||
super.readFromNBT(data);
|
||||
this.duality.readFromNBT(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToNBT(final CompoundTag data) {
|
||||
super.writeToNBT(data);
|
||||
this.duality.writeToNBT(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addToWorld() {
|
||||
super.addToWorld();
|
||||
this.duality.initialize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getDrops(final List<ItemStack> drops, final boolean wrenched) {
|
||||
this.duality.addDrops(drops);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getCableConnectionLength(AECableType cable) {
|
||||
return 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IConfigManager getConfigManager() {
|
||||
return this.duality.getConfigManager();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FixedItemInv getInventoryByName(final String name) {
|
||||
return this.duality.getInventoryByName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPartActivate(final PlayerEntity p, final Hand hand, final Vec3d pos) {
|
||||
if (Platform.isServer()) {
|
||||
ContainerOpener.openContainer(InterfaceContainer.TYPE, p, ContainerLocator.forPart(this));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canInsert(final ItemStack stack) {
|
||||
return this.duality.canInsert(stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends IAEStack<T>> IMEMonitor<T> getInventory(IStorageChannel<T> channel) {
|
||||
return this.duality.getInventory(channel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickingRequest getTickingRequest(final IGridNode node) {
|
||||
return this.duality.getTickingRequest(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickRateModulation tickingRequest(final IGridNode node, final int ticksSinceLastCall) {
|
||||
return this.duality.tickingRequest(node, ticksSinceLastCall);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeInventory(final FixedItemInv inv, final int slot, final InvOperation mc,
|
||||
final ItemStack removedStack, final ItemStack newStack) {
|
||||
this.duality.onChangeInventory(inv, slot, mc, removedStack, newStack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DualityInterface getInterfaceDuality() {
|
||||
return this.duality;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumSet<Direction> getTargets() {
|
||||
return EnumSet.of(this.getSide().getFacing());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntity getBlockEntity() {
|
||||
return super.getHost().getTile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean pushPattern(final ICraftingPatternDetails patternDetails, final CraftingInventory table) {
|
||||
return this.duality.pushPattern(patternDetails, table);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBusy() {
|
||||
return this.duality.isBusy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void provideCrafting(final ICraftingProviderHelper craftingTracker) {
|
||||
this.duality.provideCrafting(craftingTracker);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableSet<ICraftingLink> getRequestedJobs() {
|
||||
return this.duality.getRequestedJobs();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAEItemStack injectCraftedItems(final ICraftingLink link, final IAEItemStack items, final Actionable mode) {
|
||||
return this.duality.injectCraftedItems(link, items, mode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jobStateChange(final ICraftingLink link) {
|
||||
this.duality.jobStateChange(link);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return this.duality.getPriority();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPriority(final int newValue) {
|
||||
this.duality.setPriority(newValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPartModel getStaticModels() {
|
||||
if (this.isActive() && this.isPowered()) {
|
||||
return MODELS_HAS_CHANNEL;
|
||||
} else if (this.isPowered()) {
|
||||
return MODELS_ON;
|
||||
} else {
|
||||
return MODELS_OFF;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> LazyOptional<T> getCapability(Capability<T> capabilityClass) {
|
||||
return this.duality.getCapability(capabilityClass, this.getSide().getFacing());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemStackRepresentation() {
|
||||
return AEApi.instance().definitions().parts().iface().maybeStack(1).orElse(ItemStack.EMPTY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScreenHandlerType<?> getContainerType() {
|
||||
return InterfaceContainer.TYPE;
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.misc;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import appeng.api.parts.IPartModel;
|
||||
import appeng.core.AppEng;
|
||||
import appeng.helpers.Reflected;
|
||||
import appeng.items.parts.PartModels;
|
||||
import appeng.parts.PartModel;
|
||||
|
||||
public class InvertedToggleBusPart extends ToggleBusPart {
|
||||
@PartModels
|
||||
public static final Identifier MODEL_BASE = new Identifier(AppEng.MOD_ID,
|
||||
"part/inverted_toggle_bus_base");
|
||||
|
||||
public static final PartModel MODELS_OFF = new PartModel(MODEL_BASE, MODEL_STATUS_OFF);
|
||||
public static final PartModel MODELS_ON = new PartModel(MODEL_BASE, MODEL_STATUS_ON);
|
||||
public static final PartModel MODELS_HAS_CHANNEL = new PartModel(MODEL_BASE, MODEL_STATUS_HAS_CHANNEL);
|
||||
|
||||
@Reflected
|
||||
public InvertedToggleBusPart(final ItemStack is) {
|
||||
super(is);
|
||||
this.getProxy().setIdlePowerUsage(0.0);
|
||||
this.getOuterProxy().setIdlePowerUsage(0.0);
|
||||
this.getProxy().setFlags();
|
||||
this.getOuterProxy().setFlags();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean getIntention() {
|
||||
return !super.getIntention();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPartModel getStaticModels() {
|
||||
if (this.hasRedstoneFlag() && this.isActive() && this.isPowered()) {
|
||||
return MODELS_HAS_CHANNEL;
|
||||
} else if (this.hasRedstoneFlag() && this.isPowered()) {
|
||||
return MODELS_ON;
|
||||
} else {
|
||||
return MODELS_OFF;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,315 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.misc;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import alexiil.mc.lib.attributes.item.FixedItemInv;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.config.Actionable;
|
||||
import appeng.api.networking.security.IActionSource;
|
||||
import appeng.api.networking.storage.IBaseMonitor;
|
||||
import appeng.api.networking.ticking.TickRateModulation;
|
||||
import appeng.api.storage.IMEInventory;
|
||||
import appeng.api.storage.IMEMonitorHandlerReceiver;
|
||||
import appeng.api.storage.channels.IItemStorageChannel;
|
||||
import appeng.api.storage.data.IAEItemStack;
|
||||
import appeng.api.storage.data.IItemList;
|
||||
import appeng.core.AELog;
|
||||
import appeng.me.GridAccessException;
|
||||
import appeng.me.helpers.IGridProxyable;
|
||||
import appeng.me.storage.ITickingMonitor;
|
||||
import appeng.util.Platform;
|
||||
import appeng.util.item.AEItemStack;
|
||||
|
||||
/**
|
||||
* Wraps an Item Handler in such a way that it can be used as an IMEInventory
|
||||
* for items.
|
||||
*/
|
||||
class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAEItemStack>, ITickingMonitor {
|
||||
private final Map<IMEMonitorHandlerReceiver<IAEItemStack>, Object> listeners = new HashMap<>();
|
||||
private IActionSource mySource;
|
||||
private final FixedItemInv itemHandler;
|
||||
private final IGridProxyable proxyable;
|
||||
private final InventoryCache cache;
|
||||
|
||||
ItemHandlerAdapter(FixedItemInv itemHandler, IGridProxyable proxy) {
|
||||
this.itemHandler = itemHandler;
|
||||
this.proxyable = proxy;
|
||||
this.cache = new InventoryCache(this.itemHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAEItemStack injectItems(IAEItemStack iox, Actionable type, IActionSource src) {
|
||||
ItemStack orgInput = iox.createItemStack();
|
||||
ItemStack remaining = orgInput;
|
||||
|
||||
int slotCount = this.itemHandler.getSlotCount();
|
||||
boolean simulate = (type == Actionable.SIMULATE);
|
||||
|
||||
// This uses a brute force approach and tries to jam it in every slot the
|
||||
// inventory exposes.
|
||||
for (int i = 0; i < slotCount && !remaining.isEmpty(); i++) {
|
||||
remaining = this.itemHandler.insertItem(i, remaining, simulate);
|
||||
}
|
||||
|
||||
// At this point, we still have some items left...
|
||||
if (remaining == orgInput) {
|
||||
// The stack remained unmodified, target inventory is full
|
||||
return iox;
|
||||
}
|
||||
|
||||
if (type == Actionable.MODULATE) {
|
||||
try {
|
||||
this.proxyable.getProxy().getTick().alertDevice(this.proxyable.getProxy().getNode());
|
||||
} catch (GridAccessException ex) {
|
||||
// meh
|
||||
}
|
||||
}
|
||||
|
||||
return AEItemStack.fromItemStack(remaining);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAEItemStack extractItems(IAEItemStack request, Actionable mode, IActionSource src) {
|
||||
|
||||
ItemStack requestedItemStack = request.createItemStack();
|
||||
int remainingSize = requestedItemStack.getCount();
|
||||
|
||||
// Use this to gather the requested items
|
||||
ItemStack gathered = ItemStack.EMPTY;
|
||||
|
||||
final boolean simulate = (mode == Actionable.SIMULATE);
|
||||
|
||||
for (int i = 0; i < this.itemHandler.getSlotCount(); i++) {
|
||||
ItemStack stackInInventorySlot = this.itemHandler.getInvStack(i);
|
||||
|
||||
if (!Platform.itemComparisons().isSameItem(stackInInventorySlot, requestedItemStack)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ItemStack extracted;
|
||||
int stackSizeCurrentSlot = stackInInventorySlot.getCount();
|
||||
int remainingCurrentSlot = Math.min(remainingSize, stackSizeCurrentSlot);
|
||||
|
||||
// We have to loop here because according to the docs, the handler shouldn't
|
||||
// return a stack with size >
|
||||
// maxSize, even if we request more. So even if it returns a valid stack, it
|
||||
// might have more stuff.
|
||||
do {
|
||||
extracted = this.itemHandler.extractItem(i, remainingCurrentSlot, simulate);
|
||||
if (!extracted.isEmpty()) {
|
||||
if (extracted.getCount() > remainingCurrentSlot) {
|
||||
// Something broke. It should never return more than we requested...
|
||||
// We're going to silently eat the remainder
|
||||
AELog.warn(
|
||||
"Mod that provided item handler %s is broken. Returned %s items while only requesting %d.",
|
||||
this.itemHandler.getClass().getName(), extracted.toString(), remainingCurrentSlot);
|
||||
extracted.setCount(remainingCurrentSlot);
|
||||
}
|
||||
|
||||
// We're just gonna use the first stack we get our hands on as the template for
|
||||
// the rest.
|
||||
// In case some stupid itemhandler (aka forge) returns an internal state we have
|
||||
// to do a second
|
||||
// expensive copy again.
|
||||
if (gathered.isEmpty()) {
|
||||
gathered = extracted.copy();
|
||||
} else {
|
||||
gathered.increment(extracted.getCount());
|
||||
}
|
||||
remainingCurrentSlot -= extracted.getCount();
|
||||
}
|
||||
} while (!extracted.isEmpty() && remainingCurrentSlot > 0);
|
||||
|
||||
remainingSize -= stackSizeCurrentSlot - remainingCurrentSlot;
|
||||
|
||||
// Done?
|
||||
if (remainingSize <= 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!gathered.isEmpty()) {
|
||||
if (mode == Actionable.MODULATE) {
|
||||
try {
|
||||
this.proxyable.getProxy().getTick().alertDevice(this.proxyable.getProxy().getNode());
|
||||
} catch (GridAccessException ex) {
|
||||
// meh
|
||||
}
|
||||
}
|
||||
|
||||
return AEItemStack.fromItemStack(gathered);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickRateModulation onTick() {
|
||||
List<IAEItemStack> changes = this.cache.update();
|
||||
if (!changes.isEmpty()) {
|
||||
this.postDifference(changes);
|
||||
return TickRateModulation.URGENT;
|
||||
} else {
|
||||
return TickRateModulation.SLOWER;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActionSource(final IActionSource mySource) {
|
||||
this.mySource = mySource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IItemList<IAEItemStack> getAvailableItems(IItemList<IAEItemStack> out) {
|
||||
return this.cache.getAvailableItems(out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IItemStorageChannel getChannel() {
|
||||
return AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener(final IMEMonitorHandlerReceiver<IAEItemStack> l, final Object verificationToken) {
|
||||
this.listeners.put(l, verificationToken);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListener(final IMEMonitorHandlerReceiver<IAEItemStack> l) {
|
||||
this.listeners.remove(l);
|
||||
}
|
||||
|
||||
private void postDifference(Iterable<IAEItemStack> a) {
|
||||
final Iterator<Map.Entry<IMEMonitorHandlerReceiver<IAEItemStack>, Object>> i = this.listeners.entrySet()
|
||||
.iterator();
|
||||
while (i.hasNext()) {
|
||||
final Map.Entry<IMEMonitorHandlerReceiver<IAEItemStack>, Object> l = i.next();
|
||||
final IMEMonitorHandlerReceiver<IAEItemStack> key = l.getKey();
|
||||
if (key.isValid(l.getValue())) {
|
||||
key.postChange(this, a, this.mySource);
|
||||
} else {
|
||||
i.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class InventoryCache {
|
||||
private IAEItemStack[] cachedAeStacks = new IAEItemStack[0];
|
||||
private final FixedItemInv itemHandler;
|
||||
|
||||
public InventoryCache(FixedItemInv itemHandler) {
|
||||
this.itemHandler = itemHandler;
|
||||
}
|
||||
|
||||
public IItemList<IAEItemStack> getAvailableItems(IItemList<IAEItemStack> out) {
|
||||
Arrays.stream(this.cachedAeStacks).forEach(out::add);
|
||||
return out;
|
||||
}
|
||||
|
||||
public List<IAEItemStack> update() {
|
||||
final List<IAEItemStack> changes = new ArrayList<>();
|
||||
final int slots = this.itemHandler.getSlotCount();
|
||||
|
||||
// Make room for new slots
|
||||
if (slots > this.cachedAeStacks.length) {
|
||||
this.cachedAeStacks = Arrays.copyOf(this.cachedAeStacks, slots);
|
||||
}
|
||||
|
||||
for (int slot = 0; slot < slots; slot++) {
|
||||
// Save the old stuff
|
||||
final IAEItemStack oldAeIS = this.cachedAeStacks[slot];
|
||||
final ItemStack newIS = this.itemHandler.getInvStack(slot);
|
||||
|
||||
this.handlePossibleSlotChanges(slot, oldAeIS, newIS, changes);
|
||||
}
|
||||
|
||||
// Handle cases where the number of slots actually is lower now than before
|
||||
if (slots < this.cachedAeStacks.length) {
|
||||
for (int slot = slots; slot < this.cachedAeStacks.length; slot++) {
|
||||
final IAEItemStack aeStack = this.cachedAeStacks[slot];
|
||||
|
||||
if (aeStack != null) {
|
||||
final IAEItemStack a = aeStack.copy();
|
||||
a.setStackSize(-a.getStackSize());
|
||||
changes.add(a);
|
||||
}
|
||||
}
|
||||
|
||||
// Reduce the cache size
|
||||
this.cachedAeStacks = Arrays.copyOf(this.cachedAeStacks, slots);
|
||||
}
|
||||
|
||||
return changes;
|
||||
}
|
||||
|
||||
private void handlePossibleSlotChanges(int slot, IAEItemStack oldAeIS, ItemStack newIS,
|
||||
List<IAEItemStack> changes) {
|
||||
if (oldAeIS != null && oldAeIS.isSameType(newIS)) {
|
||||
this.handleStackSizeChanged(slot, oldAeIS, newIS, changes);
|
||||
} else {
|
||||
this.handleItemChanged(slot, oldAeIS, newIS, changes);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleStackSizeChanged(int slot, IAEItemStack oldAeIS, ItemStack newIS,
|
||||
List<IAEItemStack> changes) {
|
||||
// Still the same item, but amount might have changed
|
||||
final long diff = newIS.getCount() - oldAeIS.getStackSize();
|
||||
|
||||
if (diff != 0) {
|
||||
final IAEItemStack stack = oldAeIS.copy();
|
||||
stack.setStackSize(newIS.getCount());
|
||||
|
||||
this.cachedAeStacks[slot] = stack;
|
||||
|
||||
final IAEItemStack a = stack.copy();
|
||||
a.setStackSize(diff);
|
||||
changes.add(a);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleItemChanged(int slot, IAEItemStack oldAeIS, ItemStack newIS, List<IAEItemStack> changes) {
|
||||
// Completely different item
|
||||
this.cachedAeStacks[slot] = AEItemStack.fromItemStack(newIS);
|
||||
|
||||
// If we had a stack previously in this slot, notify the network about its
|
||||
// disappearance
|
||||
if (oldAeIS != null) {
|
||||
oldAeIS.setStackSize(-oldAeIS.getStackSize());
|
||||
changes.add(oldAeIS);
|
||||
}
|
||||
|
||||
// Notify the network about the new stack. Note that this is null if newIS was
|
||||
// null
|
||||
if (this.cachedAeStacks[slot] != null) {
|
||||
changes.add(this.cachedAeStacks[slot]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,171 +0,0 @@
|
||||
/*
|
||||
* 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.parts.misc;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockView;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.config.Settings;
|
||||
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.ticking.IGridTickable;
|
||||
import appeng.api.parts.IPartCollisionHelper;
|
||||
import appeng.api.storage.IMEInventoryHandler;
|
||||
import appeng.api.storage.IStorageChannel;
|
||||
import appeng.api.storage.cells.ICellContainer;
|
||||
import appeng.api.storage.cells.ICellInventory;
|
||||
import appeng.api.storage.channels.IItemStorageChannel;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.api.util.IConfigManager;
|
||||
import appeng.helpers.IPriorityHost;
|
||||
import appeng.me.GridAccessException;
|
||||
import appeng.parts.automation.UpgradeablePart;
|
||||
|
||||
/**
|
||||
* @author BrockWS
|
||||
* @version rv6 - 22/05/2018
|
||||
* @since rv6 22/05/2018
|
||||
*/
|
||||
public abstract class SharedStorageBusPart extends UpgradeablePart
|
||||
implements IGridTickable, ICellContainer, IPriorityHost {
|
||||
private boolean wasActive = false;
|
||||
private int priority = 0;
|
||||
|
||||
public SharedStorageBusPart(ItemStack is) {
|
||||
super(is);
|
||||
}
|
||||
|
||||
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 ignore) {
|
||||
// :P
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void updateChannels(final MENetworkChannelsChanged changedChannels) {
|
||||
this.updateStatus();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to get this parts storage channel
|
||||
*
|
||||
* @return Storage channel
|
||||
*/
|
||||
public IStorageChannel getStorageChannel() {
|
||||
return AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class);
|
||||
}
|
||||
|
||||
protected abstract void resetCache();
|
||||
|
||||
protected abstract void resetCache(boolean fullReset);
|
||||
|
||||
@Override
|
||||
public List<IMEInventoryHandler> getCellArray(final IStorageChannel channel) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void blinkCell(int slot) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveChanges(ICellInventory<?> cellInventory) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return this.priority;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPriority(final int newValue) {
|
||||
this.priority = newValue;
|
||||
this.getHost().markForSave();
|
||||
this.resetCache(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@MENetworkEventSubscribe
|
||||
public void powerRender(final MENetworkPowerStatusChange c) {
|
||||
this.updateStatus();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void upgradesChanged() {
|
||||
super.upgradesChanged();
|
||||
this.resetCache(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSetting(final IConfigManager manager, final Settings settingName, final Enum<?> newValue) {
|
||||
this.resetCache(true);
|
||||
this.getHost().markForSave();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onneighborUpdate(BlockView w, BlockPos pos, BlockPos neighbor) {
|
||||
if (pos.offset(this.getSide().getFacing()).equals(neighbor)) {
|
||||
this.resetCache(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromNBT(final CompoundTag data) {
|
||||
super.readFromNBT(data);
|
||||
this.priority = data.getInt("priority");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToNBT(final CompoundTag data) {
|
||||
super.writeToNBT(data);
|
||||
data.putInt("priority", this.priority);
|
||||
}
|
||||
|
||||
@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
|
||||
protected int getUpgradeSlots() {
|
||||
return 5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getCableConnectionLength(AECableType cable) {
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
@@ -1,569 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2015, 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.parts.misc;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.screen.ScreenHandlerType;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.items.CapabilityItemHandler;
|
||||
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.IncludeExclude;
|
||||
import appeng.api.config.Settings;
|
||||
import appeng.api.config.StorageFilter;
|
||||
import appeng.api.config.Upgrades;
|
||||
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.IActionSource;
|
||||
import appeng.api.networking.storage.IBaseMonitor;
|
||||
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.IPartCollisionHelper;
|
||||
import appeng.api.parts.IPartHost;
|
||||
import appeng.api.parts.IPartModel;
|
||||
import appeng.api.storage.IMEInventory;
|
||||
import appeng.api.storage.IMEInventoryHandler;
|
||||
import appeng.api.storage.IMEMonitorHandlerReceiver;
|
||||
import appeng.api.storage.IStorageChannel;
|
||||
import appeng.api.storage.IStorageMonitorable;
|
||||
import appeng.api.storage.IStorageMonitorableAccessor;
|
||||
import appeng.api.storage.cells.ICellContainer;
|
||||
import appeng.api.storage.cells.ICellInventory;
|
||||
import appeng.api.storage.channels.IItemStorageChannel;
|
||||
import appeng.api.storage.data.IAEItemStack;
|
||||
import appeng.api.storage.data.IItemList;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
import appeng.api.util.IConfigManager;
|
||||
import appeng.capabilities.Capabilities;
|
||||
import appeng.container.ContainerLocator;
|
||||
import appeng.container.ContainerOpener;
|
||||
import appeng.container.implementations.StorageBusContainer;
|
||||
import appeng.core.AppEng;
|
||||
import appeng.core.settings.TickRates;
|
||||
import appeng.helpers.IInterfaceHost;
|
||||
import appeng.helpers.IPriorityHost;
|
||||
import appeng.helpers.Reflected;
|
||||
import appeng.items.parts.PartModels;
|
||||
import appeng.me.GridAccessException;
|
||||
import appeng.me.helpers.MachineSource;
|
||||
import appeng.me.storage.ITickingMonitor;
|
||||
import appeng.me.storage.MEInventoryHandler;
|
||||
import appeng.me.storage.MEMonitorIInventory;
|
||||
import appeng.parts.PartModel;
|
||||
import appeng.parts.automation.UpgradeablePart;
|
||||
import appeng.tile.inventory.AppEngInternalAEInventory;
|
||||
import appeng.util.Platform;
|
||||
import appeng.util.inv.InvOperation;
|
||||
import appeng.util.prioritylist.FuzzyPriorityList;
|
||||
import appeng.util.prioritylist.PrecisePriorityList;
|
||||
|
||||
public class StorageBusPart extends UpgradeablePart
|
||||
implements IGridTickable, ICellContainer, IMEMonitorHandlerReceiver<IAEItemStack>, IPriorityHost {
|
||||
|
||||
public static final Identifier MODEL_BASE = new Identifier(AppEng.MOD_ID, "part/storage_bus_base");
|
||||
|
||||
@PartModels
|
||||
public static final IPartModel MODELS_OFF = new PartModel(MODEL_BASE,
|
||||
new Identifier(AppEng.MOD_ID, "part/storage_bus_off"));
|
||||
|
||||
@PartModels
|
||||
public static final IPartModel MODELS_ON = new PartModel(MODEL_BASE,
|
||||
new Identifier(AppEng.MOD_ID, "part/storage_bus_on"));
|
||||
|
||||
@PartModels
|
||||
public static final IPartModel MODELS_HAS_CHANNEL = new PartModel(MODEL_BASE,
|
||||
new Identifier(AppEng.MOD_ID, "part/storage_bus_has_channel"));
|
||||
|
||||
private final IActionSource mySrc;
|
||||
private final AppEngInternalAEInventory Config = new AppEngInternalAEInventory(this, 63);
|
||||
private int priority = 0;
|
||||
private boolean cached = false;
|
||||
private ITickingMonitor monitor = null;
|
||||
private MEInventoryHandler<IAEItemStack> handler = null;
|
||||
private int handlerHash = 0;
|
||||
private boolean wasActive = false;
|
||||
private byte resetCacheLogic = 0;
|
||||
|
||||
@Reflected
|
||||
public StorageBusPart(final 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.mySrc = new MachineSource(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@MENetworkEventSubscribe
|
||||
public void powerRender(final MENetworkPowerStatusChange c) {
|
||||
this.updateStatus();
|
||||
}
|
||||
|
||||
private 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) {
|
||||
// :P
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void updateChannels(final MENetworkChannelsChanged changedChannels) {
|
||||
this.updateStatus();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getUpgradeSlots() {
|
||||
return 5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSetting(final IConfigManager manager, final Settings settingName, final Enum<?> newValue) {
|
||||
this.resetCache(true);
|
||||
this.getHost().markForSave();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeInventory(final FixedItemInv 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);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void upgradesChanged() {
|
||||
super.upgradesChanged();
|
||||
this.resetCache(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromNBT(final CompoundTag data) {
|
||||
super.readFromNBT(data);
|
||||
this.Config.readFromNBT(data, "config");
|
||||
this.priority = data.getInt("priority");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToNBT(final CompoundTag data) {
|
||||
super.writeToNBT(data);
|
||||
this.Config.writeToNBT(data, "config");
|
||||
data.putInt("priority", this.priority);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FixedItemInv getInventoryByName(final String name) {
|
||||
if (name.equals("config")) {
|
||||
return this.Config;
|
||||
}
|
||||
|
||||
return super.getInventoryByName(name);
|
||||
}
|
||||
|
||||
private void resetCache(final boolean fullReset) {
|
||||
if (this.getHost() == null || this.getHost().getTile() == null || this.getHost().getTile().getWorld() == null
|
||||
|| this.getHost().getTile().getWorld().isClient) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (fullReset) {
|
||||
this.resetCacheLogic = 2;
|
||||
} else {
|
||||
this.resetCacheLogic = 1;
|
||||
}
|
||||
|
||||
try {
|
||||
this.getProxy().getTick().alertDevice(this.getProxy().getNode());
|
||||
} catch (final GridAccessException e) {
|
||||
// :P
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(final Object verificationToken) {
|
||||
return this.handler == verificationToken;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postChange(final IBaseMonitor<IAEItemStack> monitor, final Iterable<IAEItemStack> change,
|
||||
final IActionSource source) {
|
||||
try {
|
||||
if (this.getProxy().isActive()) {
|
||||
this.getProxy().getStorage().postAlterationOfStoredItems(
|
||||
AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class), change, this.mySrc);
|
||||
}
|
||||
} catch (final GridAccessException e) {
|
||||
// :(
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onListUpdate() {
|
||||
// not used here.
|
||||
}
|
||||
|
||||
@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 onneighborUpdate(BlockView w, BlockPos pos, BlockPos neighbor) {
|
||||
if (pos.offset(this.getSide().getFacing()).equals(neighbor)) {
|
||||
final BlockEntity te = w.getBlockEntity(neighbor);
|
||||
|
||||
// In case the TE was destroyed, we have to do a full reset immediately.
|
||||
if (te == null) {
|
||||
this.resetCache(true);
|
||||
this.resetCache();
|
||||
} else {
|
||||
this.resetCache(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getCableConnectionLength(AECableType cable) {
|
||||
return 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPartActivate(final PlayerEntity player, final Hand hand, final Vec3d pos) {
|
||||
if (Platform.isServer()) {
|
||||
ContainerOpener.openContainer(StorageBusContainer.TYPE, player, ContainerLocator.forPart(this));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickingRequest getTickingRequest(final IGridNode node) {
|
||||
return new TickingRequest(TickRates.StorageBus.getMin(), TickRates.StorageBus.getMax(), this.monitor == null,
|
||||
true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickRateModulation tickingRequest(final IGridNode node, final int ticksSinceLastCall) {
|
||||
if (this.resetCacheLogic != 0) {
|
||||
this.resetCache();
|
||||
}
|
||||
|
||||
if (this.monitor != null) {
|
||||
return this.monitor.onTick();
|
||||
}
|
||||
|
||||
return TickRateModulation.SLEEP;
|
||||
}
|
||||
|
||||
private void resetCache() {
|
||||
final boolean fullReset = this.resetCacheLogic == 2;
|
||||
this.resetCacheLogic = 0;
|
||||
|
||||
final IMEInventory<IAEItemStack> in = this.getInternalHandler();
|
||||
IItemList<IAEItemStack> before = AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class)
|
||||
.createList();
|
||||
if (in != null) {
|
||||
before = in.getAvailableItems(before);
|
||||
}
|
||||
|
||||
this.cached = false;
|
||||
if (fullReset) {
|
||||
this.handlerHash = 0;
|
||||
}
|
||||
|
||||
final IMEInventory<IAEItemStack> out = this.getInternalHandler();
|
||||
|
||||
if (in != out) {
|
||||
IItemList<IAEItemStack> after = AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class)
|
||||
.createList();
|
||||
if (out != null) {
|
||||
after = out.getAvailableItems(after);
|
||||
}
|
||||
Platform.postListChanges(before, after, this, this.mySrc);
|
||||
}
|
||||
}
|
||||
|
||||
private IMEInventory<IAEItemStack> getInventoryWrapper(BlockEntity target) {
|
||||
|
||||
Direction targetSide = this.getSide().getFacing().getOpposite();
|
||||
|
||||
// Prioritize a handler to directly link to another ME network
|
||||
final LazyOptional<IStorageMonitorableAccessor> accessorOpt = target
|
||||
.getCapability(Capabilities.STORAGE_MONITORABLE_ACCESSOR, targetSide);
|
||||
|
||||
if (accessorOpt.isPresent()) {
|
||||
IStorageMonitorableAccessor accessor = accessorOpt.orElse(null);
|
||||
IStorageMonitorable inventory = accessor.getInventory(this.mySrc);
|
||||
if (inventory != null) {
|
||||
return inventory.getInventory(AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class));
|
||||
}
|
||||
|
||||
// So this could / can be a design decision. If the tile does support our custom
|
||||
// capability,
|
||||
// but it does not return an inventory for the action source, we do NOT fall
|
||||
// back to using
|
||||
// IItemHandler's, as that might circumvent the security setings, and might also
|
||||
// cause
|
||||
// performance issues.
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check via cap for IItemHandler
|
||||
final LazyOptional<FixedItemInv> handlerExtOpt = target
|
||||
.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, targetSide);
|
||||
if (handlerExtOpt.isPresent()) {
|
||||
return new ItemHandlerAdapter(handlerExtOpt.orElse(null), this);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
// TODO, LazyOptionals are cacheable this might need changing?
|
||||
private int createHandlerHash(BlockEntity target) {
|
||||
if (target == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
final Direction targetSide = this.getSide().getFacing().getOpposite();
|
||||
|
||||
final LazyOptional<IStorageMonitorableAccessor> accessorOpt = target
|
||||
.getCapability(Capabilities.STORAGE_MONITORABLE_ACCESSOR, targetSide);
|
||||
|
||||
if (accessorOpt.isPresent()) {
|
||||
return Objects.hash(target, accessorOpt.orElse(null));
|
||||
}
|
||||
|
||||
final LazyOptional<FixedItemInv> itemHandlerOpt = target
|
||||
.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, targetSide);
|
||||
|
||||
if (itemHandlerOpt.isPresent()) {
|
||||
FixedItemInv itemHandler = itemHandlerOpt.orElse(null);
|
||||
return Objects.hash(target, itemHandler, itemHandler.getSlotCount());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public MEInventoryHandler<IAEItemStack> getInternalHandler() {
|
||||
if (this.cached) {
|
||||
return this.handler;
|
||||
}
|
||||
|
||||
final boolean wasSleeping = this.monitor == null;
|
||||
|
||||
this.cached = true;
|
||||
final BlockEntity self = this.getHost().getTile();
|
||||
final BlockEntity target = self.getWorld().getBlockEntity(self.getPos().offset(this.getSide().getFacing()));
|
||||
final int newHandlerHash = this.createHandlerHash(target);
|
||||
|
||||
if (newHandlerHash != 0 && newHandlerHash == this.handlerHash) {
|
||||
return this.handler;
|
||||
}
|
||||
|
||||
this.handlerHash = newHandlerHash;
|
||||
this.handler = null;
|
||||
this.monitor = null;
|
||||
if (target != null) {
|
||||
IMEInventory<IAEItemStack> inv = this.getInventoryWrapper(target);
|
||||
|
||||
if (inv instanceof MEMonitorIInventory) {
|
||||
final MEMonitorIInventory h = (MEMonitorIInventory) inv;
|
||||
h.setMode((StorageFilter) this.getConfigManager().getSetting(Settings.STORAGE_FILTER));
|
||||
}
|
||||
|
||||
if (inv instanceof ITickingMonitor) {
|
||||
this.monitor = (ITickingMonitor) inv;
|
||||
this.monitor.setActionSource(new MachineSource(this));
|
||||
}
|
||||
|
||||
if (inv != null) {
|
||||
this.checkInterfaceVsStorageBus(target, this.getSide().getOpposite());
|
||||
|
||||
this.handler = new MEInventoryHandler<IAEItemStack>(inv,
|
||||
AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class));
|
||||
|
||||
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);
|
||||
|
||||
final IItemList<IAEItemStack> priorityList = AEApi.instance().storage()
|
||||
.getStorageChannel(IItemStorageChannel.class).createList();
|
||||
|
||||
final int slotsToUse = 18 + this.getInstalledUpgrades(Upgrades.CAPACITY) * 9;
|
||||
for (int x = 0; x < this.Config.getSlotCount() && x < slotsToUse; x++) {
|
||||
final IAEItemStack is = this.Config.getAEStackInSlot(x);
|
||||
if (is != null) {
|
||||
priorityList.add(is);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.getInstalledUpgrades(Upgrades.FUZZY) > 0) {
|
||||
this.handler.setPartitionList(new FuzzyPriorityList<IAEItemStack>(priorityList,
|
||||
(FuzzyMode) this.getConfigManager().getSetting(Settings.FUZZY_MODE)));
|
||||
} else {
|
||||
this.handler.setPartitionList(new PrecisePriorityList<IAEItemStack>(priorityList));
|
||||
}
|
||||
|
||||
if (inv instanceof IBaseMonitor) {
|
||||
((IBaseMonitor<IAEItemStack>) inv).addListener(this, this.handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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 e) {
|
||||
// :(
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// force grid to update handlers...
|
||||
this.getProxy().getGrid().postEvent(new MENetworkCellArrayUpdate());
|
||||
} catch (final GridAccessException e) {
|
||||
// :3
|
||||
}
|
||||
|
||||
return this.handler;
|
||||
}
|
||||
|
||||
private void checkInterfaceVsStorageBus(final BlockEntity target, final AEPartLocation side) {
|
||||
IInterfaceHost achievement = null;
|
||||
|
||||
if (target instanceof IInterfaceHost) {
|
||||
achievement = (IInterfaceHost) target;
|
||||
}
|
||||
|
||||
if (target instanceof IPartHost) {
|
||||
final Object part = ((IPartHost) target).getPart(side);
|
||||
if (part instanceof IInterfaceHost) {
|
||||
achievement = (IInterfaceHost) part;
|
||||
}
|
||||
}
|
||||
|
||||
if (achievement != null && achievement.getActionableNode() != null) {
|
||||
// Platform.increaseStat( achievement.getActionableNode().getPlayerID(),
|
||||
// Achievements.Recursive.getAchievement()
|
||||
// );
|
||||
// Platform.increaseStat( getActionableNode().getPlayerID(),
|
||||
// Achievements.Recursive.getAchievement() );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IMEInventoryHandler> getCellArray(final IStorageChannel channel) {
|
||||
if (channel == AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class)) {
|
||||
final IMEInventoryHandler<IAEItemStack> out = this.getProxy().isActive() ? this.getInternalHandler() : null;
|
||||
if (out != null) {
|
||||
return Collections.singletonList(out);
|
||||
}
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return this.priority;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPriority(final int newValue) {
|
||||
this.priority = newValue;
|
||||
this.getHost().markForSave();
|
||||
this.resetCache(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void blinkCell(final int slot) {
|
||||
}
|
||||
|
||||
// TODO: BC PIPE INTEGRATION
|
||||
/*
|
||||
* @Override
|
||||
*
|
||||
* @Method( iname = IntegrationType.BuildCraftTransport ) public ConnectOverride
|
||||
* overridePipeConnection( PipeType type, ForgeDirection with ) { return type ==
|
||||
* PipeType.ITEM && with == this.getSide() ? ConnectOverride.CONNECT :
|
||||
* ConnectOverride.DISCONNECT; }
|
||||
*/
|
||||
@Override
|
||||
public void saveChanges(final ICellInventory<?> cellInventory) {
|
||||
// nope!
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPartModel getStaticModels() {
|
||||
if (this.isActive() && this.isPowered()) {
|
||||
return MODELS_HAS_CHANNEL;
|
||||
} else if (this.isPowered()) {
|
||||
return MODELS_ON;
|
||||
} else {
|
||||
return MODELS_OFF;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemStackRepresentation() {
|
||||
return AEApi.instance().definitions().parts().storageBus().maybeStack(1).orElse(ItemStack.EMPTY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScreenHandlerType<?> getContainerType() {
|
||||
return StorageBusContainer.TYPE;
|
||||
}
|
||||
}
|
||||
@@ -1,199 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.misc;
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockView;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.exceptions.FailedConnectionException;
|
||||
import appeng.api.networking.IGridConnection;
|
||||
import appeng.api.networking.IGridNode;
|
||||
import appeng.api.parts.IPartCollisionHelper;
|
||||
import appeng.api.parts.IPartHost;
|
||||
import appeng.api.parts.IPartModel;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
import appeng.core.AELog;
|
||||
import appeng.core.AppEng;
|
||||
import appeng.helpers.Reflected;
|
||||
import appeng.items.parts.PartModels;
|
||||
import appeng.me.helpers.AENetworkProxy;
|
||||
import appeng.parts.BasicStatePart;
|
||||
import appeng.parts.PartModel;
|
||||
|
||||
public class ToggleBusPart extends BasicStatePart {
|
||||
|
||||
@PartModels
|
||||
public static final Identifier MODEL_BASE = new Identifier(AppEng.MOD_ID, "part/toggle_bus_base");
|
||||
@PartModels
|
||||
public static final Identifier MODEL_STATUS_OFF = new Identifier(AppEng.MOD_ID,
|
||||
"part/toggle_bus_status_off");
|
||||
@PartModels
|
||||
public static final Identifier MODEL_STATUS_ON = new Identifier(AppEng.MOD_ID,
|
||||
"part/toggle_bus_status_on");
|
||||
@PartModels
|
||||
public static final Identifier MODEL_STATUS_HAS_CHANNEL = new Identifier(AppEng.MOD_ID,
|
||||
"part/toggle_bus_status_has_channel");
|
||||
|
||||
public static final IPartModel MODELS_OFF = new PartModel(MODEL_BASE, MODEL_STATUS_OFF);
|
||||
public static final IPartModel MODELS_ON = new PartModel(MODEL_BASE, MODEL_STATUS_ON);
|
||||
public static final IPartModel MODELS_HAS_CHANNEL = new PartModel(MODEL_BASE, MODEL_STATUS_HAS_CHANNEL);
|
||||
|
||||
private static final int REDSTONE_FLAG = 4;
|
||||
private final AENetworkProxy outerProxy = new AENetworkProxy(this, "outer", ItemStack.EMPTY, true);
|
||||
private IGridConnection connection;
|
||||
private boolean hasRedstone = false;
|
||||
|
||||
@Reflected
|
||||
public ToggleBusPart(final ItemStack is) {
|
||||
super(is);
|
||||
|
||||
this.getProxy().setIdlePowerUsage(0.0);
|
||||
this.getOuterProxy().setIdlePowerUsage(0.0);
|
||||
this.getProxy().setFlags();
|
||||
this.getOuterProxy().setFlags();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int populateFlags(final int cf) {
|
||||
return cf | (this.getIntention() ? REDSTONE_FLAG : 0);
|
||||
}
|
||||
|
||||
public boolean hasRedstoneFlag() {
|
||||
return (this.getClientFlags() & REDSTONE_FLAG) == REDSTONE_FLAG;
|
||||
}
|
||||
|
||||
protected boolean getIntention() {
|
||||
return this.getHost().hasRedstone(this.getSide());
|
||||
}
|
||||
|
||||
@Override
|
||||
public AECableType getCableConnectionType(final AEPartLocation dir) {
|
||||
return AECableType.GLASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getBoxes(final IPartCollisionHelper bch) {
|
||||
bch.addBox(6, 6, 11, 10, 10, 16);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onneighborUpdate(BlockView w, BlockPos pos, BlockPos neighbor) {
|
||||
final boolean oldHasRedstone = this.hasRedstone;
|
||||
this.hasRedstone = this.getHost().hasRedstone(this.getSide());
|
||||
|
||||
if (this.hasRedstone != oldHasRedstone) {
|
||||
this.updateInternalState();
|
||||
this.getHost().markForUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromNBT(final CompoundTag extra) {
|
||||
super.readFromNBT(extra);
|
||||
this.getOuterProxy().readFromNBT(extra);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToNBT(final CompoundTag extra) {
|
||||
super.writeToNBT(extra);
|
||||
this.getOuterProxy().writeToNBT(extra);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeFromWorld() {
|
||||
super.removeFromWorld();
|
||||
this.getOuterProxy().remove();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addToWorld() {
|
||||
super.addToWorld();
|
||||
this.getOuterProxy().onReady();
|
||||
this.hasRedstone = this.getHost().hasRedstone(this.getSide());
|
||||
this.updateInternalState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPartHostInfo(final AEPartLocation side, final IPartHost host, final BlockEntity tile) {
|
||||
super.setPartHostInfo(side, host, tile);
|
||||
this.outerProxy.setValidSides(EnumSet.of(side.getFacing()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public IGridNode getExternalFacingNode() {
|
||||
return this.getOuterProxy().getNode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getCableConnectionLength(AECableType cable) {
|
||||
return 5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlacement(final PlayerEntity player, final Hand hand, final ItemStack held,
|
||||
final AEPartLocation side) {
|
||||
super.onPlacement(player, hand, held, side);
|
||||
this.getOuterProxy().setOwner(player);
|
||||
}
|
||||
|
||||
private void updateInternalState() {
|
||||
final boolean intention = this.getIntention();
|
||||
if (intention == (this.connection == null)) {
|
||||
if (this.getProxy().getNode() != null && this.getOuterProxy().getNode() != null) {
|
||||
if (intention) {
|
||||
try {
|
||||
this.connection = AEApi.instance().grid().createGridConnection(this.getProxy().getNode(),
|
||||
this.getOuterProxy().getNode());
|
||||
} catch (final FailedConnectionException e) {
|
||||
// :(
|
||||
AELog.debug(e);
|
||||
}
|
||||
} else {
|
||||
this.connection.destroy();
|
||||
this.connection = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AENetworkProxy getOuterProxy() {
|
||||
return this.outerProxy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPartModel getStaticModels() {
|
||||
if (this.hasRedstoneFlag() && this.isActive() && this.isPowered()) {
|
||||
return MODELS_HAS_CHANNEL;
|
||||
} else if (this.hasRedstoneFlag() && this.isPowered()) {
|
||||
return MODELS_ON;
|
||||
} else {
|
||||
return MODELS_OFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,355 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.networking;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.EnumSet;
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.util.math.Direction;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.config.SecurityPermissions;
|
||||
import appeng.api.definitions.IParts;
|
||||
import appeng.api.implementations.parts.ICablePart;
|
||||
import appeng.api.networking.GridFlags;
|
||||
import appeng.api.networking.IGridConnection;
|
||||
import appeng.api.networking.IGridHost;
|
||||
import appeng.api.networking.IGridNode;
|
||||
import appeng.api.parts.BusSupport;
|
||||
import appeng.api.parts.IPart;
|
||||
import appeng.api.parts.IPartCollisionHelper;
|
||||
import appeng.api.parts.IPartHost;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.api.util.AEColor;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
import appeng.api.util.IReadOnlyCollection;
|
||||
import appeng.items.parts.ColoredPartItem;
|
||||
import appeng.me.GridAccessException;
|
||||
import appeng.parts.AEBasePart;
|
||||
import appeng.util.Platform;
|
||||
|
||||
public class CablePart extends AEBasePart implements ICablePart {
|
||||
|
||||
private final int[] channelsOnSide = { 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
private EnumSet<AEPartLocation> connections = EnumSet.noneOf(AEPartLocation.class);
|
||||
private boolean powered = false;
|
||||
|
||||
public CablePart(final ItemStack is) {
|
||||
super(is);
|
||||
this.getProxy().setFlags(GridFlags.PREFERRED);
|
||||
this.getProxy().setIdlePowerUsage(0.0);
|
||||
if (is.getItem() instanceof ColoredPartItem) {
|
||||
ColoredPartItem<?> coloredPartItem = (ColoredPartItem<?>) is.getItem();
|
||||
this.getProxy().setColor(coloredPartItem.getColor());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BusSupport supportsBuses() {
|
||||
return BusSupport.CABLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AEColor getCableColor() {
|
||||
return this.getProxy().getColor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AECableType getCableConnectionType() {
|
||||
return AECableType.GLASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getCableConnectionLength(AECableType cable) {
|
||||
if (cable == this.getCableConnectionType()) {
|
||||
return 4;
|
||||
} else if (cable.ordinal() >= this.getCableConnectionType().ordinal()) {
|
||||
return -1;
|
||||
} else {
|
||||
return 8;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean changeColor(final AEColor newColor, final PlayerEntity who) {
|
||||
if (this.getCableColor() != newColor) {
|
||||
ItemStack newPart = null;
|
||||
|
||||
final IParts parts = AEApi.instance().definitions().parts();
|
||||
|
||||
if (this.getCableConnectionType() == AECableType.GLASS) {
|
||||
newPart = parts.cableGlass().stack(newColor, 1);
|
||||
} else if (this.getCableConnectionType() == AECableType.COVERED) {
|
||||
newPart = parts.cableCovered().stack(newColor, 1);
|
||||
} else if (this.getCableConnectionType() == AECableType.SMART) {
|
||||
newPart = parts.cableSmart().stack(newColor, 1);
|
||||
} else if (this.getCableConnectionType() == AECableType.DENSE_COVERED) {
|
||||
newPart = parts.cableDenseCovered().stack(newColor, 1);
|
||||
} else if (this.getCableConnectionType() == AECableType.DENSE_SMART) {
|
||||
newPart = parts.cableDenseSmart().stack(newColor, 1);
|
||||
}
|
||||
|
||||
boolean hasPermission = true;
|
||||
|
||||
try {
|
||||
hasPermission = this.getProxy().getSecurity().hasPermission(who, SecurityPermissions.BUILD);
|
||||
} catch (final GridAccessException e) {
|
||||
// :P
|
||||
}
|
||||
|
||||
if (newPart != null && hasPermission) {
|
||||
if (Platform.isClient()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
this.getHost().removePart(AEPartLocation.INTERNAL, true);
|
||||
this.getHost().addPart(newPart, AEPartLocation.INTERNAL, who, null);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValidSides(final EnumSet<Direction> sides) {
|
||||
this.getProxy().setValidSides(sides);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConnected(final Direction side) {
|
||||
return this.getConnections().contains(AEPartLocation.fromFacing(side));
|
||||
}
|
||||
|
||||
public void markForUpdate() {
|
||||
this.getHost().markForUpdate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getBoxes(final IPartCollisionHelper bch) {
|
||||
bch.addBox(6.0, 6.0, 6.0, 10.0, 10.0, 10.0);
|
||||
|
||||
if (Platform.isServer()) {
|
||||
final IGridNode n = this.getGridNode();
|
||||
if (n != null) {
|
||||
this.setConnections(n.getConnectedSides());
|
||||
} else {
|
||||
this.getConnections().clear();
|
||||
}
|
||||
}
|
||||
|
||||
final IPartHost ph = this.getHost();
|
||||
if (ph != null) {
|
||||
for (final AEPartLocation dir : AEPartLocation.SIDE_LOCATIONS) {
|
||||
final IPart p = ph.getPart(dir);
|
||||
if (p instanceof IGridHost) {
|
||||
final double dist = p.getCableConnectionLength(this.getCableConnectionType());
|
||||
|
||||
if (dist > 8) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (dir) {
|
||||
case DOWN:
|
||||
bch.addBox(6.0, dist, 6.0, 10.0, 6.0, 10.0);
|
||||
break;
|
||||
case EAST:
|
||||
bch.addBox(10.0, 6.0, 6.0, 16.0 - dist, 10.0, 10.0);
|
||||
break;
|
||||
case NORTH:
|
||||
bch.addBox(6.0, 6.0, dist, 10.0, 10.0, 6.0);
|
||||
break;
|
||||
case SOUTH:
|
||||
bch.addBox(6.0, 6.0, 10.0, 10.0, 10.0, 16.0 - dist);
|
||||
break;
|
||||
case UP:
|
||||
bch.addBox(6.0, 10.0, 6.0, 10.0, 16.0 - dist, 10.0);
|
||||
break;
|
||||
case WEST:
|
||||
bch.addBox(dist, 6.0, 6.0, 6.0, 10.0, 10.0);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (final AEPartLocation of : this.getConnections()) {
|
||||
switch (of) {
|
||||
case DOWN:
|
||||
bch.addBox(6.0, 0.0, 6.0, 10.0, 6.0, 10.0);
|
||||
break;
|
||||
case EAST:
|
||||
bch.addBox(10.0, 6.0, 6.0, 16.0, 10.0, 10.0);
|
||||
break;
|
||||
case NORTH:
|
||||
bch.addBox(6.0, 6.0, 0.0, 10.0, 10.0, 6.0);
|
||||
break;
|
||||
case SOUTH:
|
||||
bch.addBox(6.0, 6.0, 10.0, 10.0, 10.0, 16.0);
|
||||
break;
|
||||
case UP:
|
||||
bch.addBox(6.0, 10.0, 6.0, 10.0, 16.0, 10.0);
|
||||
break;
|
||||
case WEST:
|
||||
bch.addBox(0.0, 6.0, 6.0, 6.0, 10.0, 10.0);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToNBT(final CompoundTag data) {
|
||||
super.writeToNBT(data);
|
||||
|
||||
if (Platform.isServer()) {
|
||||
final IGridNode node = this.getGridNode();
|
||||
|
||||
if (node != null) {
|
||||
int howMany = 0;
|
||||
for (final IGridConnection gc : node.getConnections()) {
|
||||
howMany = Math.max(gc.getUsedChannels(), howMany);
|
||||
}
|
||||
|
||||
data.putByte("usedChannels", (byte) howMany);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToStream(final PacketByteBuf data) throws IOException {
|
||||
int flags = 0;
|
||||
boolean[] writeSide = new boolean[Direction.values().length];
|
||||
int[] channelsPerSide = new int[Direction.values().length];
|
||||
|
||||
for (Direction thisSide : Direction.values()) {
|
||||
final IPart part = this.getHost().getPart(thisSide);
|
||||
if (part != null) {
|
||||
writeSide[thisSide.ordinal()] = true;
|
||||
int channels = 0;
|
||||
if (part.getGridNode() != null) {
|
||||
final IReadOnlyCollection<IGridConnection> set = part.getGridNode().getConnections();
|
||||
for (final IGridConnection gc : set) {
|
||||
channels = Math.max(channels, gc.getUsedChannels());
|
||||
}
|
||||
}
|
||||
channelsPerSide[thisSide.ordinal()] = channels;
|
||||
}
|
||||
}
|
||||
|
||||
IGridNode n = this.getGridNode();
|
||||
if (n != null) {
|
||||
for (final IGridConnection gc : n.getConnections()) {
|
||||
final AEPartLocation side = gc.getDirection(n);
|
||||
if (side != AEPartLocation.INTERNAL) {
|
||||
writeSide[side.ordinal()] = true;
|
||||
channelsPerSide[side.ordinal()] = gc.getUsedChannels();
|
||||
flags |= (1 << side.ordinal());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if (this.getProxy().getEnergy().isNetworkPowered()) {
|
||||
flags |= (1 << AEPartLocation.INTERNAL.ordinal());
|
||||
}
|
||||
} catch (final GridAccessException e) {
|
||||
// aww...
|
||||
}
|
||||
|
||||
data.writeByte((byte) flags);
|
||||
// Only write the used channels for sides where we have a part or another cable
|
||||
for (int i = 0; i < writeSide.length; i++) {
|
||||
if (writeSide[i]) {
|
||||
data.writeByte(channelsPerSide[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean readFromStream(final PacketByteBuf data) throws IOException {
|
||||
int cs = data.readByte();
|
||||
final EnumSet<AEPartLocation> myC = this.getConnections().clone();
|
||||
final boolean wasPowered = this.powered;
|
||||
this.powered = false;
|
||||
boolean channelsChanged = false;
|
||||
|
||||
for (final AEPartLocation d : AEPartLocation.values()) {
|
||||
if (d == AEPartLocation.INTERNAL) {
|
||||
final int id = 1 << d.ordinal();
|
||||
if (id == (cs & id)) {
|
||||
this.powered = true;
|
||||
}
|
||||
} else {
|
||||
boolean conOnSide = (cs & (1 << d.ordinal())) != 0;
|
||||
if (conOnSide) {
|
||||
this.getConnections().add(d);
|
||||
} else {
|
||||
this.getConnections().remove(d);
|
||||
}
|
||||
|
||||
int ch = 0;
|
||||
|
||||
// Only read channels if there's a part on this side or a cable connection
|
||||
// This works only because cables are always read *last* from the packet update
|
||||
// for
|
||||
// a cable bus
|
||||
if (conOnSide || this.getHost().getPart(d) != null) {
|
||||
ch = (data.readByte()) & 0xFF;
|
||||
}
|
||||
|
||||
if (ch != this.getChannelsOnSide(d.ordinal())) {
|
||||
channelsChanged = true;
|
||||
this.setChannelsOnSide(d.ordinal(), ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return !myC.equals(this.getConnections()) || wasPowered != this.powered || channelsChanged;
|
||||
}
|
||||
|
||||
int getChannelsOnSide(final int i) {
|
||||
return this.channelsOnSide[i];
|
||||
}
|
||||
|
||||
public int getChannelsOnSide(Direction side) {
|
||||
if (!this.powered) {
|
||||
return 0;
|
||||
}
|
||||
return this.channelsOnSide[side.ordinal()];
|
||||
}
|
||||
|
||||
void setChannelsOnSide(final int i, final int channels) {
|
||||
this.channelsOnSide[i] = channels;
|
||||
}
|
||||
|
||||
EnumSet<AEPartLocation> getConnections() {
|
||||
return this.connections;
|
||||
}
|
||||
|
||||
void setConnections(final EnumSet<AEPartLocation> connections) {
|
||||
this.connections = connections;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.networking;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import appeng.api.networking.IGridNode;
|
||||
import appeng.api.networking.events.MENetworkChannelsChanged;
|
||||
import appeng.api.networking.events.MENetworkEventSubscribe;
|
||||
import appeng.api.networking.events.MENetworkPowerStatusChange;
|
||||
import appeng.api.parts.IPartCollisionHelper;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
import appeng.util.Platform;
|
||||
|
||||
public class CoveredCablePart extends CablePart {
|
||||
|
||||
public CoveredCablePart(final ItemStack is) {
|
||||
super(is);
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void channelUpdated(final MENetworkChannelsChanged c) {
|
||||
this.getHost().markForUpdate();
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void powerRender(final MENetworkPowerStatusChange c) {
|
||||
this.getHost().markForUpdate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AECableType getCableConnectionType() {
|
||||
return AECableType.COVERED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getBoxes(final IPartCollisionHelper bch) {
|
||||
bch.addBox(5.0, 5.0, 5.0, 11.0, 11.0, 11.0);
|
||||
|
||||
if (Platform.isServer()) {
|
||||
final IGridNode n = this.getGridNode();
|
||||
if (n != null) {
|
||||
this.setConnections(n.getConnectedSides());
|
||||
} else {
|
||||
this.getConnections().clear();
|
||||
}
|
||||
}
|
||||
|
||||
for (final AEPartLocation of : this.getConnections()) {
|
||||
switch (of) {
|
||||
case DOWN:
|
||||
bch.addBox(5.0, 0.0, 5.0, 11.0, 5.0, 11.0);
|
||||
break;
|
||||
case EAST:
|
||||
bch.addBox(11.0, 5.0, 5.0, 16.0, 11.0, 11.0);
|
||||
break;
|
||||
case NORTH:
|
||||
bch.addBox(5.0, 5.0, 0.0, 11.0, 11.0, 5.0);
|
||||
break;
|
||||
case SOUTH:
|
||||
bch.addBox(5.0, 5.0, 11.0, 11.0, 11.0, 16.0);
|
||||
break;
|
||||
case UP:
|
||||
bch.addBox(5.0, 11.0, 5.0, 11.0, 16.0, 11.0);
|
||||
break;
|
||||
case WEST:
|
||||
bch.addBox(0.0, 5.0, 5.0, 5.0, 11.0, 11.0);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.networking;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import appeng.api.util.AECableType;
|
||||
|
||||
public class CoveredDenseCablePart extends DenseCablePart {
|
||||
|
||||
public CoveredDenseCablePart(ItemStack is) {
|
||||
super(is);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AECableType getCableConnectionType() {
|
||||
return AECableType.DENSE_COVERED;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.networking;
|
||||
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import appeng.api.networking.GridFlags;
|
||||
import appeng.api.networking.IGridHost;
|
||||
import appeng.api.networking.IGridNode;
|
||||
import appeng.api.networking.events.MENetworkChannelsChanged;
|
||||
import appeng.api.networking.events.MENetworkEventSubscribe;
|
||||
import appeng.api.networking.events.MENetworkPowerStatusChange;
|
||||
import appeng.api.parts.BusSupport;
|
||||
import appeng.api.parts.IPartCollisionHelper;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
import appeng.util.Platform;
|
||||
|
||||
public abstract class DenseCablePart extends CablePart {
|
||||
|
||||
public DenseCablePart(final ItemStack is) {
|
||||
super(is);
|
||||
|
||||
this.getProxy().setFlags(GridFlags.DENSE_CAPACITY, GridFlags.PREFERRED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BusSupport supportsBuses() {
|
||||
return BusSupport.DENSE_CABLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getBoxes(final IPartCollisionHelper bch) {
|
||||
final boolean noLadder = !bch.isBBCollision();
|
||||
final double min = noLadder ? 3.0 : 4.9;
|
||||
final double max = noLadder ? 13.0 : 11.1;
|
||||
|
||||
bch.addBox(min, min, min, max, max, max);
|
||||
|
||||
if (Platform.isServer()) {
|
||||
final IGridNode n = this.getGridNode();
|
||||
if (n != null) {
|
||||
this.setConnections(n.getConnectedSides());
|
||||
} else {
|
||||
this.getConnections().clear();
|
||||
}
|
||||
}
|
||||
|
||||
for (final AEPartLocation of : this.getConnections()) {
|
||||
if (this.isDense(of)) {
|
||||
switch (of) {
|
||||
case DOWN:
|
||||
bch.addBox(min, 0.0, min, max, min, max);
|
||||
break;
|
||||
case EAST:
|
||||
bch.addBox(max, min, min, 16.0, max, max);
|
||||
break;
|
||||
case NORTH:
|
||||
bch.addBox(min, min, 0.0, max, max, min);
|
||||
break;
|
||||
case SOUTH:
|
||||
bch.addBox(min, min, max, max, max, 16.0);
|
||||
break;
|
||||
case UP:
|
||||
bch.addBox(min, max, min, max, 16.0, max);
|
||||
break;
|
||||
case WEST:
|
||||
bch.addBox(0.0, min, min, min, max, max);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
} else {
|
||||
switch (of) {
|
||||
case DOWN:
|
||||
bch.addBox(5.0, 0.0, 5.0, 11.0, 5.0, 11.0);
|
||||
break;
|
||||
case EAST:
|
||||
bch.addBox(11.0, 5.0, 5.0, 16.0, 11.0, 11.0);
|
||||
break;
|
||||
case NORTH:
|
||||
bch.addBox(5.0, 5.0, 0.0, 11.0, 11.0, 5.0);
|
||||
break;
|
||||
case SOUTH:
|
||||
bch.addBox(5.0, 5.0, 11.0, 11.0, 11.0, 16.0);
|
||||
break;
|
||||
case UP:
|
||||
bch.addBox(5.0, 11.0, 5.0, 11.0, 16.0, 11.0);
|
||||
break;
|
||||
case WEST:
|
||||
bch.addBox(0.0, 5.0, 5.0, 5.0, 11.0, 11.0);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isDense(final AEPartLocation of) {
|
||||
final BlockEntity te = this.getTile().getWorld().getBlockEntity(this.getTile().getPos().offset(of.getFacing()));
|
||||
|
||||
if (te instanceof IGridHost) {
|
||||
final AECableType t = ((IGridHost) te).getCableConnectionType(of.getOpposite());
|
||||
return t.isDense();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void channelUpdated(final MENetworkChannelsChanged c) {
|
||||
this.getHost().markForUpdate();
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void powerRender(final MENetworkPowerStatusChange c) {
|
||||
this.getHost().markForUpdate();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.networking;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
public class GlassCablePart extends CablePart {
|
||||
|
||||
public GlassCablePart(final ItemStack is) {
|
||||
super(is);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.networking;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.EnumSet;
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import appeng.api.config.Actionable;
|
||||
import appeng.api.networking.GridFlags;
|
||||
import appeng.api.networking.IGridNode;
|
||||
import appeng.api.networking.energy.IEnergyGrid;
|
||||
import appeng.api.networking.energy.IEnergyGridProvider;
|
||||
import appeng.api.parts.IPartCollisionHelper;
|
||||
import appeng.api.parts.IPartHost;
|
||||
import appeng.api.parts.IPartModel;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
import appeng.core.AppEng;
|
||||
import appeng.items.parts.PartModels;
|
||||
import appeng.me.GridAccessException;
|
||||
import appeng.me.helpers.AENetworkProxy;
|
||||
import appeng.parts.AEBasePart;
|
||||
import appeng.parts.PartModel;
|
||||
|
||||
public class QuartzFiberPart extends AEBasePart implements IEnergyGridProvider {
|
||||
|
||||
@PartModels
|
||||
private static final IPartModel MODELS = new PartModel(new Identifier(AppEng.MOD_ID, "part/quartz_fiber"));
|
||||
|
||||
private final AENetworkProxy outerProxy = new AENetworkProxy(this, "outer",
|
||||
this.getProxy().getMachineRepresentation(), true);
|
||||
|
||||
public QuartzFiberPart(final ItemStack is) {
|
||||
super(is);
|
||||
this.getProxy().setIdlePowerUsage(0);
|
||||
this.getProxy().setFlags(GridFlags.CANNOT_CARRY);
|
||||
this.outerProxy.setIdlePowerUsage(0);
|
||||
this.outerProxy.setFlags(GridFlags.CANNOT_CARRY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AECableType getCableConnectionType(final AEPartLocation dir) {
|
||||
return AECableType.GLASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getBoxes(final IPartCollisionHelper bch) {
|
||||
bch.addBox(6, 6, 10, 10, 10, 16);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromNBT(final CompoundTag extra) {
|
||||
super.readFromNBT(extra);
|
||||
this.outerProxy.readFromNBT(extra);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToNBT(final CompoundTag extra) {
|
||||
super.writeToNBT(extra);
|
||||
this.outerProxy.writeToNBT(extra);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeFromWorld() {
|
||||
super.removeFromWorld();
|
||||
this.outerProxy.remove();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addToWorld() {
|
||||
super.addToWorld();
|
||||
this.outerProxy.onReady();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPartHostInfo(final AEPartLocation side, final IPartHost host, final BlockEntity tile) {
|
||||
super.setPartHostInfo(side, host, tile);
|
||||
this.outerProxy.setValidSides(EnumSet.of(side.getFacing()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public IGridNode getExternalFacingNode() {
|
||||
return this.outerProxy.getNode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getCableConnectionLength(AECableType cable) {
|
||||
return 16;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlacement(final PlayerEntity player, final Hand hand, final ItemStack held,
|
||||
final AEPartLocation side) {
|
||||
super.onPlacement(player, hand, held, side);
|
||||
this.outerProxy.setOwner(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<IEnergyGridProvider> providers() {
|
||||
Collection<IEnergyGridProvider> providers = new ArrayList<>();
|
||||
|
||||
try {
|
||||
final IEnergyGrid eg = this.getProxy().getEnergy();
|
||||
|
||||
providers.add(eg);
|
||||
} catch (final GridAccessException e) {
|
||||
// :P
|
||||
}
|
||||
|
||||
try {
|
||||
final IEnergyGrid eg = this.outerProxy.getEnergy();
|
||||
|
||||
providers.add(eg);
|
||||
} catch (final GridAccessException e) {
|
||||
// :P
|
||||
}
|
||||
|
||||
return providers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double extractProviderPower(final double amt, final Actionable mode) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double injectProviderPower(final double amt, final Actionable mode) {
|
||||
return amt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getProviderEnergyDemand(final double amt) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getProviderStoredEnergy() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getProviderMaxEnergy() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPartModel getStaticModels() {
|
||||
return MODELS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.networking;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import appeng.api.networking.IGridNode;
|
||||
import appeng.api.networking.events.MENetworkChannelsChanged;
|
||||
import appeng.api.networking.events.MENetworkEventSubscribe;
|
||||
import appeng.api.networking.events.MENetworkPowerStatusChange;
|
||||
import appeng.api.parts.IPartCollisionHelper;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
import appeng.util.Platform;
|
||||
|
||||
public class SmartCablePart extends CablePart {
|
||||
|
||||
public SmartCablePart(final ItemStack is) {
|
||||
super(is);
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void channelUpdated(final MENetworkChannelsChanged c) {
|
||||
this.getHost().markForUpdate();
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void powerRender(final MENetworkPowerStatusChange c) {
|
||||
this.getHost().markForUpdate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AECableType getCableConnectionType() {
|
||||
return AECableType.SMART;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getBoxes(final IPartCollisionHelper bch) {
|
||||
bch.addBox(5.0, 5.0, 5.0, 11.0, 11.0, 11.0);
|
||||
|
||||
if (Platform.isServer()) {
|
||||
final IGridNode n = this.getGridNode();
|
||||
if (n != null) {
|
||||
this.setConnections(n.getConnectedSides());
|
||||
} else {
|
||||
this.getConnections().clear();
|
||||
}
|
||||
}
|
||||
|
||||
for (final AEPartLocation of : this.getConnections()) {
|
||||
switch (of) {
|
||||
case DOWN:
|
||||
bch.addBox(5.0, 0.0, 5.0, 11.0, 5.0, 11.0);
|
||||
break;
|
||||
case EAST:
|
||||
bch.addBox(11.0, 5.0, 5.0, 16.0, 11.0, 11.0);
|
||||
break;
|
||||
case NORTH:
|
||||
bch.addBox(5.0, 5.0, 0.0, 11.0, 11.0, 5.0);
|
||||
break;
|
||||
case SOUTH:
|
||||
bch.addBox(5.0, 5.0, 11.0, 11.0, 11.0, 16.0);
|
||||
break;
|
||||
case UP:
|
||||
bch.addBox(5.0, 11.0, 5.0, 11.0, 16.0, 11.0);
|
||||
break;
|
||||
case WEST:
|
||||
bch.addBox(0.0, 5.0, 5.0, 5.0, 11.0, 11.0);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.networking;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import appeng.api.util.AECableType;
|
||||
|
||||
public class SmartDenseCablePart extends DenseCablePart {
|
||||
|
||||
public SmartDenseCablePart(ItemStack is) {
|
||||
super(is);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AECableType getCableConnectionType() {
|
||||
return AECableType.DENSE_SMART;
|
||||
}
|
||||
}
|
||||
@@ -1,239 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2017, 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.parts.p2p;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.energy.IEnergyStorage;
|
||||
|
||||
import appeng.api.config.PowerUnits;
|
||||
import appeng.api.parts.IPartModel;
|
||||
import appeng.capabilities.Capabilities;
|
||||
import appeng.items.parts.PartModels;
|
||||
import appeng.me.GridAccessException;
|
||||
|
||||
public class FEP2PTunnelPart extends P2PTunnelPart<FEP2PTunnelPart> {
|
||||
private static final P2PModels MODELS = new P2PModels("part/p2p/p2p_tunnel_fe");
|
||||
private static final IEnergyStorage NULL_ENERGY_STORAGE = new NullEnergyStorage();
|
||||
private final IEnergyStorage inputHandler = new InputEnergyStorage();
|
||||
private final IEnergyStorage outputHandler = new OutputEnergyStorage();
|
||||
|
||||
public FEP2PTunnelPart(ItemStack is) {
|
||||
super(is);
|
||||
}
|
||||
|
||||
@PartModels
|
||||
public static List<IPartModel> getModels() {
|
||||
return MODELS.getModels();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPartModel getStaticModels() {
|
||||
return MODELS.getModel(this.isPowered(), this.isActive());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTunnelNetworkChange() {
|
||||
this.getHost().notifyNeighbors();
|
||||
}
|
||||
|
||||
private IEnergyStorage getAttachedEnergyStorage() {
|
||||
LazyOptional<IEnergyStorage> energyStorageOpt = LazyOptional.empty();
|
||||
if (this.isActive()) {
|
||||
final BlockEntity self = this.getTile();
|
||||
final BlockEntity te = self.getWorld().getBlockEntity(self.getPos().offset(this.getSide().getFacing()));
|
||||
|
||||
if (te != null) {
|
||||
energyStorageOpt = te.getCapability(Capabilities.FORGE_ENERGY,
|
||||
this.getSide().getOpposite().getFacing());
|
||||
}
|
||||
}
|
||||
return energyStorageOpt.orElse(NULL_ENERGY_STORAGE);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
@Override
|
||||
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> capability) {
|
||||
if (capability == Capabilities.FORGE_ENERGY) {
|
||||
if (this.isOutput()) {
|
||||
return (LazyOptional<T>) LazyOptional.of(() -> this.outputHandler);
|
||||
}
|
||||
return (LazyOptional<T>) LazyOptional.of(() -> this.inputHandler);
|
||||
}
|
||||
return super.getCapability(capability);
|
||||
}
|
||||
|
||||
private class InputEnergyStorage implements IEnergyStorage {
|
||||
@Override
|
||||
public int extractEnergy(int maxExtract, boolean simulate) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int receiveEnergy(int maxReceive, boolean simulate) {
|
||||
int total = 0;
|
||||
|
||||
try {
|
||||
final int outputTunnels = FEP2PTunnelPart.this.getOutputs().size();
|
||||
|
||||
if (outputTunnels == 0 | maxReceive == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
final int amountPerOutput = maxReceive / outputTunnels;
|
||||
int overflow = amountPerOutput == 0 ? maxReceive : maxReceive % amountPerOutput;
|
||||
|
||||
for (FEP2PTunnelPart target : FEP2PTunnelPart.this.getOutputs()) {
|
||||
final IEnergyStorage output = target.getAttachedEnergyStorage();
|
||||
final int toSend = amountPerOutput + overflow;
|
||||
final int received = output.receiveEnergy(toSend, simulate);
|
||||
|
||||
overflow = toSend - received;
|
||||
total += received;
|
||||
}
|
||||
|
||||
if (!simulate) {
|
||||
FEP2PTunnelPart.this.queueTunnelDrain(PowerUnits.RF, total);
|
||||
}
|
||||
} catch (GridAccessException ignored) {
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExtract() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canReceive() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxEnergyStored() {
|
||||
int total = 0;
|
||||
|
||||
try {
|
||||
for (FEP2PTunnelPart t : FEP2PTunnelPart.this.getOutputs()) {
|
||||
total += t.getAttachedEnergyStorage().getMaxEnergyStored();
|
||||
}
|
||||
} catch (GridAccessException e) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEnergyStored() {
|
||||
int total = 0;
|
||||
|
||||
try {
|
||||
for (FEP2PTunnelPart t : FEP2PTunnelPart.this.getOutputs()) {
|
||||
total += t.getAttachedEnergyStorage().getEnergyStored();
|
||||
}
|
||||
} catch (GridAccessException e) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
}
|
||||
|
||||
private class OutputEnergyStorage implements IEnergyStorage {
|
||||
@Override
|
||||
public int extractEnergy(int maxExtract, boolean simulate) {
|
||||
final int total = FEP2PTunnelPart.this.getAttachedEnergyStorage().extractEnergy(maxExtract, simulate);
|
||||
|
||||
if (!simulate) {
|
||||
FEP2PTunnelPart.this.queueTunnelDrain(PowerUnits.RF, total);
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int receiveEnergy(int maxReceive, boolean simulate) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExtract() {
|
||||
return FEP2PTunnelPart.this.getAttachedEnergyStorage().canExtract();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canReceive() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxEnergyStored() {
|
||||
return FEP2PTunnelPart.this.getAttachedEnergyStorage().getMaxEnergyStored();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEnergyStored() {
|
||||
return FEP2PTunnelPart.this.getAttachedEnergyStorage().getEnergyStored();
|
||||
}
|
||||
}
|
||||
|
||||
private static class NullEnergyStorage implements IEnergyStorage {
|
||||
|
||||
@Override
|
||||
public int receiveEnergy(int maxReceive, boolean simulate) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int extractEnergy(int maxExtract, boolean simulate) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEnergyStored() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxEnergyStored() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExtract() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canReceive() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,262 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.p2p;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Deque;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import alexiil.mc.lib.attributes.fluid.volume.FluidVolume;
|
||||
import net.minecraft.fluid.Fluid;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler;
|
||||
|
||||
import appeng.api.parts.IPartModel;
|
||||
import appeng.items.parts.PartModels;
|
||||
import appeng.me.GridAccessException;
|
||||
|
||||
public class FluidP2PTunnelPart extends P2PTunnelPart<FluidP2PTunnelPart> implements IFluidHandler {
|
||||
|
||||
private static final P2PModels MODELS = new P2PModels("part/p2p/p2p_tunnel_fluids");
|
||||
|
||||
private static final ThreadLocal<Deque<FluidP2PTunnelPart>> DEPTH = new ThreadLocal<>();;
|
||||
|
||||
private LazyOptional<IFluidHandler> cachedTank;
|
||||
private int tmpUsed;
|
||||
|
||||
public FluidP2PTunnelPart(final ItemStack is) {
|
||||
super(is);
|
||||
}
|
||||
|
||||
@PartModels
|
||||
public static List<IPartModel> getModels() {
|
||||
return MODELS.getModels();
|
||||
}
|
||||
|
||||
public float getPowerDrainPerTick() {
|
||||
return 2.0f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTunnelNetworkChange() {
|
||||
this.cachedTank = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onneighborUpdate(BlockView w, BlockPos pos, BlockPos neighbor) {
|
||||
this.cachedTank = null;
|
||||
|
||||
if (this.isOutput()) {
|
||||
final FluidP2PTunnelPart in = this.getInput();
|
||||
if (in != null) {
|
||||
in.onTunnelNetworkChange();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> LazyOptional<T> getCapability(Capability<T> capabilityClass) {
|
||||
if (capabilityClass == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) {
|
||||
return (LazyOptional<T>) LazyOptional.of(() -> this);
|
||||
}
|
||||
|
||||
return super.getCapability(capabilityClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPartModel getStaticModels() {
|
||||
return MODELS.getModel(this.isPowered(), this.isActive());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTanks() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public FluidVolume getFluidInTank(int tank) {
|
||||
return FluidVolumeUtil.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTankCapacity(int tank) {
|
||||
return 1000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFluidValid(int tank, @Nonnull FluidVolume stack) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int fill(FluidVolume resource, FluidAction action) {
|
||||
|
||||
final Deque<FluidP2PTunnelPart> stack = this.getDepth();
|
||||
|
||||
for (final FluidP2PTunnelPart t : stack) {
|
||||
if (t == this) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
stack.push(this);
|
||||
|
||||
final List<FluidP2PTunnelPart> list = this.getOutputs(resource.getFluidKey());
|
||||
int requestTotal = 0;
|
||||
|
||||
Iterator<FluidP2PTunnelPart> i = list.iterator();
|
||||
|
||||
while (i.hasNext()) {
|
||||
final FluidP2PTunnelPart l = i.next();
|
||||
final IFluidHandler tank = l.getTarget().orElse(null);
|
||||
if (tank != null) {
|
||||
l.tmpUsed = tank.fill(resource.copy(), FluidAction.SIMULATE);
|
||||
} else {
|
||||
l.tmpUsed = 0;
|
||||
}
|
||||
|
||||
if (l.tmpUsed <= 0) {
|
||||
i.remove();
|
||||
} else {
|
||||
requestTotal += l.tmpUsed;
|
||||
}
|
||||
}
|
||||
|
||||
if (requestTotal <= 0) {
|
||||
if (stack.pop() != this) {
|
||||
throw new IllegalStateException("Invalid Recursion detected.");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (action == FluidAction.EXECUTE) {
|
||||
if (stack.pop() != this) {
|
||||
throw new IllegalStateException("Invalid Recursion detected.");
|
||||
}
|
||||
|
||||
return Math.min(resource.getAmount(), requestTotal);
|
||||
}
|
||||
|
||||
int available = resource.getAmount();
|
||||
|
||||
i = list.iterator();
|
||||
int used = 0;
|
||||
|
||||
while (i.hasNext() && available > 0) {
|
||||
final FluidP2PTunnelPart l = i.next();
|
||||
|
||||
final FluidVolume insert = resource.copy();
|
||||
insert.setAmount((int) Math.ceil(insert.getAmount() * ((double) l.tmpUsed / (double) requestTotal)));
|
||||
if (insert.getAmount() > available) {
|
||||
insert.setAmount(available);
|
||||
}
|
||||
|
||||
final IFluidHandler tank = l.getTarget().orElse(null);
|
||||
if (tank != null) {
|
||||
l.tmpUsed = tank.fill(insert.copy(), action);
|
||||
} else {
|
||||
l.tmpUsed = 0;
|
||||
}
|
||||
|
||||
available -= insert.getAmount();
|
||||
used += l.tmpUsed;
|
||||
}
|
||||
|
||||
if (stack.pop() != this) {
|
||||
throw new IllegalStateException("Invalid Recursion detected.");
|
||||
}
|
||||
|
||||
return used;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public FluidVolume drain(FluidVolume resource, FluidAction action) {
|
||||
return FluidVolumeUtil.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public FluidVolume drain(int maxDrain, FluidAction action) {
|
||||
return FluidVolumeUtil.EMPTY;
|
||||
}
|
||||
|
||||
private Deque<FluidP2PTunnelPart> getDepth() {
|
||||
Deque<FluidP2PTunnelPart> s = DEPTH.get();
|
||||
|
||||
if (s == null) {
|
||||
DEPTH.set(s = new ArrayDeque<>());
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
private List<FluidP2PTunnelPart> getOutputs(final Fluid input) {
|
||||
final List<FluidP2PTunnelPart> outs = new ArrayList<>();
|
||||
|
||||
try {
|
||||
for (final FluidP2PTunnelPart l : this.getOutputs()) {
|
||||
final IFluidHandler handler = l.getTarget().orElse(null);
|
||||
|
||||
if (handler != null) {
|
||||
outs.add(l);
|
||||
}
|
||||
}
|
||||
} catch (final GridAccessException e) {
|
||||
// :P
|
||||
}
|
||||
|
||||
return outs;
|
||||
}
|
||||
|
||||
private LazyOptional<IFluidHandler> getTarget() {
|
||||
if (!this.getProxy().isActive()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (this.cachedTank != null) {
|
||||
return this.cachedTank;
|
||||
}
|
||||
|
||||
final BlockEntity te = this.getTile().getWorld()
|
||||
.getBlockEntity(this.getTile().getPos().offset(this.getSide().getFacing()));
|
||||
|
||||
if (te != null && te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY,
|
||||
this.getSide().getFacing().getOpposite()).isPresent()) {
|
||||
return this.cachedTank = te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY,
|
||||
this.getSide().getFacing().getOpposite());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,246 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2015, 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.parts.p2p;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import alexiil.mc.lib.attributes.item.FixedItemInv;
|
||||
import alexiil.mc.lib.attributes.item.impl.EmptyFixedItemInv;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.items.CapabilityItemHandler;
|
||||
|
||||
import appeng.api.networking.IGridNode;
|
||||
import appeng.api.networking.events.MENetworkBootingStatusChange;
|
||||
import appeng.api.networking.events.MENetworkChannelsChanged;
|
||||
import appeng.api.networking.events.MENetworkEventSubscribe;
|
||||
import appeng.api.networking.events.MENetworkPowerStatusChange;
|
||||
import appeng.api.networking.ticking.IGridTickable;
|
||||
import appeng.api.networking.ticking.TickRateModulation;
|
||||
import appeng.api.networking.ticking.TickingRequest;
|
||||
import appeng.api.parts.IPartModel;
|
||||
import appeng.core.settings.TickRates;
|
||||
import appeng.items.parts.PartModels;
|
||||
import appeng.me.GridAccessException;
|
||||
import appeng.me.cache.helpers.TunnelCollection;
|
||||
import appeng.util.Platform;
|
||||
import appeng.util.inv.WrapperChainedItemHandler;
|
||||
|
||||
public class ItemP2PTunnelPart extends P2PTunnelPart<ItemP2PTunnelPart> implements FixedItemInv, IGridTickable {
|
||||
private static final float POWER_DRAIN = 2.0f;
|
||||
private static final P2PModels MODELS = new P2PModels("part/p2p/p2p_tunnel_items");
|
||||
private boolean partVisited = false;
|
||||
|
||||
@PartModels
|
||||
public static List<IPartModel> getModels() {
|
||||
return MODELS.getModels();
|
||||
}
|
||||
|
||||
private int oldSize = 0;
|
||||
private boolean requested;
|
||||
private FixedItemInv cachedInv;
|
||||
|
||||
public ItemP2PTunnelPart(final ItemStack is) {
|
||||
super(is);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onneighborUpdate(BlockView w, BlockPos pos, BlockPos neighbor) {
|
||||
this.cachedInv = null;
|
||||
final ItemP2PTunnelPart input = this.getInput();
|
||||
if (input != null && this.isOutput()) {
|
||||
input.onTunnelNetworkChange();
|
||||
}
|
||||
}
|
||||
|
||||
private FixedItemInv getDestination() {
|
||||
this.requested = true;
|
||||
|
||||
if (this.cachedInv != null) {
|
||||
return this.cachedInv;
|
||||
}
|
||||
|
||||
final List<FixedItemInv> outs = new ArrayList<FixedItemInv>();
|
||||
final TunnelCollection<ItemP2PTunnelPart> itemTunnels;
|
||||
|
||||
try {
|
||||
itemTunnels = this.getOutputs();
|
||||
} catch (final GridAccessException e) {
|
||||
return EmptyFixedItemInv.INSTANCE;
|
||||
}
|
||||
|
||||
for (final ItemP2PTunnelPart t : itemTunnels) {
|
||||
final FixedItemInv inv = t.getOutputInv();
|
||||
if (inv != null && inv != this) {
|
||||
if (Platform.getRandomInt() % 2 == 0) {
|
||||
outs.add(inv);
|
||||
} else {
|
||||
outs.add(0, inv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this.cachedInv = new WrapperChainedItemHandler(outs.toArray(new FixedItemInv[outs.size()]));
|
||||
}
|
||||
|
||||
private FixedItemInv getOutputInv() {
|
||||
FixedItemInv ret = null;
|
||||
if (!this.partVisited) {
|
||||
this.partVisited = true;
|
||||
if (this.getProxy().isActive()) {
|
||||
final Direction facing = this.getSide().getFacing();
|
||||
final BlockEntity te = this.getTile().getWorld().getBlockEntity(this.getTile().getPos().offset(facing));
|
||||
|
||||
if (te != null) {
|
||||
ret = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, facing.getOpposite())
|
||||
.orElse(ret);
|
||||
}
|
||||
}
|
||||
this.partVisited = false;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickingRequest getTickingRequest(final IGridNode node) {
|
||||
return new TickingRequest(TickRates.ItemTunnel.getMin(), TickRates.ItemTunnel.getMax(), false, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickRateModulation tickingRequest(final IGridNode node, final int ticksSinceLastCall) {
|
||||
final boolean wasReq = this.requested;
|
||||
|
||||
if (this.requested && this.cachedInv != null) {
|
||||
((WrapperChainedItemHandler) this.cachedInv).cycleOrder();
|
||||
}
|
||||
|
||||
this.requested = false;
|
||||
return wasReq ? TickRateModulation.FASTER : TickRateModulation.SLOWER;
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void changeStateA(final MENetworkBootingStatusChange bs) {
|
||||
if (!this.isOutput()) {
|
||||
this.cachedInv = null;
|
||||
final int olderSize = this.oldSize;
|
||||
this.oldSize = this.getDestination().getSlotCount();
|
||||
if (olderSize != this.oldSize) {
|
||||
this.getHost().notifyNeighbors();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void changeStateB(final MENetworkChannelsChanged bs) {
|
||||
if (!this.isOutput()) {
|
||||
this.cachedInv = null;
|
||||
final int olderSize = this.oldSize;
|
||||
this.oldSize = this.getDestination().getSlotCount();
|
||||
if (olderSize != this.oldSize) {
|
||||
this.getHost().notifyNeighbors();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void changeStateC(final MENetworkPowerStatusChange bs) {
|
||||
if (!this.isOutput()) {
|
||||
this.cachedInv = null;
|
||||
final int olderSize = this.oldSize;
|
||||
this.oldSize = this.getDestination().getSlotCount();
|
||||
if (olderSize != this.oldSize) {
|
||||
this.getHost().notifyNeighbors();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTunnelNetworkChange() {
|
||||
if (!this.isOutput()) {
|
||||
this.cachedInv = null;
|
||||
final int olderSize = this.oldSize;
|
||||
this.oldSize = this.getDestination().getSlotCount();
|
||||
if (olderSize != this.oldSize) {
|
||||
this.getHost().notifyNeighbors();
|
||||
}
|
||||
} else {
|
||||
final ItemP2PTunnelPart input = this.getInput();
|
||||
if (input != null) {
|
||||
input.getHost().notifyNeighbors();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> LazyOptional<T> getCapability(Capability<T> capabilityClass) {
|
||||
if (capabilityClass == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
|
||||
return (LazyOptional<T>) LazyOptional.of(() -> this);
|
||||
}
|
||||
|
||||
return super.getCapability(capabilityClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSlots() {
|
||||
return this.getDestination().getSlotCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isItemValid(int slot, @Nonnull ItemStack stack) {
|
||||
return this.getDestination().isItemValid(slot, stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getStackInSlot(final int i) {
|
||||
return this.getDestination().getInvStack(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack insertItem(final int slot, final ItemStack stack, boolean simulate) {
|
||||
return this.getDestination().insertItem(slot, stack, simulate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack extractItem(final int slot, final int amount, boolean simulate) {
|
||||
return this.getDestination().extractItem(slot, amount, simulate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxAmount(int slot, ItemStack is) {
|
||||
return this.getDestination().getMaxAmount(slot, is);
|
||||
}
|
||||
|
||||
public float getPowerDrainPerTick() {
|
||||
return POWER_DRAIN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPartModel getStaticModels() {
|
||||
return MODELS.getModel(this.isPowered(), this.isActive());
|
||||
}
|
||||
}
|
||||
@@ -1,198 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.p2p;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import appeng.api.networking.IGridNode;
|
||||
import appeng.api.networking.events.MENetworkChannelsChanged;
|
||||
import appeng.api.networking.events.MENetworkPowerStatusChange;
|
||||
import appeng.api.networking.ticking.IGridTickable;
|
||||
import appeng.api.networking.ticking.TickRateModulation;
|
||||
import appeng.api.networking.ticking.TickingRequest;
|
||||
import appeng.api.parts.IPartModel;
|
||||
import appeng.core.settings.TickRates;
|
||||
import appeng.items.parts.PartModels;
|
||||
import appeng.me.GridAccessException;
|
||||
|
||||
public class LightP2PTunnelPart extends P2PTunnelPart<LightP2PTunnelPart> implements IGridTickable {
|
||||
|
||||
private static final P2PModels MODELS = new P2PModels("part/p2p/p2p_tunnel_light");
|
||||
|
||||
@PartModels
|
||||
public static List<IPartModel> getModels() {
|
||||
return MODELS.getModels();
|
||||
}
|
||||
|
||||
private int lastValue = 0;
|
||||
private int opacity = -1;
|
||||
|
||||
public LightP2PTunnelPart(final ItemStack is) {
|
||||
super(is);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void chanRender(final MENetworkChannelsChanged c) {
|
||||
this.onTunnelNetworkChange();
|
||||
super.chanRender(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void powerRender(final MENetworkPowerStatusChange c) {
|
||||
this.onTunnelNetworkChange();
|
||||
super.powerRender(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToStream(final PacketByteBuf data) throws IOException {
|
||||
super.writeToStream(data);
|
||||
data.writeInt(this.isOutput() ? this.lastValue : 0);
|
||||
data.writeInt(this.opacity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean readFromStream(final PacketByteBuf data) throws IOException {
|
||||
super.readFromStream(data);
|
||||
final int oldValue = this.lastValue;
|
||||
final int oldOpacity = this.opacity;
|
||||
|
||||
this.lastValue = data.readInt();
|
||||
this.opacity = data.readInt();
|
||||
|
||||
this.setOutput(this.lastValue > 0);
|
||||
return this.lastValue != oldValue || oldOpacity != this.opacity;
|
||||
}
|
||||
|
||||
private boolean doWork() {
|
||||
if (this.isOutput()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final BlockEntity te = this.getTile();
|
||||
final World w = te.getWorld();
|
||||
|
||||
final int newLevel = w.getLightLevel(te.getPos().offset(this.getSide().getFacing()));
|
||||
|
||||
if (this.lastValue != newLevel && this.getProxy().isActive()) {
|
||||
this.lastValue = newLevel;
|
||||
try {
|
||||
for (final LightP2PTunnelPart out : this.getOutputs()) {
|
||||
out.setLightLevel(this.lastValue);
|
||||
}
|
||||
} catch (final GridAccessException e) {
|
||||
// :P
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onneighborUpdate(BlockView w, BlockPos pos, BlockPos neighbor) {
|
||||
if (this.isOutput() && pos.offset(this.getSide().getFacing()).equals(neighbor)) {
|
||||
this.opacity = -1;
|
||||
this.getHost().markForUpdate();
|
||||
} else {
|
||||
this.doWork();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLightLevel() {
|
||||
if (this.isOutput() && this.isPowered()) {
|
||||
return this.blockLight(this.lastValue);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void setLightLevel(final int out) {
|
||||
this.lastValue = out;
|
||||
this.getHost().markForUpdate();
|
||||
}
|
||||
|
||||
private int blockLight(final int emit) {
|
||||
if (this.opacity < 0) {
|
||||
final BlockEntity te = this.getTile();
|
||||
this.opacity = 255 - te.getWorld().getLightLevel(te.getPos().offset(this.getSide().getFacing()));
|
||||
}
|
||||
|
||||
return (int) (emit * (this.opacity / 255.0f));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromNBT(final CompoundTag tag) {
|
||||
super.readFromNBT(tag);
|
||||
this.lastValue = tag.getInt("lastValue");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToNBT(final CompoundTag tag) {
|
||||
super.writeToNBT(tag);
|
||||
tag.putInt("lastValue", this.lastValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTunnelConfigChange() {
|
||||
this.onTunnelNetworkChange();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTunnelNetworkChange() {
|
||||
if (this.isOutput()) {
|
||||
final LightP2PTunnelPart src = this.getInput();
|
||||
if (src != null && src.getProxy().isActive()) {
|
||||
this.setLightLevel(src.lastValue);
|
||||
} else {
|
||||
this.getHost().markForUpdate();
|
||||
}
|
||||
} else {
|
||||
this.doWork();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickingRequest getTickingRequest(final IGridNode node) {
|
||||
return new TickingRequest(TickRates.LightTunnel.getMin(), TickRates.LightTunnel.getMax(), false, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickRateModulation tickingRequest(final IGridNode node, final int ticksSinceLastCall) {
|
||||
return this.doWork() ? TickRateModulation.URGENT : TickRateModulation.SLOWER;
|
||||
}
|
||||
|
||||
public float getPowerDrainPerTick() {
|
||||
return 0.5f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPartModel getStaticModels() {
|
||||
return MODELS.getModel(this.isPowered(), this.isActive());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,222 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.p2p;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.util.Hand;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.exceptions.FailedConnectionException;
|
||||
import appeng.api.networking.GridFlags;
|
||||
import appeng.api.networking.IGridNode;
|
||||
import appeng.api.networking.ticking.IGridTickable;
|
||||
import appeng.api.networking.ticking.TickRateModulation;
|
||||
import appeng.api.networking.ticking.TickingRequest;
|
||||
import appeng.api.parts.IPartHost;
|
||||
import appeng.api.parts.IPartModel;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
import appeng.core.AELog;
|
||||
import appeng.core.settings.TickRates;
|
||||
import appeng.hooks.TickHandler;
|
||||
import appeng.items.parts.PartModels;
|
||||
import appeng.me.GridAccessException;
|
||||
import appeng.me.cache.helpers.Connections;
|
||||
import appeng.me.cache.helpers.TunnelConnection;
|
||||
import appeng.me.helpers.AENetworkProxy;
|
||||
|
||||
public class MEP2PTunnelPart extends P2PTunnelPart<MEP2PTunnelPart> implements IGridTickable {
|
||||
|
||||
private static final P2PModels MODELS = new P2PModels("part/p2p/p2p_tunnel_me");
|
||||
|
||||
@PartModels
|
||||
public static List<IPartModel> getModels() {
|
||||
return MODELS.getModels();
|
||||
}
|
||||
|
||||
private final Connections connection = new Connections(this);
|
||||
private final AENetworkProxy outerProxy = new AENetworkProxy(this, "outer", ItemStack.EMPTY, true);
|
||||
|
||||
public MEP2PTunnelPart(final ItemStack is) {
|
||||
super(is);
|
||||
this.getProxy().setFlags(GridFlags.REQUIRE_CHANNEL, GridFlags.COMPRESSED_CHANNEL);
|
||||
this.outerProxy.setFlags(GridFlags.DENSE_CAPACITY, GridFlags.CANNOT_CARRY_COMPRESSED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromNBT(final CompoundTag extra) {
|
||||
super.readFromNBT(extra);
|
||||
this.outerProxy.readFromNBT(extra);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToNBT(final CompoundTag extra) {
|
||||
super.writeToNBT(extra);
|
||||
this.outerProxy.writeToNBT(extra);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTunnelNetworkChange() {
|
||||
super.onTunnelNetworkChange();
|
||||
if (!this.isOutput()) {
|
||||
try {
|
||||
this.getProxy().getTick().wakeDevice(this.getProxy().getNode());
|
||||
} catch (final GridAccessException e) {
|
||||
// :P
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AECableType getCableConnectionType(final AEPartLocation dir) {
|
||||
return AECableType.DENSE_SMART;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeFromWorld() {
|
||||
super.removeFromWorld();
|
||||
this.outerProxy.remove();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addToWorld() {
|
||||
super.addToWorld();
|
||||
this.outerProxy.onReady();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPartHostInfo(final AEPartLocation side, final IPartHost host, final BlockEntity tile) {
|
||||
super.setPartHostInfo(side, host, tile);
|
||||
this.outerProxy.setValidSides(EnumSet.of(side.getFacing()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public IGridNode getExternalFacingNode() {
|
||||
return this.outerProxy.getNode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlacement(final PlayerEntity player, final Hand hand, final ItemStack held,
|
||||
final AEPartLocation side) {
|
||||
super.onPlacement(player, hand, held, side);
|
||||
this.outerProxy.setOwner(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickingRequest getTickingRequest(final IGridNode node) {
|
||||
return new TickingRequest(TickRates.METunnel.getMin(), TickRates.METunnel.getMax(), true, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickRateModulation tickingRequest(final IGridNode node, final int ticksSinceLastCall) {
|
||||
// just move on...
|
||||
try {
|
||||
if (!this.getProxy().getPath().isNetworkBooting()) {
|
||||
if (!this.getProxy().getEnergy().isNetworkPowered()) {
|
||||
this.connection.markDestroy();
|
||||
TickHandler.INSTANCE.addCallable(this.getTile().getWorld(), this.connection);
|
||||
} else {
|
||||
if (this.getProxy().isActive()) {
|
||||
this.connection.markCreate();
|
||||
TickHandler.INSTANCE.addCallable(this.getTile().getWorld(), this.connection);
|
||||
} else {
|
||||
this.connection.markDestroy();
|
||||
TickHandler.INSTANCE.addCallable(this.getTile().getWorld(), this.connection);
|
||||
}
|
||||
}
|
||||
|
||||
return TickRateModulation.SLEEP;
|
||||
}
|
||||
} catch (final GridAccessException e) {
|
||||
// meh?
|
||||
}
|
||||
|
||||
return TickRateModulation.IDLE;
|
||||
}
|
||||
|
||||
public void updateConnections(final Connections connections) {
|
||||
if (connections.isDestroy()) {
|
||||
for (final TunnelConnection cw : this.connection.getConnections().values()) {
|
||||
cw.getConnection().destroy();
|
||||
}
|
||||
|
||||
this.connection.getConnections().clear();
|
||||
} else if (connections.isCreate()) {
|
||||
|
||||
final Iterator<TunnelConnection> i = this.connection.getConnections().values().iterator();
|
||||
while (i.hasNext()) {
|
||||
final TunnelConnection cw = i.next();
|
||||
try {
|
||||
if (cw.getTunnel().getProxy().getGrid() != this.getProxy().getGrid()) {
|
||||
cw.getConnection().destroy();
|
||||
i.remove();
|
||||
} else if (!cw.getTunnel().getProxy().isActive()) {
|
||||
cw.getConnection().destroy();
|
||||
i.remove();
|
||||
}
|
||||
} catch (final GridAccessException e) {
|
||||
// :P
|
||||
}
|
||||
}
|
||||
|
||||
final List<MEP2PTunnelPart> newSides = new ArrayList<>();
|
||||
try {
|
||||
for (final MEP2PTunnelPart me : this.getOutputs()) {
|
||||
if (me.getProxy().isActive() && connections.getConnections().get(me.getGridNode()) == null) {
|
||||
newSides.add(me);
|
||||
}
|
||||
}
|
||||
|
||||
for (final MEP2PTunnelPart me : newSides) {
|
||||
try {
|
||||
connections.getConnections().put(me.getGridNode(), new TunnelConnection(me, AEApi.instance()
|
||||
.grid().createGridConnection(this.outerProxy.getNode(), me.outerProxy.getNode())));
|
||||
} catch (final FailedConnectionException e) {
|
||||
final BlockEntity start = this.getTile();
|
||||
final BlockEntity end = me.getTile();
|
||||
|
||||
AELog.debug(e);
|
||||
|
||||
AELog.warn(
|
||||
"Failed to establish a ME P2P Tunnel between the tunnels at [x=%d, y=%d, z=%d] and [x=%d, y=%d, z=%d]",
|
||||
start.getPos().getX(), start.getPos().getY(), start.getPos().getZ(),
|
||||
end.getPos().getX(), end.getPos().getY(), end.getPos().getZ());
|
||||
// :(
|
||||
}
|
||||
}
|
||||
} catch (final GridAccessException e) {
|
||||
AELog.debug(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPartModel getStaticModels() {
|
||||
return MODELS.getModel(this.isPowered(), this.isActive());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2015, 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.parts.p2p;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import appeng.api.parts.IPartModel;
|
||||
import appeng.core.AppEng;
|
||||
import appeng.parts.PartModel;
|
||||
|
||||
/**
|
||||
* Helper for maintaining the models used for a variant of the P2P bus.
|
||||
*/
|
||||
class P2PModels {
|
||||
|
||||
public static final Identifier MODEL_STATUS_OFF = new Identifier(AppEng.MOD_ID,
|
||||
"part/p2p/p2p_tunnel_status_off");
|
||||
public static final Identifier MODEL_STATUS_ON = new Identifier(AppEng.MOD_ID,
|
||||
"part/p2p/p2p_tunnel_status_on");
|
||||
public static final Identifier MODEL_STATUS_HAS_CHANNEL = new Identifier(AppEng.MOD_ID,
|
||||
"part/p2p/p2p_tunnel_status_has_channel");
|
||||
public static final Identifier MODEL_FREQUENCY = new Identifier(AppEng.MOD_ID,
|
||||
"part/p2p/p2p_tunnel_frequency");
|
||||
|
||||
private final IPartModel modelsOff;
|
||||
private final IPartModel modelsOn;
|
||||
private final IPartModel modelsHasChannel;
|
||||
|
||||
public P2PModels(String frontModelPath) {
|
||||
Identifier frontModel = new Identifier(AppEng.MOD_ID, frontModelPath);
|
||||
|
||||
this.modelsOff = new PartModel(MODEL_STATUS_OFF, MODEL_FREQUENCY, frontModel);
|
||||
this.modelsOn = new PartModel(MODEL_STATUS_ON, MODEL_FREQUENCY, frontModel);
|
||||
this.modelsHasChannel = new PartModel(MODEL_STATUS_HAS_CHANNEL, MODEL_FREQUENCY, frontModel);
|
||||
}
|
||||
|
||||
public IPartModel getModel(boolean hasPower, boolean hasChannel) {
|
||||
if (hasPower && hasChannel) {
|
||||
return this.modelsHasChannel;
|
||||
} else if (hasPower) {
|
||||
return this.modelsOn;
|
||||
} else {
|
||||
return this.modelsOff;
|
||||
}
|
||||
}
|
||||
|
||||
public List<IPartModel> getModels() {
|
||||
List<IPartModel> result = new ArrayList<>();
|
||||
result.add(this.modelsOff);
|
||||
result.add(this.modelsOn);
|
||||
result.add(this.modelsHasChannel);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,383 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2015, 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.parts.p2p;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.config.Actionable;
|
||||
import appeng.api.config.PowerMultiplier;
|
||||
import appeng.api.config.PowerUnits;
|
||||
import appeng.api.config.TunnelType;
|
||||
import appeng.api.definitions.IParts;
|
||||
import appeng.api.implementations.items.IMemoryCard;
|
||||
import appeng.api.implementations.items.MemoryCardMessages;
|
||||
import appeng.api.parts.IPart;
|
||||
import appeng.api.parts.IPartCollisionHelper;
|
||||
import appeng.api.parts.IPartItem;
|
||||
import appeng.api.parts.PartItemStack;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.api.util.AEColor;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
import appeng.client.render.cablebus.P2PTunnelFrequencyModelData;
|
||||
import appeng.core.AEConfig;
|
||||
import appeng.me.GridAccessException;
|
||||
import appeng.me.cache.P2PCache;
|
||||
import appeng.me.cache.helpers.TunnelCollection;
|
||||
import appeng.parts.BasicStatePart;
|
||||
import appeng.util.Platform;
|
||||
|
||||
public abstract class P2PTunnelPart<T extends P2PTunnelPart> extends BasicStatePart {
|
||||
private final TunnelCollection type = new TunnelCollection<T>(null, this.getClass());
|
||||
private boolean output;
|
||||
private short freq;
|
||||
|
||||
public P2PTunnelPart(final ItemStack is) {
|
||||
super(is);
|
||||
}
|
||||
|
||||
public TunnelCollection<T> getCollection(final Collection<P2PTunnelPart> collection,
|
||||
final Class<? extends P2PTunnelPart> c) {
|
||||
if (this.type.matches(c)) {
|
||||
this.type.setSource(collection);
|
||||
return this.type;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public T getInput() {
|
||||
if (this.getFrequency() == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
final P2PTunnelPart tunnel = this.getProxy().getP2P().getInput(this.getFrequency());
|
||||
if (this.getClass().isInstance(tunnel)) {
|
||||
return (T) tunnel;
|
||||
}
|
||||
} catch (final GridAccessException e) {
|
||||
// :P
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public TunnelCollection<T> getOutputs() throws GridAccessException {
|
||||
if (this.getProxy().isActive()) {
|
||||
return (TunnelCollection<T>) this.getProxy().getP2P().getOutputs(this.getFrequency(), this.getClass());
|
||||
}
|
||||
return new TunnelCollection(new ArrayList(), this.getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getBoxes(final IPartCollisionHelper bch) {
|
||||
bch.addBox(5, 5, 12, 11, 11, 13);
|
||||
bch.addBox(3, 3, 13, 13, 13, 14);
|
||||
bch.addBox(2, 2, 14, 14, 14, 16);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemStack(final PartItemStack type) {
|
||||
if (type == PartItemStack.WORLD || type == PartItemStack.NETWORK || type == PartItemStack.WRENCH
|
||||
|| type == PartItemStack.PICK) {
|
||||
return super.getItemStack(type);
|
||||
}
|
||||
|
||||
final Optional<ItemStack> maybeMEStack = AEApi.instance().definitions().parts().p2PTunnelME().maybeStack(1);
|
||||
if (maybeMEStack.isPresent()) {
|
||||
return maybeMEStack.get();
|
||||
}
|
||||
|
||||
return super.getItemStack(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromNBT(final CompoundTag data) {
|
||||
super.readFromNBT(data);
|
||||
this.setOutput(data.getBoolean("output"));
|
||||
this.freq = data.getShort("freq");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToNBT(final CompoundTag data) {
|
||||
super.writeToNBT(data);
|
||||
data.putBoolean("output", this.isOutput());
|
||||
data.putShort("freq", this.getFrequency());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean readFromStream(PacketByteBuf data) throws IOException {
|
||||
final boolean c = super.readFromStream(data);
|
||||
final short oldf = this.freq;
|
||||
this.freq = data.readShort();
|
||||
return c || oldf != this.freq;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToStream(PacketByteBuf data) throws IOException {
|
||||
super.writeToStream(data);
|
||||
data.writeShort(this.getFrequency());
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getCableConnectionLength(AECableType cable) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useStandardMemoryCard() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPartActivate(final PlayerEntity player, final Hand hand, final Vec3d pos) {
|
||||
if (Platform.isClient()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (hand == Hand.OFF_HAND) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final ItemStack is = player.getStackInHand(hand);
|
||||
|
||||
final TunnelType tt = AEApi.instance().registries().p2pTunnel().getTunnelTypeByItem(is);
|
||||
if (!is.isEmpty() && is.getItem() instanceof IMemoryCard) {
|
||||
final IMemoryCard mc = (IMemoryCard) is.getItem();
|
||||
final CompoundTag data = mc.getData(is);
|
||||
|
||||
final ItemStack newType = ItemStack.fromTag(data);
|
||||
final short freq = data.getShort("freq");
|
||||
|
||||
if (!newType.isEmpty()) {
|
||||
if (newType.getItem() instanceof IPartItem) {
|
||||
final IPart testPart = ((IPartItem<?>) newType.getItem()).createPart(newType);
|
||||
if (testPart instanceof P2PTunnelPart) {
|
||||
this.getHost().removePart(this.getSide(), true);
|
||||
final AEPartLocation dir = this.getHost().addPart(newType, this.getSide(), player, hand);
|
||||
final IPart newBus = this.getHost().getPart(dir);
|
||||
|
||||
if (newBus instanceof P2PTunnelPart) {
|
||||
final P2PTunnelPart<?> newTunnel = (P2PTunnelPart<?>) newBus;
|
||||
newTunnel.setOutput(true);
|
||||
|
||||
try {
|
||||
final P2PCache p2p = newTunnel.getProxy().getP2P();
|
||||
p2p.updateFreq(newTunnel, freq);
|
||||
} catch (final GridAccessException e) {
|
||||
// :P
|
||||
}
|
||||
|
||||
newTunnel.onTunnelNetworkChange();
|
||||
}
|
||||
|
||||
mc.notifyUser(player, MemoryCardMessages.SETTINGS_LOADED);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
mc.notifyUser(player, MemoryCardMessages.INVALID_MACHINE);
|
||||
} else if (tt != null) // attunement
|
||||
{
|
||||
final ItemStack newType;
|
||||
|
||||
final IParts parts = AEApi.instance().definitions().parts();
|
||||
|
||||
switch (tt) {
|
||||
case LIGHT:
|
||||
newType = parts.p2PTunnelLight().maybeStack(1).orElse(ItemStack.EMPTY);
|
||||
break;
|
||||
|
||||
case FE_POWER:
|
||||
newType = parts.p2PTunnelFE().maybeStack(1).orElse(ItemStack.EMPTY);
|
||||
break;
|
||||
|
||||
case FLUID:
|
||||
newType = parts.p2PTunnelFluids().maybeStack(1).orElse(ItemStack.EMPTY);
|
||||
break;
|
||||
|
||||
case IC2_POWER:
|
||||
newType = parts.p2PTunnelEU().maybeStack(1).orElse(ItemStack.EMPTY);
|
||||
break;
|
||||
|
||||
case ITEM:
|
||||
newType = parts.p2PTunnelItems().maybeStack(1).orElse(ItemStack.EMPTY);
|
||||
break;
|
||||
|
||||
case ME:
|
||||
newType = parts.p2PTunnelME().maybeStack(1).orElse(ItemStack.EMPTY);
|
||||
break;
|
||||
|
||||
case REDSTONE:
|
||||
newType = parts.p2PTunnelRedstone().maybeStack(1).orElse(ItemStack.EMPTY);
|
||||
break;
|
||||
|
||||
/*
|
||||
* case COMPUTER_MESSAGE: for( ItemStack stack :
|
||||
* parts.p2PTunnelOpenComputers().maybeStack( 1 ).asSet() ) { newType = stack; }
|
||||
* break;
|
||||
*/
|
||||
|
||||
default:
|
||||
newType = ItemStack.EMPTY;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!newType.isEmpty() && !ItemStack.areItemsEqual(newType, this.getItemStack())) {
|
||||
final boolean oldOutput = this.isOutput();
|
||||
final short myFreq = this.getFrequency();
|
||||
|
||||
this.getHost().removePart(this.getSide(), false);
|
||||
final AEPartLocation dir = this.getHost().addPart(newType, this.getSide(), player, hand);
|
||||
final IPart newBus = this.getHost().getPart(dir);
|
||||
|
||||
if (newBus instanceof P2PTunnelPart) {
|
||||
final P2PTunnelPart newTunnel = (P2PTunnelPart) newBus;
|
||||
newTunnel.setOutput(oldOutput);
|
||||
newTunnel.onTunnelNetworkChange();
|
||||
|
||||
try {
|
||||
final P2PCache p2p = newTunnel.getProxy().getP2P();
|
||||
p2p.updateFreq(newTunnel, myFreq);
|
||||
} catch (final GridAccessException e) {
|
||||
// :P
|
||||
}
|
||||
}
|
||||
|
||||
Platform.notifyBlocksOfNeighbors(this.getTile().getWorld(), this.getTile().getPos());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPartShiftActivate(final PlayerEntity player, final Hand hand, final Vec3d pos) {
|
||||
final ItemStack is = player.inventory.getCurrentItem();
|
||||
if (!is.isEmpty() && is.getItem() instanceof IMemoryCard) {
|
||||
if (Platform.isClient()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final IMemoryCard mc = (IMemoryCard) is.getItem();
|
||||
final CompoundTag data = mc.getData(is);
|
||||
final short storedFrequency = data.getShort("freq");
|
||||
|
||||
short newFreq = this.getFrequency();
|
||||
final boolean wasOutput = this.isOutput();
|
||||
this.setOutput(false);
|
||||
|
||||
final boolean needsNewFrequency = wasOutput || this.getFrequency() == 0 || storedFrequency == newFreq;
|
||||
|
||||
try {
|
||||
if (needsNewFrequency) {
|
||||
newFreq = this.getProxy().getP2P().newFrequency();
|
||||
}
|
||||
|
||||
this.getProxy().getP2P().updateFreq(this, newFreq);
|
||||
} catch (final GridAccessException e) {
|
||||
// :P
|
||||
}
|
||||
|
||||
this.onTunnelConfigChange();
|
||||
|
||||
final ItemStack p2pItem = this.getItemStack(PartItemStack.WRENCH);
|
||||
final String type = p2pItem.getTranslationKey();
|
||||
|
||||
p2pItem.toTag(data);
|
||||
data.putShort("freq", this.getFrequency());
|
||||
|
||||
final AEColor[] colors = Platform.p2p().toColors(this.getFrequency());
|
||||
final int[] colorCode = new int[] { colors[0].ordinal(), colors[0].ordinal(), colors[1].ordinal(),
|
||||
colors[1].ordinal(), colors[2].ordinal(), colors[2].ordinal(), colors[3].ordinal(),
|
||||
colors[3].ordinal(), };
|
||||
|
||||
data.putIntArray("colorCode", colorCode);
|
||||
|
||||
mc.setMemoryCardContents(is, type + ".name", data);
|
||||
if (needsNewFrequency) {
|
||||
mc.notifyUser(player, MemoryCardMessages.SETTINGS_RESET);
|
||||
} else {
|
||||
mc.notifyUser(player, MemoryCardMessages.SETTINGS_SAVED);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void onTunnelConfigChange() {
|
||||
}
|
||||
|
||||
public void onTunnelNetworkChange() {
|
||||
|
||||
}
|
||||
|
||||
protected void queueTunnelDrain(final PowerUnits unit, final double f) {
|
||||
final double ae_to_tax = unit.convertTo(PowerUnits.AE, f * AEConfig.TUNNEL_POWER_LOSS);
|
||||
|
||||
try {
|
||||
this.getProxy().getEnergy().extractAEPower(ae_to_tax, Actionable.MODULATE, PowerMultiplier.ONE);
|
||||
} catch (final GridAccessException e) {
|
||||
// :P
|
||||
}
|
||||
}
|
||||
|
||||
public short getFrequency() {
|
||||
return this.freq;
|
||||
}
|
||||
|
||||
public void setFrequency(final short freq) {
|
||||
final short oldf = this.freq;
|
||||
this.freq = freq;
|
||||
if (oldf != this.freq) {
|
||||
this.getHost().markForUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isOutput() {
|
||||
return this.output;
|
||||
}
|
||||
|
||||
void setOutput(final boolean output) {
|
||||
this.output = output;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IModelData getModelData() {
|
||||
long ret = Short.toUnsignedLong(this.getFrequency());
|
||||
|
||||
if (this.isActive() && this.isPowered()) {
|
||||
ret |= 0x10000L;
|
||||
}
|
||||
|
||||
return new P2PTunnelFrequencyModelData(ret);
|
||||
}
|
||||
}
|
||||
@@ -1,182 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.p2p;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.RedstoneWireBlock;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import appeng.api.networking.events.MENetworkBootingStatusChange;
|
||||
import appeng.api.networking.events.MENetworkChannelsChanged;
|
||||
import appeng.api.networking.events.MENetworkEventSubscribe;
|
||||
import appeng.api.networking.events.MENetworkPowerStatusChange;
|
||||
import appeng.api.parts.IPartModel;
|
||||
import appeng.items.parts.PartModels;
|
||||
import appeng.me.GridAccessException;
|
||||
import appeng.util.Platform;
|
||||
|
||||
public class RedstoneP2PTunnelPart extends P2PTunnelPart<RedstoneP2PTunnelPart> {
|
||||
|
||||
private static final P2PModels MODELS = new P2PModels("part/p2p/p2p_tunnel_redstone");
|
||||
|
||||
@PartModels
|
||||
public static List<IPartModel> getModels() {
|
||||
return MODELS.getModels();
|
||||
}
|
||||
|
||||
private int power;
|
||||
private boolean recursive = false;
|
||||
|
||||
public RedstoneP2PTunnelPart(final ItemStack is) {
|
||||
super(is);
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void changeStateA(final MENetworkBootingStatusChange bs) {
|
||||
this.setNetworkReady();
|
||||
}
|
||||
|
||||
private void setNetworkReady() {
|
||||
if (this.isOutput()) {
|
||||
final RedstoneP2PTunnelPart in = this.getInput();
|
||||
if (in != null) {
|
||||
this.putInput(in.power);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void putInput(final Object o) {
|
||||
if (this.recursive) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.recursive = true;
|
||||
if (this.isOutput() && this.getProxy().isActive()) {
|
||||
final int newPower = (Integer) o;
|
||||
if (this.power != newPower) {
|
||||
this.power = newPower;
|
||||
this.notifyNeighbors();
|
||||
}
|
||||
}
|
||||
this.recursive = false;
|
||||
}
|
||||
|
||||
private void notifyNeighbors() {
|
||||
final World world = this.getTile().getWorld();
|
||||
|
||||
Platform.notifyBlocksOfNeighbors(world, this.getTile().getPos());
|
||||
|
||||
// and this cause sometimes it can go thought walls.
|
||||
for (final Direction face : Direction.values()) {
|
||||
Platform.notifyBlocksOfNeighbors(world, this.getTile().getPos().offset(face));
|
||||
}
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void changeStateB(final MENetworkChannelsChanged bs) {
|
||||
this.setNetworkReady();
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void changeStateC(final MENetworkPowerStatusChange bs) {
|
||||
this.setNetworkReady();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromNBT(final CompoundTag tag) {
|
||||
super.readFromNBT(tag);
|
||||
this.power = tag.getInt("power");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToNBT(final CompoundTag tag) {
|
||||
super.writeToNBT(tag);
|
||||
tag.putInt("power", this.power);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTunnelNetworkChange() {
|
||||
this.setNetworkReady();
|
||||
}
|
||||
|
||||
public float getPowerDrainPerTick() {
|
||||
return 0.5f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onneighborUpdate(BlockView w, BlockPos pos, BlockPos neighbor) {
|
||||
if (!this.isOutput()) {
|
||||
final BlockPos target = this.getTile().getPos().offset(this.getSide().getFacing());
|
||||
|
||||
final BlockState state = this.getTile().getWorld().getBlockState(target);
|
||||
final Block b = state.getBlock();
|
||||
if (b != null && !this.isOutput()) {
|
||||
Direction srcSide = this.getSide().getFacing();
|
||||
if (b instanceof RedstoneWireBlock) {
|
||||
srcSide = Direction.UP;
|
||||
}
|
||||
|
||||
this.power = b.getWeakRedstonePower(state, this.getTile().getWorld(), target, srcSide);
|
||||
this.power = Math.max(this.power, b.getWeakRedstonePower(state, this.getTile().getWorld(), target, srcSide));
|
||||
this.sendToOutput(this.power);
|
||||
} else {
|
||||
this.sendToOutput(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canConnectRedstone() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int isProvidingStrongPower() {
|
||||
return this.isOutput() ? this.power : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int isProvidingWeakPower() {
|
||||
return this.isOutput() ? this.power : 0;
|
||||
}
|
||||
|
||||
private void sendToOutput(final int power) {
|
||||
try {
|
||||
for (final RedstoneP2PTunnelPart rs : this.getOutputs()) {
|
||||
rs.putInput(power);
|
||||
}
|
||||
} catch (final GridAccessException e) {
|
||||
// :P
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPartModel getStaticModels() {
|
||||
return MODELS.getModel(this.isPowered(), this.isActive());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.reporting;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import appeng.core.AppEng;
|
||||
import appeng.items.parts.PartModels;
|
||||
|
||||
/**
|
||||
* A more sophisticated part overlapping all 3 textures.
|
||||
*
|
||||
* Subclass this if you need want a new part and need all 3 textures. For more
|
||||
* concrete implementations, the direct abstract subclasses might be a better
|
||||
* alternative.
|
||||
*
|
||||
* @author AlgorithmX2
|
||||
* @author yueh
|
||||
* @version rv3
|
||||
* @since rv3
|
||||
*/
|
||||
public abstract class AbstractDisplayPart extends AbstractReportingPart {
|
||||
|
||||
// The base chassis of all display parts
|
||||
@PartModels
|
||||
protected static final Identifier MODEL_BASE = new Identifier(AppEng.MOD_ID, "part/display_base");
|
||||
|
||||
// Models that contain the status indicator light
|
||||
@PartModels
|
||||
protected static final Identifier MODEL_STATUS_OFF = new Identifier(AppEng.MOD_ID,
|
||||
"part/display_status_off");
|
||||
@PartModels
|
||||
protected static final Identifier MODEL_STATUS_ON = new Identifier(AppEng.MOD_ID,
|
||||
"part/display_status_on");
|
||||
@PartModels
|
||||
protected static final Identifier MODEL_STATUS_HAS_CHANNEL = new Identifier(AppEng.MOD_ID,
|
||||
"part/display_status_has_channel");
|
||||
|
||||
public AbstractDisplayPart(final ItemStack is) {
|
||||
super(is, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLightSource() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,320 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.reporting;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
|
||||
import net.minecraft.client.render.VertexConsumerProvider;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.hit.HitResult;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.implementations.parts.IStorageMonitorPart;
|
||||
import appeng.api.networking.security.IActionSource;
|
||||
import appeng.api.networking.storage.IStackWatcher;
|
||||
import appeng.api.networking.storage.IStackWatcherHost;
|
||||
import appeng.api.parts.IPartModel;
|
||||
import appeng.api.storage.IMEMonitor;
|
||||
import appeng.api.storage.IStorageChannel;
|
||||
import appeng.api.storage.channels.IItemStorageChannel;
|
||||
import appeng.api.storage.data.IAEItemStack;
|
||||
import appeng.api.storage.data.IAEStack;
|
||||
import appeng.api.storage.data.IItemList;
|
||||
import appeng.client.render.TesrRenderHelper;
|
||||
import appeng.core.localization.PlayerMessages;
|
||||
import appeng.helpers.Reflected;
|
||||
import appeng.me.GridAccessException;
|
||||
import appeng.util.IWideReadableNumberConverter;
|
||||
import appeng.util.Platform;
|
||||
import appeng.util.ReadableNumberConverter;
|
||||
import appeng.util.item.AEItemStack;
|
||||
|
||||
/**
|
||||
* A basic subclass for any item monitor like display with an item icon and an
|
||||
* amount.
|
||||
*
|
||||
* It can also be used to extract items from somewhere and spawned into the
|
||||
* world.
|
||||
*
|
||||
* @author AlgorithmX2
|
||||
* @author thatsIch
|
||||
* @author yueh
|
||||
* @version rv3
|
||||
* @since rv3
|
||||
*/
|
||||
public abstract class AbstractMonitorPart extends AbstractDisplayPart
|
||||
implements IStorageMonitorPart, IStackWatcherHost {
|
||||
private static final IWideReadableNumberConverter NUMBER_CONVERTER = ReadableNumberConverter.INSTANCE;
|
||||
private IAEItemStack configuredItem;
|
||||
private String lastHumanReadableText;
|
||||
private boolean isLocked;
|
||||
private IStackWatcher myWatcher;
|
||||
|
||||
@Reflected
|
||||
public AbstractMonitorPart(final ItemStack is) {
|
||||
super(is);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromNBT(final CompoundTag data) {
|
||||
super.readFromNBT(data);
|
||||
|
||||
this.isLocked = data.getBoolean("isLocked");
|
||||
|
||||
final CompoundTag myItem = data.getCompound("configuredItem");
|
||||
this.configuredItem = AEItemStack.fromNBT(myItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToNBT(final CompoundTag data) {
|
||||
super.writeToNBT(data);
|
||||
|
||||
data.putBoolean("isLocked", this.isLocked);
|
||||
|
||||
final CompoundTag myItem = new CompoundTag();
|
||||
if (this.configuredItem != null) {
|
||||
this.configuredItem.writeToNBT(myItem);
|
||||
}
|
||||
|
||||
data.put("configuredItem", myItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToStream(final PacketByteBuf data) throws IOException {
|
||||
super.writeToStream(data);
|
||||
|
||||
data.writeBoolean(this.isLocked);
|
||||
data.writeBoolean(this.configuredItem != null);
|
||||
if (this.configuredItem != null) {
|
||||
this.configuredItem.writeToPacket(data);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean readFromStream(final PacketByteBuf data) throws IOException {
|
||||
boolean needRedraw = super.readFromStream(data);
|
||||
|
||||
final boolean isLocked = data.readBoolean();
|
||||
needRedraw = this.isLocked != isLocked;
|
||||
|
||||
this.isLocked = isLocked;
|
||||
|
||||
final boolean val = data.readBoolean();
|
||||
if (val) {
|
||||
this.configuredItem = AEItemStack.fromPacket(data);
|
||||
} else {
|
||||
this.configuredItem = null;
|
||||
}
|
||||
|
||||
return needRedraw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPartActivate(final PlayerEntity player, final Hand hand, final Vec3d pos) {
|
||||
if (Platform.isClient()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!this.getProxy().isActive()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Platform.hasPermissions(this.getLocation(), player)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this.isLocked) {
|
||||
final ItemStack eq = player.getStackInHand(hand);
|
||||
this.configuredItem = AEItemStack.fromItemStack(eq);
|
||||
this.configureWatchers();
|
||||
this.getHost().markForSave();
|
||||
this.getHost().markForUpdate();
|
||||
} else {
|
||||
return super.onPartActivate(player, hand, pos);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPartShiftActivate(PlayerEntity player, Hand hand, Vec3d pos) {
|
||||
if (Platform.isClient()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!this.getProxy().isActive()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Platform.hasPermissions(this.getLocation(), player)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (player.getStackInHand(hand).isEmpty()) {
|
||||
this.isLocked = !this.isLocked;
|
||||
player.sendSystemMessage((this.isLocked ? PlayerMessages.isNowLocked : PlayerMessages.isNowUnlocked).get(), Util.NIL_UUID);
|
||||
this.getHost().markForSave();
|
||||
this.getHost().markForUpdate();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// update the system...
|
||||
private void configureWatchers() {
|
||||
if (this.myWatcher != null) {
|
||||
this.myWatcher.reset();
|
||||
}
|
||||
|
||||
try {
|
||||
if (this.configuredItem != null) {
|
||||
if (this.myWatcher != null) {
|
||||
this.myWatcher.add(this.configuredItem);
|
||||
}
|
||||
|
||||
this.updateReportingValue(this.getProxy().getStorage()
|
||||
.getInventory(AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class)));
|
||||
}
|
||||
} catch (final GridAccessException e) {
|
||||
// >.>
|
||||
}
|
||||
}
|
||||
|
||||
private void updateReportingValue(final IMEMonitor<IAEItemStack> itemInventory) {
|
||||
if (this.configuredItem != null) {
|
||||
final IAEItemStack result = itemInventory.getStorageList().findPrecise(this.configuredItem);
|
||||
if (result == null) {
|
||||
this.configuredItem.setStackSize(0);
|
||||
} else {
|
||||
this.configuredItem.setStackSize(result.getStackSize());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Environment(EnvType.CLIENT)
|
||||
public void renderDynamic(float partialTicks, MatrixStack matrixStack, VertexConsumerProvider buffers,
|
||||
int combinedLightIn, int combinedOverlayIn) {
|
||||
|
||||
if ((this.getClientFlags() & (PanelPart.POWERED_FLAG | PanelPart.CHANNEL_FLAG)) != (PanelPart.POWERED_FLAG
|
||||
| PanelPart.CHANNEL_FLAG)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final IAEItemStack ais = this.getDisplayed();
|
||||
|
||||
if (ais == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
matrixStack.push();
|
||||
matrixStack.translate(0.5, 0.5, 0.5); // Move into the center of the block
|
||||
|
||||
Direction facing = this.getSide().getFacing();
|
||||
|
||||
TesrRenderHelper.rotateToFace(matrixStack, facing, this.getSpin());
|
||||
|
||||
matrixStack.translate(0, 0.05, 0.5);
|
||||
|
||||
TesrRenderHelper.renderItem2dWithAmount(matrixStack, buffers, ais, 0.4f, -0.23f, 15728880, combinedOverlayIn);
|
||||
|
||||
matrixStack.pop();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requireDynamicRender() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAEItemStack getDisplayed() {
|
||||
return this.configuredItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLocked() {
|
||||
return this.isLocked;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateWatcher(final IStackWatcher newWatcher) {
|
||||
this.myWatcher = newWatcher;
|
||||
this.configureWatchers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStackChange(final IItemList o, final IAEStack fullStack, final IAEStack diffStack,
|
||||
final IActionSource src, final IStorageChannel chan) {
|
||||
if (this.configuredItem != null) {
|
||||
if (fullStack == null) {
|
||||
this.configuredItem.setStackSize(0);
|
||||
} else {
|
||||
this.configuredItem.setStackSize(fullStack.getStackSize());
|
||||
}
|
||||
|
||||
final long stackSize = this.configuredItem.getStackSize();
|
||||
final String humanReadableText = NUMBER_CONVERTER.toWideReadableForm(stackSize);
|
||||
|
||||
if (!humanReadableText.equals(this.lastHumanReadableText)) {
|
||||
this.lastHumanReadableText = humanReadableText;
|
||||
this.getHost().markForUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean showNetworkInfo(final HitResult where) {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected IPartModel selectModel(IPartModel off, IPartModel on, IPartModel hasChannel, IPartModel lockedOff,
|
||||
IPartModel lockedOn, IPartModel lockedHasChannel) {
|
||||
if (this.isActive()) {
|
||||
if (this.isLocked()) {
|
||||
return lockedHasChannel;
|
||||
} else {
|
||||
return hasChannel;
|
||||
}
|
||||
} else if (this.isPowered()) {
|
||||
if (this.isLocked()) {
|
||||
return lockedOn;
|
||||
} else {
|
||||
return on;
|
||||
}
|
||||
} else {
|
||||
if (this.isLocked()) {
|
||||
return lockedOff;
|
||||
} else {
|
||||
return off;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.reporting;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import appeng.api.util.AEColor;
|
||||
import appeng.core.AppEng;
|
||||
import appeng.items.parts.PartModels;
|
||||
|
||||
/**
|
||||
* A very simple part for emitting light.
|
||||
*
|
||||
* Opposed to the other subclass of {@link AbstractReportingPart}, it will only
|
||||
* use the bright front texture.
|
||||
*
|
||||
* @author AlgorithmX2
|
||||
* @author yueh
|
||||
* @version rv3
|
||||
* @since rv3
|
||||
*/
|
||||
public abstract class AbstractPanelPart extends AbstractReportingPart {
|
||||
|
||||
@PartModels
|
||||
public static final Identifier MODEL_BASE = new Identifier(AppEng.MOD_ID, "part/monitor_base");
|
||||
|
||||
public AbstractPanelPart(final ItemStack is) {
|
||||
super(is, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLightSource() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* How bright the color the panel should appear. Usually it depends on a
|
||||
* {@link AEColor} variant. This does not affect the actual light level of the
|
||||
* part.
|
||||
*
|
||||
* @return the brightness to be used.
|
||||
*/
|
||||
protected abstract int getBrightnessColor();
|
||||
|
||||
}
|
||||
@@ -1,279 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.reporting;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import appeng.api.implementations.IPowerChannelState;
|
||||
import appeng.api.implementations.parts.IMonitorPart;
|
||||
import appeng.api.networking.GridFlags;
|
||||
import appeng.api.networking.events.MENetworkBootingStatusChange;
|
||||
import appeng.api.networking.events.MENetworkEventSubscribe;
|
||||
import appeng.api.networking.events.MENetworkPowerStatusChange;
|
||||
import appeng.api.parts.IPartCollisionHelper;
|
||||
import appeng.api.parts.IPartModel;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
import appeng.me.GridAccessException;
|
||||
import appeng.parts.AEBasePart;
|
||||
import appeng.util.Platform;
|
||||
|
||||
/**
|
||||
* The most basic class for any part reporting information, like terminals or
|
||||
* monitors. This can also include basic panels which just provide light.
|
||||
*
|
||||
* It deals with the most basic functionalities like network data, grid
|
||||
* registration or the rotation of the actual part.
|
||||
*
|
||||
* The direct abstract subclasses are usually a better entry point for adding
|
||||
* new concrete ones. But this might be an ideal starting point to completely
|
||||
* new type, which does not resemble any existing one.
|
||||
*
|
||||
* @author AlgorithmX2
|
||||
* @author yueh
|
||||
* @version rv3
|
||||
* @since rv3
|
||||
*/
|
||||
public abstract class AbstractReportingPart extends AEBasePart implements IMonitorPart, IPowerChannelState {
|
||||
|
||||
protected static final int POWERED_FLAG = 4;
|
||||
protected static final int CHANNEL_FLAG = 16;
|
||||
private static final int BOOTING_FLAG = 8;
|
||||
|
||||
private byte spin = 0; // 0-3
|
||||
private int clientFlags = 0; // sent as byte.
|
||||
private int opacity = -1;
|
||||
|
||||
public AbstractReportingPart(final ItemStack is) {
|
||||
this(is, false);
|
||||
}
|
||||
|
||||
protected AbstractReportingPart(final ItemStack is, final boolean requireChannel) {
|
||||
super(is);
|
||||
|
||||
if (requireChannel) {
|
||||
this.getProxy().setFlags(GridFlags.REQUIRE_CHANNEL);
|
||||
this.getProxy().setIdlePowerUsage(1.0 / 2.0);
|
||||
} else {
|
||||
this.getProxy().setIdlePowerUsage(1.0 / 16.0); // lights drain a little bit.
|
||||
}
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public final void bootingRender(final MENetworkBootingStatusChange c) {
|
||||
if (!this.isLightSource()) {
|
||||
this.getHost().markForUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public final void powerRender(final MENetworkPowerStatusChange c) {
|
||||
this.getHost().markForUpdate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void getBoxes(final IPartCollisionHelper bch) {
|
||||
bch.addBox(2, 2, 14, 14, 14, 16);
|
||||
bch.addBox(4, 4, 13, 12, 12, 14);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onneighborUpdate(BlockView w, BlockPos pos, BlockPos neighbor) {
|
||||
if (pos.offset(this.getSide().getFacing()).equals(neighbor)) {
|
||||
this.opacity = -1;
|
||||
this.getHost().markForUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromNBT(final CompoundTag data) {
|
||||
super.readFromNBT(data);
|
||||
this.spin = data.getByte("spin");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToNBT(final CompoundTag data) {
|
||||
super.writeToNBT(data);
|
||||
data.putByte("spin", this.getSpin());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToStream(final PacketByteBuf data) throws IOException {
|
||||
super.writeToStream(data);
|
||||
this.clientFlags = this.getSpin() & 3;
|
||||
|
||||
try {
|
||||
if (this.getProxy().getEnergy().isNetworkPowered()) {
|
||||
this.clientFlags = this.getClientFlags() | AbstractReportingPart.POWERED_FLAG;
|
||||
}
|
||||
|
||||
if (this.getProxy().getPath().isNetworkBooting()) {
|
||||
this.clientFlags = this.getClientFlags() | AbstractReportingPart.BOOTING_FLAG;
|
||||
}
|
||||
|
||||
if (this.getProxy().getNode().meetsChannelRequirements()) {
|
||||
this.clientFlags = this.getClientFlags() | AbstractReportingPart.CHANNEL_FLAG;
|
||||
}
|
||||
} catch (final GridAccessException e) {
|
||||
// um.. nothing.
|
||||
}
|
||||
|
||||
data.writeByte((byte) this.getClientFlags());
|
||||
data.writeInt(this.opacity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean readFromStream(final PacketByteBuf data) throws IOException {
|
||||
super.readFromStream(data);
|
||||
final int oldFlags = this.getClientFlags();
|
||||
final int oldOpacity = this.opacity;
|
||||
|
||||
this.clientFlags = data.readByte();
|
||||
this.opacity = data.readInt();
|
||||
|
||||
this.spin = (byte) (this.getClientFlags() & 3);
|
||||
if (this.getClientFlags() == oldFlags && this.opacity == oldOpacity) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int getLightLevel() {
|
||||
return this.blockLight(this.isPowered() ? (this.isLightSource() ? 15 : 9) : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPartActivate(final PlayerEntity player, final Hand hand, final Vec3d pos) {
|
||||
final BlockEntity te = this.getTile();
|
||||
|
||||
if (Platform.isWrench(player, player.inventory.getCurrentItem(), te.getPos())) {
|
||||
if (Platform.isServer()) {
|
||||
if (this.getSpin() > 3) {
|
||||
this.spin = 0;
|
||||
}
|
||||
|
||||
switch (this.getSpin()) {
|
||||
case 0:
|
||||
this.spin = 1;
|
||||
break;
|
||||
case 1:
|
||||
this.spin = 3;
|
||||
break;
|
||||
case 2:
|
||||
this.spin = 0;
|
||||
break;
|
||||
case 3:
|
||||
this.spin = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
this.getHost().markForUpdate();
|
||||
this.saveChanges();
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return super.onPartActivate(player, hand, pos);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onPlacement(final PlayerEntity player, final Hand hand, final ItemStack held,
|
||||
final AEPartLocation side) {
|
||||
super.onPlacement(player, hand, held, side);
|
||||
|
||||
final byte rotation = (byte) (MathHelper.floor((player.yaw * 4F) / 360F + 2.5D) & 3);
|
||||
if (side == AEPartLocation.UP) {
|
||||
this.spin = rotation;
|
||||
} else if (side == AEPartLocation.DOWN) {
|
||||
this.spin = rotation;
|
||||
}
|
||||
}
|
||||
|
||||
private final int blockLight(final int emit) {
|
||||
if (this.opacity < 0) {
|
||||
final BlockEntity te = this.getTile();
|
||||
World world = te.getWorld();
|
||||
BlockPos pos = te.getPos().offset(this.getSide().getFacing());
|
||||
this.opacity = 255 - world.getBlockState(pos).getOpacity(world, pos);
|
||||
}
|
||||
|
||||
return (int) (emit * (this.opacity / 255.0f));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isPowered() {
|
||||
try {
|
||||
if (Platform.isServer()) {
|
||||
return this.getProxy().getEnergy().isNetworkPowered();
|
||||
} else {
|
||||
return ((this.getClientFlags() & PanelPart.POWERED_FLAG) == PanelPart.POWERED_FLAG);
|
||||
}
|
||||
} catch (final GridAccessException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isActive() {
|
||||
if (!this.isLightSource()) {
|
||||
return ((this.getClientFlags()
|
||||
& (PanelPart.CHANNEL_FLAG | PanelPart.POWERED_FLAG)) == (PanelPart.CHANNEL_FLAG
|
||||
| PanelPart.POWERED_FLAG));
|
||||
} else {
|
||||
return this.isPowered();
|
||||
}
|
||||
}
|
||||
|
||||
protected IPartModel selectModel(IPartModel offModels, IPartModel onModels, IPartModel hasChannelModels) {
|
||||
if (this.isActive()) {
|
||||
return hasChannelModels;
|
||||
} else if (this.isPowered()) {
|
||||
return onModels;
|
||||
} else {
|
||||
return offModels;
|
||||
}
|
||||
}
|
||||
|
||||
public final int getClientFlags() {
|
||||
return this.clientFlags;
|
||||
}
|
||||
|
||||
public final byte getSpin() {
|
||||
return this.spin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should the part emit light. This actually only affects the light level, light
|
||||
* source use a level of 15 and non light source 9.
|
||||
*/
|
||||
public abstract boolean isLightSource();
|
||||
|
||||
}
|
||||
@@ -1,145 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.reporting;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import alexiil.mc.lib.attributes.item.FixedItemInv;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.screen.ScreenHandlerType;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
import appeng.api.config.Settings;
|
||||
import appeng.api.config.SortDir;
|
||||
import appeng.api.config.SortOrder;
|
||||
import appeng.api.config.ViewItems;
|
||||
import appeng.api.implementations.tiles.IViewCellStorage;
|
||||
import appeng.api.storage.IMEMonitor;
|
||||
import appeng.api.storage.IStorageChannel;
|
||||
import appeng.api.storage.ITerminalHost;
|
||||
import appeng.api.storage.data.IAEStack;
|
||||
import appeng.api.util.IConfigManager;
|
||||
import appeng.container.ContainerLocator;
|
||||
import appeng.container.ContainerOpener;
|
||||
import appeng.container.implementations.MEMonitorableContainer;
|
||||
import appeng.me.GridAccessException;
|
||||
import appeng.tile.inventory.AppEngInternalInventory;
|
||||
import appeng.util.ConfigManager;
|
||||
import appeng.util.IConfigManagerHost;
|
||||
import appeng.util.inv.IAEAppEngInventory;
|
||||
import appeng.util.inv.InvOperation;
|
||||
|
||||
/**
|
||||
* Anything resembling an network terminal with view cells can reuse this.
|
||||
*
|
||||
* Note this applies only to terminals like the ME Terminal. It does not apply
|
||||
* for more specialized terminals like the Interface Terminal.
|
||||
*
|
||||
* @author AlgorithmX2
|
||||
* @author yueh
|
||||
* @version rv3
|
||||
* @since rv3
|
||||
*/
|
||||
public abstract class AbstractTerminalPart extends AbstractDisplayPart
|
||||
implements ITerminalHost, IConfigManagerHost, IViewCellStorage, IAEAppEngInventory {
|
||||
|
||||
private final IConfigManager cm = new ConfigManager(this);
|
||||
private final AppEngInternalInventory viewCell = new AppEngInternalInventory(this, 5);
|
||||
|
||||
public AbstractTerminalPart(final ItemStack is) {
|
||||
super(is);
|
||||
|
||||
this.cm.registerSetting(Settings.SORT_BY, SortOrder.NAME);
|
||||
this.cm.registerSetting(Settings.VIEW_MODE, ViewItems.ALL);
|
||||
this.cm.registerSetting(Settings.SORT_DIRECTION, SortDir.ASCENDING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getDrops(final List<ItemStack> drops, final boolean wrenched) {
|
||||
super.getDrops(drops, wrenched);
|
||||
|
||||
for (final ItemStack is : this.viewCell) {
|
||||
if (!is.isEmpty()) {
|
||||
drops.add(is);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IConfigManager getConfigManager() {
|
||||
return this.cm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromNBT(final CompoundTag data) {
|
||||
super.readFromNBT(data);
|
||||
this.cm.readFromNBT(data);
|
||||
this.viewCell.readFromNBT(data, "viewCell");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToNBT(final CompoundTag data) {
|
||||
super.writeToNBT(data);
|
||||
this.cm.writeToNBT(data);
|
||||
this.viewCell.writeToNBT(data, "viewCell");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPartActivate(final PlayerEntity player, final Hand hand, final Vec3d pos) {
|
||||
if (!super.onPartActivate(player, hand, pos)) {
|
||||
if (!player.world.isClient) {
|
||||
ContainerOpener.openContainer(getContainerType(player), player, ContainerLocator.forPart(this));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public ScreenHandlerType<?> getContainerType(final PlayerEntity player) {
|
||||
return MEMonitorableContainer.TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends IAEStack<T>> IMEMonitor<T> getInventory(IStorageChannel<T> channel) {
|
||||
try {
|
||||
return this.getProxy().getStorage().getInventory(channel);
|
||||
} catch (final GridAccessException e) {
|
||||
// err nope?
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSetting(final IConfigManager manager, final Settings settingName, final Enum<?> newValue) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public FixedItemInv getViewCellStorage() {
|
||||
return this.viewCell;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeInventory(final FixedItemInv inv, final int slot, final InvOperation mc,
|
||||
final ItemStack removedStack, final ItemStack newStack) {
|
||||
this.getHost().markForSave();
|
||||
}
|
||||
}
|
||||
@@ -1,229 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.reporting;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import alexiil.mc.lib.attributes.item.FixedItemInv;
|
||||
import net.minecraftforge.items.wrapper.PlayerMainInvWrapper;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.networking.energy.IEnergySource;
|
||||
import appeng.api.parts.IPartModel;
|
||||
import appeng.api.storage.IMEMonitor;
|
||||
import appeng.api.storage.channels.IItemStorageChannel;
|
||||
import appeng.api.storage.data.IAEItemStack;
|
||||
import appeng.core.AppEng;
|
||||
import appeng.helpers.Reflected;
|
||||
import appeng.items.parts.PartModels;
|
||||
import appeng.me.GridAccessException;
|
||||
import appeng.me.helpers.PlayerSource;
|
||||
import appeng.parts.PartModel;
|
||||
import appeng.util.InventoryAdaptor;
|
||||
import appeng.util.Platform;
|
||||
import appeng.util.item.AEItemStack;
|
||||
|
||||
public class ConversionMonitorPart extends AbstractMonitorPart {
|
||||
|
||||
@PartModels
|
||||
public static final Identifier MODEL_OFF = new Identifier(AppEng.MOD_ID, "part/conversion_monitor_off");
|
||||
@PartModels
|
||||
public static final Identifier MODEL_ON = new Identifier(AppEng.MOD_ID, "part/conversion_monitor_on");
|
||||
@PartModels
|
||||
public static final Identifier MODEL_LOCKED_OFF = new Identifier(AppEng.MOD_ID,
|
||||
"part/conversion_monitor_locked_off");
|
||||
@PartModels
|
||||
public static final Identifier MODEL_LOCKED_ON = new Identifier(AppEng.MOD_ID,
|
||||
"part/conversion_monitor_locked_on");
|
||||
|
||||
public static final IPartModel MODELS_OFF = new PartModel(MODEL_BASE, MODEL_OFF, MODEL_STATUS_OFF);
|
||||
public static final IPartModel MODELS_ON = new PartModel(MODEL_BASE, MODEL_ON, MODEL_STATUS_ON);
|
||||
public static final IPartModel MODELS_HAS_CHANNEL = new PartModel(MODEL_BASE, MODEL_ON, MODEL_STATUS_HAS_CHANNEL);
|
||||
public static final IPartModel MODELS_LOCKED_OFF = new PartModel(MODEL_BASE, MODEL_LOCKED_OFF, MODEL_STATUS_OFF);
|
||||
public static final IPartModel MODELS_LOCKED_ON = new PartModel(MODEL_BASE, MODEL_LOCKED_ON, MODEL_STATUS_ON);
|
||||
public static final IPartModel MODELS_LOCKED_HAS_CHANNEL = new PartModel(MODEL_BASE, MODEL_LOCKED_ON,
|
||||
MODEL_STATUS_HAS_CHANNEL);
|
||||
|
||||
@Reflected
|
||||
public ConversionMonitorPart(final ItemStack is) {
|
||||
super(is);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPartActivate(PlayerEntity player, Hand hand, Vec3d pos) {
|
||||
if (Platform.isClient()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!this.getProxy().isActive()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Platform.hasPermissions(this.getLocation(), player)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final ItemStack eq = player.getStackInHand(hand);
|
||||
if (this.isLocked()) {
|
||||
if (eq.isEmpty()) {
|
||||
this.insertItem(player, hand, true);
|
||||
} else if (Platform.isWrench(player, eq, this.getLocation().getPos())
|
||||
&& (this.getDisplayed() == null || !this.getDisplayed().equals(eq))) {
|
||||
// wrench it
|
||||
return super.onPartActivate(player, hand, pos);
|
||||
} else {
|
||||
this.insertItem(player, hand, false);
|
||||
}
|
||||
} else if (this.getDisplayed() != null && this.getDisplayed().equals(eq)) {
|
||||
this.insertItem(player, hand, false);
|
||||
} else {
|
||||
return super.onPartActivate(player, hand, pos);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onClicked(PlayerEntity player, Hand hand, Vec3d pos) {
|
||||
if (Platform.isClient()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!this.getProxy().isActive()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Platform.hasPermissions(this.getLocation(), player)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.getDisplayed() != null) {
|
||||
this.extractItem(player, this.getDisplayed().getDefinition().getMaxCount());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onShiftClicked(PlayerEntity player, Hand hand, Vec3d pos) {
|
||||
if (Platform.isClient()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!this.getProxy().isActive()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Platform.hasPermissions(this.getLocation(), player)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.getDisplayed() != null) {
|
||||
this.extractItem(player, 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void insertItem(final PlayerEntity player, final Hand hand, final boolean allItems) {
|
||||
try {
|
||||
final IEnergySource energy = this.getProxy().getEnergy();
|
||||
final IMEMonitor<IAEItemStack> cell = this.getProxy().getStorage()
|
||||
.getInventory(AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class));
|
||||
|
||||
if (allItems) {
|
||||
if (this.getDisplayed() != null) {
|
||||
final IAEItemStack input = this.getDisplayed().copy();
|
||||
FixedItemInv inv = new PlayerMainInvWrapper(player.inventory);
|
||||
|
||||
for (int x = 0; x < inv.getSlotCount(); x++) {
|
||||
final ItemStack targetStack = inv.getInvStack(x);
|
||||
if (input.equals(targetStack)) {
|
||||
final ItemStack canExtract = inv.extractItem(x, targetStack.getCount(), true);
|
||||
if (!canExtract.isEmpty()) {
|
||||
input.setStackSize(canExtract.getCount());
|
||||
final IAEItemStack failedToInsert = Platform.poweredInsert(energy, cell, input,
|
||||
new PlayerSource(player, this));
|
||||
inv.extractItem(x, failedToInsert == null ? canExtract.getCount()
|
||||
: canExtract.getCount() - (int) failedToInsert.getStackSize(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
final IAEItemStack input = AEItemStack.fromItemStack(player.getStackInHand(hand));
|
||||
final IAEItemStack failedToInsert = Platform.poweredInsert(energy, cell, input,
|
||||
new PlayerSource(player, this));
|
||||
player.setStackInHand(hand, failedToInsert == null ? ItemStack.EMPTY : failedToInsert.createItemStack());
|
||||
}
|
||||
} catch (final GridAccessException e) {
|
||||
// :P
|
||||
}
|
||||
}
|
||||
|
||||
private void extractItem(final PlayerEntity player, int count) {
|
||||
final IAEItemStack input = this.getDisplayed();
|
||||
if (input != null) {
|
||||
try {
|
||||
if (!this.getProxy().isActive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final IEnergySource energy = this.getProxy().getEnergy();
|
||||
final IMEMonitor<IAEItemStack> cell = this.getProxy().getStorage()
|
||||
.getInventory(AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class));
|
||||
|
||||
input.setStackSize(count);
|
||||
|
||||
final IAEItemStack retrieved = Platform.poweredExtraction(energy, cell, input,
|
||||
new PlayerSource(player, this));
|
||||
if (retrieved != null) {
|
||||
ItemStack newItems = retrieved.createItemStack();
|
||||
final InventoryAdaptor adaptor = InventoryAdaptor.getAdaptor(player);
|
||||
newItems = adaptor.addItems(newItems);
|
||||
if (!newItems.isEmpty()) {
|
||||
final BlockEntity te = this.getTile();
|
||||
final List<ItemStack> list = Collections.singletonList(newItems);
|
||||
Platform.spawnDrops(player.world, te.getPos().offset(this.getSide().getFacing()), list);
|
||||
}
|
||||
|
||||
if (player.openContainer != null) {
|
||||
player.openContainer.detectAndSendChanges();
|
||||
}
|
||||
}
|
||||
} catch (final GridAccessException e) {
|
||||
// :P
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPartModel getStaticModels() {
|
||||
return this.selectModel(MODELS_OFF, MODELS_ON, MODELS_HAS_CHANNEL, MODELS_LOCKED_OFF, MODELS_LOCKED_ON,
|
||||
MODELS_LOCKED_HAS_CHANNEL);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.reporting;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import alexiil.mc.lib.attributes.item.FixedItemInv;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.screen.ScreenHandlerType;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import appeng.api.config.SecurityPermissions;
|
||||
import appeng.api.parts.IPartModel;
|
||||
import appeng.container.implementations.CraftingTermContainer;
|
||||
import appeng.container.implementations.MEMonitorableContainer;
|
||||
import appeng.core.AppEng;
|
||||
import appeng.helpers.Reflected;
|
||||
import appeng.items.parts.PartModels;
|
||||
import appeng.parts.PartModel;
|
||||
import appeng.tile.inventory.AppEngInternalInventory;
|
||||
import appeng.util.Platform;
|
||||
|
||||
public class CraftingTerminalPart extends AbstractTerminalPart {
|
||||
|
||||
@PartModels
|
||||
public static final Identifier MODEL_OFF = new Identifier(AppEng.MOD_ID, "part/crafting_terminal_off");
|
||||
@PartModels
|
||||
public static final Identifier MODEL_ON = new Identifier(AppEng.MOD_ID, "part/crafting_terminal_on");
|
||||
|
||||
public static final IPartModel MODELS_OFF = new PartModel(MODEL_BASE, MODEL_OFF, MODEL_STATUS_OFF);
|
||||
public static final IPartModel MODELS_ON = new PartModel(MODEL_BASE, MODEL_ON, MODEL_STATUS_ON);
|
||||
public static final IPartModel MODELS_HAS_CHANNEL = new PartModel(MODEL_BASE, MODEL_ON, MODEL_STATUS_HAS_CHANNEL);
|
||||
|
||||
private final AppEngInternalInventory craftingGrid = new AppEngInternalInventory(this, 9);
|
||||
|
||||
@Reflected
|
||||
public CraftingTerminalPart(final ItemStack is) {
|
||||
super(is);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getDrops(final List<ItemStack> drops, final boolean wrenched) {
|
||||
super.getDrops(drops, wrenched);
|
||||
|
||||
for (final ItemStack is : this.craftingGrid) {
|
||||
if (!is.isEmpty()) {
|
||||
drops.add(is);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromNBT(final CompoundTag data) {
|
||||
super.readFromNBT(data);
|
||||
this.craftingGrid.readFromNBT(data, "craftingGrid");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToNBT(final CompoundTag data) {
|
||||
super.writeToNBT(data);
|
||||
this.craftingGrid.writeToNBT(data, "craftingGrid");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScreenHandlerType<?> getContainerType(final PlayerEntity p) {
|
||||
if (Platform.checkPermissions(p, this, SecurityPermissions.CRAFT, false)) {
|
||||
return CraftingTermContainer.TYPE;
|
||||
}
|
||||
return MEMonitorableContainer.TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FixedItemInv getInventoryByName(final String name) {
|
||||
if (name.equals("crafting")) {
|
||||
return this.craftingGrid;
|
||||
}
|
||||
return super.getInventoryByName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPartModel getStaticModels() {
|
||||
return this.selectModel(MODELS_OFF, MODELS_ON, MODELS_HAS_CHANNEL);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.reporting;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import appeng.api.parts.IPartModel;
|
||||
import appeng.core.AppEng;
|
||||
import appeng.helpers.Reflected;
|
||||
import appeng.items.parts.PartModels;
|
||||
import appeng.parts.PartModel;
|
||||
|
||||
public class DarkPanelPart extends AbstractPanelPart {
|
||||
|
||||
@PartModels
|
||||
public static final Identifier MODEL_OFF = new Identifier(AppEng.MOD_ID, "part/monitor_dark_off");
|
||||
@PartModels
|
||||
public static final Identifier MODEL_ON = new Identifier(AppEng.MOD_ID, "part/monitor_dark_on");
|
||||
|
||||
public static final IPartModel MODELS_OFF = new PartModel(MODEL_BASE, MODEL_OFF);
|
||||
public static final IPartModel MODELS_ON = new PartModel(MODEL_BASE, MODEL_ON);
|
||||
|
||||
@Reflected
|
||||
public DarkPanelPart(final ItemStack is) {
|
||||
super(is);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getBrightnessColor() {
|
||||
return this.getColor().mediumVariant;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPartModel getStaticModels() {
|
||||
return this.isPowered() ? MODELS_ON : MODELS_OFF;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.reporting;
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
import appeng.api.parts.IPartModel;
|
||||
import appeng.container.ContainerLocator;
|
||||
import appeng.container.ContainerOpener;
|
||||
import appeng.container.implementations.InterfaceTerminalContainer;
|
||||
import appeng.core.AppEng;
|
||||
import appeng.items.parts.PartModels;
|
||||
import appeng.parts.PartModel;
|
||||
import appeng.util.Platform;
|
||||
|
||||
public class InterfaceTerminalPart extends AbstractDisplayPart {
|
||||
|
||||
@PartModels
|
||||
public static final Identifier MODEL_OFF = new Identifier(AppEng.MOD_ID, "part/interface_terminal_off");
|
||||
@PartModels
|
||||
public static final Identifier MODEL_ON = new Identifier(AppEng.MOD_ID, "part/interface_terminal_on");
|
||||
|
||||
public static final IPartModel MODELS_OFF = new PartModel(MODEL_BASE, MODEL_OFF, MODEL_STATUS_OFF);
|
||||
public static final IPartModel MODELS_ON = new PartModel(MODEL_BASE, MODEL_ON, MODEL_STATUS_ON);
|
||||
public static final IPartModel MODELS_HAS_CHANNEL = new PartModel(MODEL_BASE, MODEL_ON, MODEL_STATUS_HAS_CHANNEL);
|
||||
|
||||
public InterfaceTerminalPart(final ItemStack is) {
|
||||
super(is);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPartActivate(final PlayerEntity player, final Hand hand, final Vec3d pos) {
|
||||
if (!super.onPartActivate(player, hand, pos)) {
|
||||
if (Platform.isServer()) {
|
||||
ContainerOpener.openContainer(InterfaceTerminalContainer.TYPE, player, ContainerLocator.forPart(this));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPartModel getStaticModels() {
|
||||
return this.selectModel(MODELS_OFF, MODELS_ON, MODELS_HAS_CHANNEL);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.reporting;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import appeng.api.parts.IPartModel;
|
||||
import appeng.core.AppEng;
|
||||
import appeng.helpers.Reflected;
|
||||
import appeng.items.parts.PartModels;
|
||||
import appeng.parts.PartModel;
|
||||
|
||||
public class PanelPart extends AbstractPanelPart {
|
||||
|
||||
@PartModels
|
||||
public static final Identifier MODEL_OFF = new Identifier(AppEng.MOD_ID, "part/monitor_bright_off");
|
||||
@PartModels
|
||||
public static final Identifier MODEL_ON = new Identifier(AppEng.MOD_ID, "part/monitor_bright_on");
|
||||
|
||||
public static final IPartModel MODELS_OFF = new PartModel(MODEL_BASE, MODEL_OFF);
|
||||
public static final IPartModel MODELS_ON = new PartModel(MODEL_BASE, MODEL_ON);
|
||||
|
||||
@Reflected
|
||||
public PanelPart(final ItemStack is) {
|
||||
super(is);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getBrightnessColor() {
|
||||
return this.getColor().whiteVariant;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPartModel getStaticModels() {
|
||||
return this.isPowered() ? MODELS_ON : MODELS_OFF;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,185 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.reporting;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.screen.ScreenHandlerType;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.util.Identifier;
|
||||
import alexiil.mc.lib.attributes.item.FixedItemInv;
|
||||
|
||||
import appeng.api.config.SecurityPermissions;
|
||||
import appeng.api.implementations.ICraftingPatternItem;
|
||||
import appeng.api.networking.crafting.ICraftingPatternDetails;
|
||||
import appeng.api.parts.IPartModel;
|
||||
import appeng.api.storage.data.IAEItemStack;
|
||||
import appeng.container.implementations.MEMonitorableContainer;
|
||||
import appeng.container.implementations.PatternTermContainer;
|
||||
import appeng.core.AppEng;
|
||||
import appeng.helpers.Reflected;
|
||||
import appeng.items.parts.PartModels;
|
||||
import appeng.parts.PartModel;
|
||||
import appeng.tile.inventory.AppEngInternalInventory;
|
||||
import appeng.util.Platform;
|
||||
import appeng.util.inv.InvOperation;
|
||||
|
||||
public class PatternTerminalPart extends AbstractTerminalPart {
|
||||
|
||||
@PartModels
|
||||
public static final Identifier MODEL_OFF = new Identifier(AppEng.MOD_ID, "part/pattern_terminal_off");
|
||||
@PartModels
|
||||
public static final Identifier MODEL_ON = new Identifier(AppEng.MOD_ID, "part/pattern_terminal_on");
|
||||
|
||||
public static final IPartModel MODELS_OFF = new PartModel(MODEL_BASE, MODEL_OFF, MODEL_STATUS_OFF);
|
||||
public static final IPartModel MODELS_ON = new PartModel(MODEL_BASE, MODEL_ON, MODEL_STATUS_ON);
|
||||
public static final IPartModel MODELS_HAS_CHANNEL = new PartModel(MODEL_BASE, MODEL_ON, MODEL_STATUS_HAS_CHANNEL);
|
||||
|
||||
private final AppEngInternalInventory crafting = new AppEngInternalInventory(this, 9);
|
||||
private final AppEngInternalInventory output = new AppEngInternalInventory(this, 3);
|
||||
private final AppEngInternalInventory pattern = new AppEngInternalInventory(this, 2);
|
||||
|
||||
private boolean craftingMode = true;
|
||||
private boolean substitute = false;
|
||||
|
||||
@Reflected
|
||||
public PatternTerminalPart(final ItemStack is) {
|
||||
super(is);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getDrops(final List<ItemStack> drops, final boolean wrenched) {
|
||||
for (final ItemStack is : this.pattern) {
|
||||
if (!is.isEmpty()) {
|
||||
drops.add(is);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromNBT(final CompoundTag data) {
|
||||
super.readFromNBT(data);
|
||||
this.setCraftingRecipe(data.getBoolean("craftingMode"));
|
||||
this.setSubstitution(data.getBoolean("substitute"));
|
||||
this.pattern.readFromNBT(data, "pattern");
|
||||
this.output.readFromNBT(data, "outputList");
|
||||
this.crafting.readFromNBT(data, "craftingGrid");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToNBT(final CompoundTag data) {
|
||||
super.writeToNBT(data);
|
||||
data.putBoolean("craftingMode", this.craftingMode);
|
||||
data.putBoolean("substitute", this.substitute);
|
||||
this.pattern.writeToNBT(data, "pattern");
|
||||
this.output.writeToNBT(data, "outputList");
|
||||
this.crafting.writeToNBT(data, "craftingGrid");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScreenHandlerType<?> getContainerType(final PlayerEntity p) {
|
||||
if (Platform.checkPermissions(p, this, SecurityPermissions.CRAFT, false)) {
|
||||
return PatternTermContainer.TYPE;
|
||||
}
|
||||
return MEMonitorableContainer.TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeInventory(final FixedItemInv inv, final int slot, final InvOperation mc,
|
||||
final ItemStack removedStack, final ItemStack newStack) {
|
||||
if (inv == this.pattern && slot == 1) {
|
||||
final ItemStack is = this.pattern.getInvStack(1);
|
||||
if (!is.isEmpty() && is.getItem() instanceof ICraftingPatternItem) {
|
||||
final ICraftingPatternItem pattern = (ICraftingPatternItem) is.getItem();
|
||||
final ICraftingPatternDetails details = pattern.getPatternForItem(is,
|
||||
this.getHost().getTile().getWorld());
|
||||
if (details != null) {
|
||||
this.setCraftingRecipe(details.isCraftable());
|
||||
this.setSubstitution(details.canSubstitute());
|
||||
|
||||
for (int x = 0; x < this.crafting.getSlotCount() && x < details.getInputs().length; x++) {
|
||||
final IAEItemStack item = details.getInputs()[x];
|
||||
this.crafting.setInvStack(x, item == null ? ItemStack.EMPTY : item.createItemStack());
|
||||
}
|
||||
|
||||
for (int x = 0; x < this.output.getSlotCount() && x < details.getOutputs().length; x++) {
|
||||
final IAEItemStack item = details.getOutputs()[x];
|
||||
this.output.setInvStack(x, item == null ? ItemStack.EMPTY : item.createItemStack());
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (inv == this.crafting) {
|
||||
this.fixCraftingRecipes();
|
||||
}
|
||||
|
||||
this.getHost().markForSave();
|
||||
}
|
||||
|
||||
private void fixCraftingRecipes() {
|
||||
if (this.craftingMode) {
|
||||
for (int x = 0; x < this.crafting.getSlotCount(); x++) {
|
||||
final ItemStack is = this.crafting.getInvStack(x);
|
||||
if (!is.isEmpty()) {
|
||||
is.setCount(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isCraftingRecipe() {
|
||||
return this.craftingMode;
|
||||
}
|
||||
|
||||
public void setCraftingRecipe(final boolean craftingMode) {
|
||||
this.craftingMode = craftingMode;
|
||||
this.fixCraftingRecipes();
|
||||
}
|
||||
|
||||
public boolean isSubstitution() {
|
||||
return this.substitute;
|
||||
}
|
||||
|
||||
public void setSubstitution(final boolean canSubstitute) {
|
||||
this.substitute = canSubstitute;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FixedItemInv getInventoryByName(final String name) {
|
||||
if (name.equals("crafting")) {
|
||||
return this.crafting;
|
||||
}
|
||||
|
||||
if (name.equals("output")) {
|
||||
return this.output;
|
||||
}
|
||||
|
||||
if (name.equals("pattern")) {
|
||||
return this.pattern;
|
||||
}
|
||||
|
||||
return super.getInventoryByName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPartModel getStaticModels() {
|
||||
return this.selectModel(MODELS_OFF, MODELS_ON, MODELS_HAS_CHANNEL);
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.reporting;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import appeng.api.parts.IPartModel;
|
||||
import appeng.core.AppEng;
|
||||
import appeng.helpers.Reflected;
|
||||
import appeng.items.parts.PartModels;
|
||||
import appeng.parts.PartModel;
|
||||
|
||||
public class SemiDarkPanelPart extends AbstractPanelPart {
|
||||
@PartModels
|
||||
public static final Identifier MODEL_OFF = new Identifier(AppEng.MOD_ID, "part/monitor_medium_off");
|
||||
@PartModels
|
||||
public static final Identifier MODEL_ON = new Identifier(AppEng.MOD_ID, "part/monitor_medium_on");
|
||||
|
||||
public static final PartModel MODELS_OFF = new PartModel(MODEL_BASE, MODEL_OFF);
|
||||
public static final IPartModel MODELS_ON = new PartModel(MODEL_BASE, MODEL_ON);
|
||||
|
||||
@Reflected
|
||||
public SemiDarkPanelPart(final ItemStack is) {
|
||||
super(is);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getBrightnessColor() {
|
||||
final int light = this.getColor().whiteVariant;
|
||||
final int dark = this.getColor().mediumVariant;
|
||||
return (((((light >> 16) & 0xff) + ((dark >> 16) & 0xff)) / 2) << 16)
|
||||
| (((((light >> 8) & 0xff) + ((dark >> 8) & 0xff)) / 2) << 8)
|
||||
| ((((light) & 0xff) + ((dark) & 0xff)) / 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPartModel getStaticModels() {
|
||||
return this.isPowered() ? MODELS_ON : MODELS_OFF;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.reporting;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import appeng.api.parts.IPartModel;
|
||||
import appeng.core.AppEng;
|
||||
import appeng.helpers.Reflected;
|
||||
import appeng.items.parts.PartModels;
|
||||
import appeng.parts.PartModel;
|
||||
|
||||
/**
|
||||
* @author AlgorithmX2
|
||||
* @author thatsIch
|
||||
* @version rv2
|
||||
* @since rv0
|
||||
*/
|
||||
public class StorageMonitorPart extends AbstractMonitorPart {
|
||||
|
||||
@PartModels
|
||||
public static final Identifier MODEL_OFF = new Identifier(AppEng.MOD_ID, "part/storage_monitor_off");
|
||||
@PartModels
|
||||
public static final Identifier MODEL_ON = new Identifier(AppEng.MOD_ID, "part/storage_monitor_on");
|
||||
@PartModels
|
||||
public static final Identifier MODEL_LOCKED_OFF = new Identifier(AppEng.MOD_ID,
|
||||
"part/storage_monitor_locked_off");
|
||||
@PartModels
|
||||
public static final Identifier MODEL_LOCKED_ON = new Identifier(AppEng.MOD_ID,
|
||||
"part/storage_monitor_locked_on");
|
||||
|
||||
public static final IPartModel MODELS_OFF = new PartModel(MODEL_BASE, MODEL_OFF, MODEL_STATUS_OFF);
|
||||
public static final IPartModel MODELS_ON = new PartModel(MODEL_BASE, MODEL_ON, MODEL_STATUS_ON);
|
||||
public static final IPartModel MODELS_HAS_CHANNEL = new PartModel(MODEL_BASE, MODEL_ON, MODEL_STATUS_HAS_CHANNEL);
|
||||
|
||||
public static final IPartModel MODELS_LOCKED_OFF = new PartModel(MODEL_BASE, MODEL_LOCKED_OFF, MODEL_STATUS_OFF);
|
||||
public static final IPartModel MODELS_LOCKED_ON = new PartModel(MODEL_BASE, MODEL_LOCKED_ON, MODEL_STATUS_ON);
|
||||
public static final IPartModel MODELS_LOCKED_HAS_CHANNEL = new PartModel(MODEL_BASE, MODEL_LOCKED_ON,
|
||||
MODEL_STATUS_HAS_CHANNEL);
|
||||
|
||||
@Reflected
|
||||
public StorageMonitorPart(final ItemStack is) {
|
||||
super(is);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPartModel getStaticModels() {
|
||||
return this.selectModel(MODELS_OFF, MODELS_ON, MODELS_HAS_CHANNEL, MODELS_LOCKED_OFF, MODELS_LOCKED_ON,
|
||||
MODELS_LOCKED_HAS_CHANNEL);
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, 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.parts.reporting;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import appeng.api.parts.IPartModel;
|
||||
import appeng.core.AppEng;
|
||||
import appeng.items.parts.PartModels;
|
||||
import appeng.parts.PartModel;
|
||||
|
||||
public class TerminalPart extends AbstractTerminalPart {
|
||||
|
||||
@PartModels
|
||||
public static final Identifier MODEL_OFF = new Identifier(AppEng.MOD_ID, "part/terminal_off");
|
||||
@PartModels
|
||||
public static final Identifier MODEL_ON = new Identifier(AppEng.MOD_ID, "part/terminal_on");
|
||||
|
||||
public static final IPartModel MODELS_OFF = new PartModel(MODEL_BASE, MODEL_OFF, MODEL_STATUS_OFF);
|
||||
public static final IPartModel MODELS_ON = new PartModel(MODEL_BASE, MODEL_ON, MODEL_STATUS_ON);
|
||||
public static final IPartModel MODELS_HAS_CHANNEL = new PartModel(MODEL_BASE, MODEL_ON, MODEL_STATUS_HAS_CHANNEL);
|
||||
|
||||
public TerminalPart(final ItemStack is) {
|
||||
super(is);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPartModel getStaticModels() {
|
||||
return this.selectModel(MODELS_OFF, MODELS_ON, MODELS_HAS_CHANNEL);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user