Moving to source sets
This commit is contained in:
@@ -0,0 +1,451 @@
|
||||
/*
|
||||
* 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.tile;
|
||||
|
||||
import alexiil.mc.lib.attributes.AttributeList;
|
||||
import alexiil.mc.lib.attributes.AttributeProvider;
|
||||
import alexiil.mc.lib.attributes.item.FixedItemInv;
|
||||
import appeng.api.implementations.tiles.ISegmentedInventory;
|
||||
import appeng.api.util.ICommonTile;
|
||||
import appeng.api.util.IConfigManager;
|
||||
import appeng.api.util.IConfigurableObject;
|
||||
import appeng.api.util.IOrientable;
|
||||
import appeng.block.AEBaseTileBlock;
|
||||
import appeng.client.render.model.AEModelData;
|
||||
import appeng.core.AELog;
|
||||
import appeng.core.features.IStackSrc;
|
||||
import appeng.helpers.ICustomNameObject;
|
||||
import appeng.helpers.IPriorityHost;
|
||||
import appeng.tile.inventory.AppEngInternalAEInventory;
|
||||
import appeng.util.Platform;
|
||||
import appeng.util.SettingsFrom;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import net.fabricmc.fabric.api.block.entity.BlockEntityClientSerializable;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerChunkEvents;
|
||||
import net.fabricmc.fabric.api.rendering.data.v1.RenderAttachmentBlockEntity;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.item.ItemPlacementContext;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.text.LiteralText;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class AEBaseBlockEntity extends BlockEntity implements IOrientable, ICommonTile, ICustomNameObject, BlockEntityClientSerializable, RenderAttachmentBlockEntity, AttributeProvider {
|
||||
|
||||
// FIXME: should probably remove at start of next server tick!
|
||||
static {
|
||||
ServerChunkEvents.CHUNK_UNLOAD.register((serverWorld, worldChunk) -> {
|
||||
List<AEBaseBlockEntity> entitiesToRemove = null;
|
||||
for (BlockEntity value : worldChunk.getBlockEntities().values()) {
|
||||
if (value instanceof AEBaseBlockEntity) {
|
||||
if (entitiesToRemove == null) {
|
||||
entitiesToRemove = new ArrayList<>();
|
||||
}
|
||||
entitiesToRemove.add((AEBaseBlockEntity) value);
|
||||
}
|
||||
}
|
||||
if (entitiesToRemove != null) {
|
||||
for (AEBaseBlockEntity blockEntity : entitiesToRemove) {
|
||||
blockEntity.onChunkUnloaded();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void onChunkUnloaded() {
|
||||
}
|
||||
|
||||
private static final ThreadLocal<WeakReference<AEBaseBlockEntity>> DROP_NO_ITEMS = new ThreadLocal<>();
|
||||
private static final Map<Class<? extends BlockEntity>, IStackSrc> ITEM_STACKS = new HashMap<>();
|
||||
private int renderFragment = 0;
|
||||
@Nullable
|
||||
private String customName;
|
||||
private Direction forward = Direction.NORTH;
|
||||
private Direction up = Direction.UP;
|
||||
private boolean markDirtyQueued = false;
|
||||
|
||||
public AEBaseBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
}
|
||||
|
||||
public static void registerTileItem(final Class<? extends BlockEntity> c, final IStackSrc wat) {
|
||||
ITEM_STACKS.put(c, wat);
|
||||
}
|
||||
|
||||
public boolean dropItems() {
|
||||
final WeakReference<AEBaseBlockEntity> what = DROP_NO_ITEMS.get();
|
||||
return what == null || what.get() != this;
|
||||
}
|
||||
|
||||
public boolean notLoaded() {
|
||||
return !this.world.isChunkLoaded(this.pos);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public BlockEntity getTile() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected ItemStack getItemFromTile(final Object obj) {
|
||||
final IStackSrc src = ITEM_STACKS.get(obj.getClass());
|
||||
if (src == null) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
return src.stack(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromTag(BlockState state, final CompoundTag data) {
|
||||
super.fromTag(state, data);
|
||||
|
||||
if (data.contains("customName")) {
|
||||
this.customName = data.getString("customName");
|
||||
} else {
|
||||
this.customName = null;
|
||||
}
|
||||
|
||||
try {
|
||||
if (this.canBeRotated()) {
|
||||
this.forward = Direction.valueOf(data.getString("forward"));
|
||||
this.up = Direction.valueOf(data.getString("up"));
|
||||
}
|
||||
} catch (final IllegalArgumentException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag toTag(final CompoundTag data) {
|
||||
super.toTag(data);
|
||||
|
||||
if (this.canBeRotated()) {
|
||||
data.putString("forward", this.getForward().name());
|
||||
data.putString("up", this.getUp().name());
|
||||
}
|
||||
|
||||
if (this.customName != null) {
|
||||
data.putString("customName", this.customName);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public void onReady() {
|
||||
}
|
||||
|
||||
private boolean readUpdateData(PacketByteBuf stream) {
|
||||
boolean output = false;
|
||||
|
||||
try {
|
||||
this.renderFragment = 100;
|
||||
|
||||
output = this.readFromStream(stream);
|
||||
|
||||
if ((this.renderFragment & 1) == 1) {
|
||||
output = true;
|
||||
}
|
||||
this.renderFragment = 0;
|
||||
} catch (final Throwable t) {
|
||||
AELog.debug(t);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag toClientTag(CompoundTag data) {
|
||||
boolean finished = false;
|
||||
|
||||
final PacketByteBuf stream = new PacketByteBuf(Unpooled.buffer());
|
||||
|
||||
try {
|
||||
this.writeToStream(stream);
|
||||
if (stream.readableBytes() == 0) {
|
||||
finished = true;
|
||||
}
|
||||
} catch (final Throwable t) {
|
||||
AELog.debug(t);
|
||||
}
|
||||
if (!finished) {
|
||||
stream.capacity(stream.readableBytes());
|
||||
data.putByteArray("X", stream.array());
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles tile entites that are being received by the client as part of a full
|
||||
* chunk.
|
||||
*/
|
||||
@Override
|
||||
public void fromClientTag(CompoundTag tag) {
|
||||
final PacketByteBuf stream = new PacketByteBuf(Unpooled.copiedBuffer(tag.getByteArray("X")));
|
||||
|
||||
if (this.readUpdateData(stream)) {
|
||||
this.markForUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean readFromStream(final PacketByteBuf data) throws IOException {
|
||||
if (this.canBeRotated()) {
|
||||
final Direction old_Forward = this.forward;
|
||||
final Direction old_Up = this.up;
|
||||
|
||||
final byte orientation = data.readByte();
|
||||
this.forward = Direction.values()[orientation & 0x7];
|
||||
this.up = Direction.values()[orientation >> 3];
|
||||
|
||||
return this.forward != old_Forward || this.up != old_Up;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void writeToStream(final PacketByteBuf data) throws IOException {
|
||||
if (this.canBeRotated()) {
|
||||
final byte orientation = (byte) ((this.up.ordinal() << 3) | this.forward.ordinal());
|
||||
data.writeByte(orientation);
|
||||
}
|
||||
}
|
||||
|
||||
public void markForUpdate() {
|
||||
if (this.renderFragment > 0) {
|
||||
this.renderFragment |= 1;
|
||||
} else {
|
||||
// TODO: Optimize Network Load
|
||||
if (this.world != null) {
|
||||
boolean alreadyUpdated = false;
|
||||
// Let the block update it's own state with our internal state changes
|
||||
BlockState currentState = getCachedState();
|
||||
if (currentState.getBlock() instanceof AEBaseTileBlock) {
|
||||
AEBaseTileBlock<?> tileBlock = (AEBaseTileBlock<?>) currentState.getBlock();
|
||||
BlockState newState = tileBlock.getBlockEntityBlockState(currentState, this);
|
||||
if (currentState != newState) {
|
||||
AELog.blockUpdate(this.pos, currentState, newState, this);
|
||||
this.world.setBlockState(pos, newState);
|
||||
alreadyUpdated = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!alreadyUpdated) {
|
||||
this.world.updateListeners(this.pos, currentState, currentState, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* By default all blocks can have orientation, this handles saving, and loading,
|
||||
* as well as synchronization.
|
||||
*
|
||||
* @return true if tile can be rotated
|
||||
*/
|
||||
@Override
|
||||
public boolean canBeRotated() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Direction getForward() {
|
||||
return this.forward;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Direction getUp() {
|
||||
return this.up;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOrientation(final Direction inForward, final Direction inUp) {
|
||||
this.forward = inForward;
|
||||
this.up = inUp;
|
||||
this.markForUpdate();
|
||||
Platform.notifyBlocksOfNeighbors(this.world, this.pos);
|
||||
}
|
||||
|
||||
public void onPlacement(ItemPlacementContext context) {
|
||||
ItemStack stack = context.getStack();
|
||||
if (stack.hasTag()) {
|
||||
this.uploadSettings(SettingsFrom.DISMANTLE_ITEM, stack.getTag());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
public void uploadSettings(final SettingsFrom from, final CompoundTag compound) {
|
||||
if (this instanceof IConfigurableObject) {
|
||||
final IConfigManager cm = ((IConfigurableObject) this).getConfigManager();
|
||||
if (cm != null) {
|
||||
cm.readFromNBT(compound);
|
||||
}
|
||||
}
|
||||
|
||||
if (this instanceof IPriorityHost) {
|
||||
final IPriorityHost pHost = (IPriorityHost) this;
|
||||
pHost.setPriority(compound.getInt("priority"));
|
||||
}
|
||||
|
||||
if (this instanceof ISegmentedInventory) {
|
||||
final FixedItemInv inv = ((ISegmentedInventory) 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the contents of the block entity, into the world, defaults to dropping
|
||||
* everything in the inventory.
|
||||
*
|
||||
* @param w world
|
||||
* @param pos block position
|
||||
* @param drops drops of block entity
|
||||
*/
|
||||
@Override
|
||||
public void getDrops(final World w, final BlockPos pos, final List<ItemStack> drops) {
|
||||
|
||||
}
|
||||
|
||||
public void getNoDrops(final World w, final BlockPos pos, final List<ItemStack> drops) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* null means nothing to store...
|
||||
*
|
||||
* @param from source of settings
|
||||
*
|
||||
* @return compound of source
|
||||
*/
|
||||
public CompoundTag downloadSettings(final SettingsFrom from) {
|
||||
final CompoundTag output = new CompoundTag();
|
||||
|
||||
if (this.hasCustomInventoryName()) {
|
||||
final CompoundTag dsp = new CompoundTag();
|
||||
dsp.putString("Name", this.customName);
|
||||
output.put("display", dsp);
|
||||
}
|
||||
|
||||
if (this instanceof IConfigurableObject) {
|
||||
final IConfigManager cm = ((IConfigurableObject) this).getConfigManager();
|
||||
if (cm != null) {
|
||||
cm.writeToNBT(output);
|
||||
}
|
||||
}
|
||||
|
||||
if (this instanceof IPriorityHost) {
|
||||
final IPriorityHost pHost = (IPriorityHost) this;
|
||||
output.putInt("priority", pHost.getPriority());
|
||||
}
|
||||
|
||||
if (this instanceof ISegmentedInventory) {
|
||||
final FixedItemInv inv = ((ISegmentedInventory) this).getInventoryByName("config");
|
||||
if (inv instanceof AppEngInternalAEInventory) {
|
||||
((AppEngInternalAEInventory) inv).writeToNBT(output, "config");
|
||||
}
|
||||
}
|
||||
|
||||
return output.isEmpty() ? null : output;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Text getCustomInventoryName() {
|
||||
return new LiteralText(
|
||||
this.hasCustomInventoryName() ? this.customName : this.getClass().getSimpleName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasCustomInventoryName() {
|
||||
return this.customName != null && !this.customName.isEmpty();
|
||||
}
|
||||
|
||||
public void securityBreak() {
|
||||
this.world.breakBlock(this.pos, true);
|
||||
this.disableDrops();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this block entity is remote (we are running on the logical client
|
||||
* side).
|
||||
*/
|
||||
public boolean isClient() {
|
||||
World world = getWorld();
|
||||
return world == null || world.isClient();
|
||||
}
|
||||
|
||||
public void disableDrops() {
|
||||
DROP_NO_ITEMS.set(new WeakReference<>(this));
|
||||
}
|
||||
|
||||
public void saveChanges() {
|
||||
if (this.world != null) {
|
||||
this.world.markDirty(this.pos, this);
|
||||
if (!this.markDirtyQueued) {
|
||||
// FIXME FABRIC TickHandler.INSTANCE.addCallable(null, this::markDirtyAtEndOfTick);
|
||||
this.markDirtyQueued = true;
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Object markDirtyAtEndOfTick(final World w) {
|
||||
this.markDirty();
|
||||
this.markDirtyQueued = false;
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setName(final String name) {
|
||||
this.customName = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getRenderAttachmentData() {
|
||||
return new AEModelData(up, forward);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAllAttributes(World world, BlockPos pos, BlockState state, AttributeList<?> to) {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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.tile;
|
||||
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import alexiil.mc.lib.attributes.AttributeList;
|
||||
import alexiil.mc.lib.attributes.item.FixedItemInv;
|
||||
import alexiil.mc.lib.attributes.item.impl.EmptyFixedItemInv;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
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.util.shape.VoxelShape;
|
||||
import net.minecraft.util.shape.VoxelShapes;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import appeng.util.helpers.ItemHandlerUtil;
|
||||
import appeng.util.inv.IAEAppEngInventory;
|
||||
import appeng.util.inv.InvOperation;
|
||||
|
||||
public abstract class AEBaseInvBlockEntity extends AEBaseBlockEntity implements IAEAppEngInventory {
|
||||
|
||||
public AEBaseInvBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromTag(BlockState state, final CompoundTag data) {
|
||||
super.fromTag(state, data);
|
||||
final FixedItemInv inv = this.getInternalInventory();
|
||||
if (inv != EmptyFixedItemInv.INSTANCE) {
|
||||
final CompoundTag opt = data.getCompound("inv");
|
||||
for (int x = 0; x < inv.getSlotCount(); x++) {
|
||||
final CompoundTag item = opt.getCompound("item" + x);
|
||||
ItemHandlerUtil.setStackInSlot(inv, x, ItemStack.fromTag(item));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract @Nonnull
|
||||
FixedItemInv getInternalInventory();
|
||||
|
||||
@Override
|
||||
public CompoundTag toTag(final CompoundTag data) {
|
||||
super.toTag(data);
|
||||
final FixedItemInv inv = this.getInternalInventory();
|
||||
if (inv != EmptyFixedItemInv.INSTANCE) {
|
||||
final CompoundTag opt = new CompoundTag();
|
||||
for (int x = 0; x < inv.getSlotCount(); x++) {
|
||||
final CompoundTag item = new CompoundTag();
|
||||
final ItemStack is = inv.getInvStack(x);
|
||||
if (!is.isEmpty()) {
|
||||
is.toTag(item);
|
||||
}
|
||||
opt.put("item" + x, item);
|
||||
}
|
||||
data.put("inv", opt);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getDrops(final World w, final BlockPos pos, final List<ItemStack> drops) {
|
||||
final FixedItemInv inv = this.getInternalInventory();
|
||||
|
||||
for (int l = 0; l < inv.getSlotCount(); l++) {
|
||||
final ItemStack is = inv.getInvStack(l);
|
||||
if (!is.isEmpty()) {
|
||||
drops.add(is);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract void onChangeInventory(FixedItemInv inv, int slot, InvOperation mc, ItemStack removed,
|
||||
ItemStack added);
|
||||
|
||||
protected @Nonnull
|
||||
FixedItemInv getItemHandlerForSide(@Nonnull Direction side) {
|
||||
return this.getInternalInventory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAllAttributes(World world, BlockPos pos, BlockState state, AttributeList<?> to) {
|
||||
super.addAllAttributes(world, pos, state, to);
|
||||
offerItemInventory(to);
|
||||
}
|
||||
|
||||
private void offerItemInventory(AttributeList<?> to) {
|
||||
FixedItemInv internalHandler = getInternalInventory();
|
||||
|
||||
// Offer up the directional ones first
|
||||
for (Direction side : Direction.values()) {
|
||||
FixedItemInv inv = getItemHandlerForSide(side);
|
||||
if (inv != internalHandler) {
|
||||
to.offer(inv, FACE_SHAPES.get(side));
|
||||
}
|
||||
}
|
||||
|
||||
to.offer(internalHandler);
|
||||
}
|
||||
|
||||
private static final EnumMap<Direction, VoxelShape> FACE_SHAPES = new EnumMap<>(Direction.class);
|
||||
static {
|
||||
FACE_SHAPES.put(Direction.UP, VoxelShapes.cuboid(0f, 15f, 0f, 16f, 16f, 16f));
|
||||
FACE_SHAPES.put(Direction.DOWN, VoxelShapes.cuboid(0f, 0f, 0f, 16f, 1f, 16f));
|
||||
FACE_SHAPES.put(Direction.NORTH, VoxelShapes.cuboid(0f, 0f, 0f, 16f, 16f, 1f));
|
||||
FACE_SHAPES.put(Direction.SOUTH, VoxelShapes.cuboid(0f, 0f, 15f, 16f, 16f, 16f));
|
||||
FACE_SHAPES.put(Direction.WEST, VoxelShapes.cuboid(0f, 0f, 0f, 1f, 16f, 16f));
|
||||
FACE_SHAPES.put(Direction.EAST, VoxelShapes.cuboid(15f, 0f, 0f, 16f, 16f, 16f));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
package appeng.tile.crafting;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
/**
|
||||
* Stores client-side only state about the ongoing animation for a molecular
|
||||
* assembler.
|
||||
*/
|
||||
public class AssemblerAnimationStatus {
|
||||
|
||||
private final ItemStack is;
|
||||
|
||||
private final byte speed;
|
||||
|
||||
private final int ticksRequired;
|
||||
|
||||
private float accumulatedTicks;
|
||||
|
||||
private float ticksUntilParticles;
|
||||
|
||||
public AssemblerAnimationStatus(byte speed, ItemStack is) {
|
||||
this.speed = speed;
|
||||
this.is = is;
|
||||
this.ticksRequired = (int) Math.ceil(Math.max(1, 100.0f / speed)) + 2;
|
||||
}
|
||||
|
||||
public ItemStack getIs() {
|
||||
return is;
|
||||
}
|
||||
|
||||
public byte getSpeed() {
|
||||
return speed;
|
||||
}
|
||||
|
||||
public float getAccumulatedTicks() {
|
||||
return accumulatedTicks;
|
||||
}
|
||||
|
||||
public void setAccumulatedTicks(float accumulatedTicks) {
|
||||
this.accumulatedTicks = accumulatedTicks;
|
||||
}
|
||||
|
||||
public float getTicksUntilParticles() {
|
||||
return ticksUntilParticles;
|
||||
}
|
||||
|
||||
public void setTicksUntilParticles(float ticksUntilParticles) {
|
||||
this.ticksUntilParticles = ticksUntilParticles;
|
||||
}
|
||||
|
||||
public boolean isExpired() {
|
||||
return accumulatedTicks > ticksRequired;
|
||||
}
|
||||
}
|
||||
@@ -1,368 +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.tile.crafting;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockView;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.config.Actionable;
|
||||
import appeng.api.implementations.IPowerChannelState;
|
||||
import appeng.api.networking.GridFlags;
|
||||
import appeng.api.networking.IGridHost;
|
||||
import appeng.api.networking.events.MENetworkChannelsChanged;
|
||||
import appeng.api.networking.events.MENetworkEventSubscribe;
|
||||
import appeng.api.networking.events.MENetworkPowerStatusChange;
|
||||
import appeng.api.storage.IMEInventory;
|
||||
import appeng.api.storage.channels.IItemStorageChannel;
|
||||
import appeng.api.storage.data.IAEItemStack;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
import appeng.api.util.WorldCoord;
|
||||
import appeng.block.crafting.AbstractCraftingUnitBlock;
|
||||
import appeng.block.crafting.AbstractCraftingUnitBlock.CraftingUnitType;
|
||||
import appeng.me.cluster.IAECluster;
|
||||
import appeng.me.cluster.IAEMultiBlock;
|
||||
import appeng.me.cluster.implementations.CraftingCPUCalculator;
|
||||
import appeng.me.cluster.implementations.CraftingCPUCluster;
|
||||
import appeng.me.helpers.AENetworkProxy;
|
||||
import appeng.me.helpers.AENetworkProxyMultiblock;
|
||||
import appeng.tile.grid.AENetworkBlockEntity;
|
||||
import appeng.util.Platform;
|
||||
|
||||
public class CraftingBlockEntity extends AENetworkBlockEntity implements IAEMultiBlock, IPowerChannelState {
|
||||
|
||||
private final CraftingCPUCalculator calc = new CraftingCPUCalculator(this);
|
||||
private CompoundTag previousState = null;
|
||||
private boolean isCoreBlock = false;
|
||||
private CraftingCPUCluster cluster;
|
||||
|
||||
public CraftingBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
this.getProxy().setFlags(GridFlags.MULTIBLOCK, GridFlags.REQUIRE_CHANNEL);
|
||||
this.getProxy().setValidSides(EnumSet.noneOf(Direction.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AENetworkProxy createProxy() {
|
||||
return new AENetworkProxyMultiblock(this, "proxy", this.getItemFromTile(this), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ItemStack getItemFromTile(final Object obj) {
|
||||
Optional<ItemStack> is;
|
||||
|
||||
if (((CraftingBlockEntity) obj).isAccelerator()) {
|
||||
is = AEApi.instance().definitions().blocks().craftingAccelerator().maybeStack(1);
|
||||
} else {
|
||||
is = AEApi.instance().definitions().blocks().craftingUnit().maybeStack(1);
|
||||
}
|
||||
|
||||
return is.orElseGet(() -> super.getItemFromTile(obj));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeRotated() {
|
||||
return true;// return BlockCraftingUnit.checkType( world.getBlockMetadata( xCoord, yCoord,
|
||||
// zCoord ),
|
||||
// BlockCraftingUnit.BASE_MONITOR );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(final String name) {
|
||||
super.setName(name);
|
||||
if (this.cluster != null) {
|
||||
this.cluster.updateName();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isAccelerator() {
|
||||
if (this.world == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final AbstractCraftingUnitBlock unit = (AbstractCraftingUnitBlock) this.world.getBlockState(this.pos)
|
||||
.getBlock();
|
||||
return unit.type == CraftingUnitType.ACCELERATOR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReady() {
|
||||
super.onReady();
|
||||
this.getProxy().setVisualRepresentation(this.getItemFromTile(this));
|
||||
this.updateMultiBlock();
|
||||
}
|
||||
|
||||
public void updateMultiBlock() {
|
||||
this.calc.calculateMultiblock(this.world, this.getLocation());
|
||||
}
|
||||
|
||||
public void updateStatus(final CraftingCPUCluster c) {
|
||||
if (this.cluster != null && this.cluster != c) {
|
||||
this.cluster.breakCluster();
|
||||
}
|
||||
|
||||
this.cluster = c;
|
||||
this.updateMeta(true);
|
||||
}
|
||||
|
||||
public void updateMeta(final boolean updateFormed) {
|
||||
if (this.world == null || this.notLoaded() || this.isRemoved()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final boolean formed = this.isFormed();
|
||||
boolean power = false;
|
||||
|
||||
if (this.getProxy().isReady()) {
|
||||
power = this.getProxy().isActive();
|
||||
}
|
||||
|
||||
final BlockState current = this.world.getBlockState(this.pos);
|
||||
|
||||
// The tile might try to update while being destroyed
|
||||
if (current.getBlock() instanceof AbstractCraftingUnitBlock) {
|
||||
final BlockState newState = current.with(AbstractCraftingUnitBlock.POWERED, power)
|
||||
.with(AbstractCraftingUnitBlock.FORMED, formed);
|
||||
|
||||
if (current != newState) {
|
||||
// Not using flag 2 here (only send to clients, prevent block update) will cause
|
||||
// infinite loops
|
||||
// In case there is an inconsistency in the crafting clusters.
|
||||
this.world.setBlockState(this.pos, newState, Constants.BlockFlags.BLOCK_UPDATE);
|
||||
}
|
||||
}
|
||||
|
||||
if (updateFormed) {
|
||||
if (formed) {
|
||||
this.getProxy().setValidSides(EnumSet.allOf(Direction.class));
|
||||
} else {
|
||||
this.getProxy().setValidSides(EnumSet.noneOf(Direction.class));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isFormed() {
|
||||
if (isClient()) {
|
||||
return this.world.getBlockState(this.pos).get(AbstractCraftingUnitBlock.FORMED);
|
||||
}
|
||||
return this.cluster != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag toTag(final CompoundTag data) {
|
||||
super.toTag(data);
|
||||
data.putBoolean("core", this.isCoreBlock());
|
||||
if (this.isCoreBlock() && this.cluster != null) {
|
||||
this.cluster.writeToNBT(data);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromTag(BlockState state, final CompoundTag data) {
|
||||
super.fromTag(state, data);
|
||||
this.setCoreBlock(data.getBoolean("core"));
|
||||
if (this.isCoreBlock()) {
|
||||
if (this.cluster != null) {
|
||||
this.cluster.readFromNBT(data);
|
||||
} else {
|
||||
this.setPreviousState(data.copy());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect(final boolean update) {
|
||||
if (this.cluster != null) {
|
||||
this.cluster.destroy();
|
||||
if (update) {
|
||||
this.updateMeta(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAECluster getCluster() {
|
||||
return this.cluster;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void onPowerStateChange(final MENetworkChannelsChanged ev) {
|
||||
this.updateMeta(false);
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void onPowerStateChange(final MENetworkPowerStatusChange ev) {
|
||||
this.updateMeta(false);
|
||||
}
|
||||
|
||||
public boolean isStatus() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isStorage() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getStorageBytes() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void breakCluster() {
|
||||
if (this.cluster != null) {
|
||||
this.cluster.cancel();
|
||||
final IMEInventory<IAEItemStack> inv = this.cluster.getInventory();
|
||||
|
||||
final LinkedList<WorldCoord> places = new LinkedList<>();
|
||||
|
||||
final Iterator<IGridHost> i = this.cluster.getTiles();
|
||||
while (i.hasNext()) {
|
||||
final IGridHost h = i.next();
|
||||
if (h == this) {
|
||||
places.add(new WorldCoord(this));
|
||||
} else {
|
||||
final BlockEntity te = (BlockEntity) h;
|
||||
|
||||
for (final AEPartLocation d : AEPartLocation.SIDE_LOCATIONS) {
|
||||
final WorldCoord wc = new WorldCoord(te);
|
||||
wc.add(d, 1);
|
||||
if (this.world.isAir(wc.getPos())) {
|
||||
places.add(wc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Collections.shuffle(places);
|
||||
|
||||
if (places.isEmpty()) {
|
||||
throw new IllegalStateException(
|
||||
this.cluster + " does not contain any kind of blocks, which were destroyed.");
|
||||
}
|
||||
|
||||
for (IAEItemStack ais : inv.getAvailableItems(
|
||||
AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class).createList())) {
|
||||
ais = ais.copy();
|
||||
ais.setStackSize(ais.getDefinition().getMaxCount());
|
||||
while (true) {
|
||||
final IAEItemStack g = inv.extractItems(ais.copy(), Actionable.MODULATE,
|
||||
this.cluster.getActionSource());
|
||||
if (g == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
final WorldCoord wc = places.poll();
|
||||
places.add(wc);
|
||||
|
||||
Platform.spawnDrops(this.world, wc.getPos(), Collections.singletonList(g.createItemStack()));
|
||||
}
|
||||
}
|
||||
|
||||
this.cluster.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPowered() {
|
||||
if (isClient()) {
|
||||
return this.world.getBlockState(this.pos).get(AbstractCraftingUnitBlock.POWERED);
|
||||
}
|
||||
return this.getProxy().isActive();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
if (Platform.isServer()) {
|
||||
return this.getProxy().isActive();
|
||||
}
|
||||
return this.isPowered() && this.isFormed();
|
||||
}
|
||||
|
||||
public boolean isCoreBlock() {
|
||||
return this.isCoreBlock;
|
||||
}
|
||||
|
||||
public void setCoreBlock(final boolean isCoreBlock) {
|
||||
this.isCoreBlock = isCoreBlock;
|
||||
}
|
||||
|
||||
public CompoundTag getPreviousState() {
|
||||
return this.previousState;
|
||||
}
|
||||
|
||||
public void setPreviousState(final CompoundTag previousState) {
|
||||
this.previousState = previousState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getRenderAttachmentData() {
|
||||
return new CraftingCubeModelData(getUp(), getForward(), getConnections());
|
||||
}
|
||||
|
||||
protected EnumSet<Direction> getConnections() {
|
||||
if (world == null) {
|
||||
return EnumSet.noneOf(Direction.class);
|
||||
}
|
||||
|
||||
EnumSet<Direction> connections = EnumSet.noneOf(Direction.class);
|
||||
|
||||
for (Direction facing : Direction.values()) {
|
||||
if (this.isConnected(world, pos, facing)) {
|
||||
connections.add(facing);
|
||||
}
|
||||
}
|
||||
|
||||
return connections;
|
||||
}
|
||||
|
||||
private boolean isConnected(BlockView world, BlockPos pos, Direction side) {
|
||||
BlockPos adjacentPos = pos.offset(side);
|
||||
return world.getBlockState(adjacentPos).getBlock() instanceof AbstractCraftingUnitBlock;
|
||||
}
|
||||
|
||||
/**
|
||||
* When the block state changes (i.e. becoming formed or unformed), we need to
|
||||
* update the model data since it contains connections to neighboring tiles.
|
||||
*/
|
||||
@Override
|
||||
public void updateContainingBlockInfo() {
|
||||
super.updateContainingBlockInfo();
|
||||
requestModelDataUpdate();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
package appeng.tile.crafting;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.Objects;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
import net.minecraft.util.math.Direction;
|
||||
|
||||
import appeng.client.render.model.AEModelData;
|
||||
|
||||
public class CraftingCubeModelData extends AEModelData {
|
||||
|
||||
// Contains information on which sides of the block are connected to other parts
|
||||
// of a formed crafting cube
|
||||
private final EnumSet<Direction> connections;
|
||||
|
||||
public CraftingCubeModelData(Direction up, Direction forward, EnumSet<Direction> connections) {
|
||||
super(up, forward);
|
||||
this.connections = Preconditions.checkNotNull(connections);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCacheable() {
|
||||
return false; // Too many variants
|
||||
}
|
||||
|
||||
public EnumSet<Direction> getConnections() {
|
||||
return connections;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
if (!super.equals(o)) {
|
||||
return false;
|
||||
}
|
||||
CraftingCubeModelData that = (CraftingCubeModelData) o;
|
||||
return connections.equals(that.connections);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), connections);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,176 +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.tile.crafting;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
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.fabricmc.api.EnvType;
|
||||
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.implementations.tiles.IColorableTile;
|
||||
import appeng.api.storage.data.IAEItemStack;
|
||||
import appeng.api.util.AEColor;
|
||||
import appeng.util.item.AEItemStack;
|
||||
|
||||
public class CraftingMonitorBlockEntity extends CraftingBlockEntity implements IColorableTile {
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
private Integer dspList;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
private boolean updateList;
|
||||
|
||||
private IAEItemStack dspPlay;
|
||||
private AEColor paintedColor = AEColor.TRANSPARENT;
|
||||
|
||||
public CraftingMonitorBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean readFromStream(final PacketByteBuf data) throws IOException {
|
||||
final boolean c = super.readFromStream(data);
|
||||
final AEColor oldPaintedColor = this.paintedColor;
|
||||
this.paintedColor = AEColor.values()[data.readByte()];
|
||||
|
||||
final boolean hasItem = data.readBoolean();
|
||||
|
||||
if (hasItem) {
|
||||
this.dspPlay = AEItemStack.fromPacket(data);
|
||||
} else {
|
||||
this.dspPlay = null;
|
||||
}
|
||||
|
||||
this.setUpdateList(true);
|
||||
return oldPaintedColor != this.paintedColor || c; // tesr!
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeToStream(final PacketByteBuf data) throws IOException {
|
||||
super.writeToStream(data);
|
||||
data.writeByte(this.paintedColor.ordinal());
|
||||
|
||||
if (this.dspPlay == null) {
|
||||
data.writeBoolean(false);
|
||||
} else {
|
||||
data.writeBoolean(true);
|
||||
this.dspPlay.writeToPacket(data);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromTag(BlockState state, final CompoundTag data) {
|
||||
super.fromTag(state, data);
|
||||
if (data.contains("paintedColor")) {
|
||||
this.paintedColor = AEColor.values()[data.getByte("paintedColor")];
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag toTag(final CompoundTag data) {
|
||||
super.toTag(data);
|
||||
data.putByte("paintedColor", (byte) this.paintedColor.ordinal());
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccelerator() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStatus() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setJob(final IAEItemStack is) {
|
||||
if ((is == null) != (this.dspPlay == null)) {
|
||||
this.dspPlay = is == null ? null : is.copy();
|
||||
this.markForUpdate();
|
||||
} else if (is != null && this.dspPlay != null) {
|
||||
if (is.getStackSize() != this.dspPlay.getStackSize()) {
|
||||
this.dspPlay = is.copy();
|
||||
this.markForUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IAEItemStack getJobProgress() {
|
||||
return this.dspPlay; // AEItemStack.create( new ItemStack( Items.DIAMOND, 64 ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public AEColor getColor() {
|
||||
return this.paintedColor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean recolourBlock(final Direction side, final AEColor newPaintedColor, final PlayerEntity who) {
|
||||
if (this.paintedColor == newPaintedColor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.paintedColor = newPaintedColor;
|
||||
this.saveChanges();
|
||||
this.markForUpdate();
|
||||
return true;
|
||||
}
|
||||
|
||||
public Integer getDisplayList() {
|
||||
return this.dspList;
|
||||
}
|
||||
|
||||
public void setDisplayList(final Integer dspList) {
|
||||
this.dspList = dspList;
|
||||
}
|
||||
|
||||
public boolean isUpdateList() {
|
||||
return this.updateList;
|
||||
}
|
||||
|
||||
public void setUpdateList(final boolean updateList) {
|
||||
this.updateList = updateList;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ItemStack getItemFromTile(final Object obj) {
|
||||
final Optional<ItemStack> is = AEApi.instance().definitions().blocks().craftingMonitor().maybeStack(1);
|
||||
|
||||
return is.orElseGet(() -> super.getItemFromTile(obj));
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CraftingMonitorModelData getRenderAttachmentData() {
|
||||
return new CraftingMonitorModelData(getUp(), getForward(), getConnections(), getColor());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
package appeng.tile.crafting;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.Objects;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
import net.minecraft.util.math.Direction;
|
||||
|
||||
import appeng.api.util.AEColor;
|
||||
|
||||
public class CraftingMonitorModelData extends CraftingCubeModelData {
|
||||
|
||||
private final AEColor color;
|
||||
|
||||
public CraftingMonitorModelData(Direction up, Direction forward, EnumSet<Direction> connections, AEColor color) {
|
||||
super(up, forward, connections);
|
||||
this.color = Preconditions.checkNotNull(color);
|
||||
}
|
||||
|
||||
public AEColor getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
if (!super.equals(o)) {
|
||||
return false;
|
||||
}
|
||||
CraftingMonitorModelData that = (CraftingMonitorModelData) o;
|
||||
return color == that.color;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), color);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,95 +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.tile.crafting;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.definitions.IBlocks;
|
||||
import appeng.block.crafting.AbstractCraftingUnitBlock;
|
||||
|
||||
public class CraftingStorageBlockEntity extends CraftingBlockEntity {
|
||||
private static final int KILO_SCALAR = 1024;
|
||||
|
||||
public CraftingStorageBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ItemStack getItemFromTile(final Object obj) {
|
||||
final IBlocks blocks = AEApi.instance().definitions().blocks();
|
||||
final int storage = ((CraftingBlockEntity) obj).getStorageBytes() / KILO_SCALAR;
|
||||
|
||||
Optional<ItemStack> is;
|
||||
|
||||
switch (storage) {
|
||||
case 1:
|
||||
is = blocks.craftingStorage1k().maybeStack(1);
|
||||
break;
|
||||
case 4:
|
||||
is = blocks.craftingStorage4k().maybeStack(1);
|
||||
break;
|
||||
case 16:
|
||||
is = blocks.craftingStorage16k().maybeStack(1);
|
||||
break;
|
||||
case 64:
|
||||
is = blocks.craftingStorage64k().maybeStack(1);
|
||||
break;
|
||||
default:
|
||||
is = Optional.empty();
|
||||
break;
|
||||
}
|
||||
|
||||
return is.orElseGet(() -> super.getItemFromTile(obj));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccelerator() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStorage() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStorageBytes() {
|
||||
if (this.world == null || this.notLoaded() || this.isRemoved()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
final AbstractCraftingUnitBlock unit = (AbstractCraftingUnitBlock) this.world.getBlockState(this.pos)
|
||||
.getBlock();
|
||||
switch (unit.type) {
|
||||
default:
|
||||
case STORAGE_1K:
|
||||
return 1024;
|
||||
case STORAGE_4K:
|
||||
return 4 * 1024;
|
||||
case STORAGE_16K:
|
||||
return 16 * 1024;
|
||||
case STORAGE_64K:
|
||||
return 64 * 1024;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,579 +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.tile.crafting;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import appeng.util.*;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.inventory.CraftingInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.minecraftforge.fml.hooks.BasicEventHooks;
|
||||
import alexiil.mc.lib.attributes.item.FixedItemInv;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.config.Actionable;
|
||||
import appeng.api.config.PowerMultiplier;
|
||||
import appeng.api.config.RedstoneMode;
|
||||
import appeng.api.config.Settings;
|
||||
import appeng.api.config.Upgrades;
|
||||
import appeng.api.definitions.ITileDefinition;
|
||||
import appeng.api.implementations.IPowerChannelState;
|
||||
import appeng.api.implementations.IUpgradeableHost;
|
||||
import appeng.api.implementations.tiles.ICraftingMachine;
|
||||
import appeng.api.networking.IGridNode;
|
||||
import appeng.api.networking.crafting.ICraftingPatternDetails;
|
||||
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.storage.data.IAEItemStack;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
import appeng.api.util.DimensionalCoord;
|
||||
import appeng.api.util.IConfigManager;
|
||||
import appeng.container.ContainerNull;
|
||||
import appeng.core.sync.network.NetworkHandler;
|
||||
import appeng.core.sync.network.TargetPoint;
|
||||
import appeng.core.sync.packets.AssemblerAnimationPacket;
|
||||
import appeng.items.misc.EncodedPatternItem;
|
||||
import appeng.me.GridAccessException;
|
||||
import appeng.parts.automation.DefinitionUpgradeInventory;
|
||||
import appeng.parts.automation.UpgradeInventory;
|
||||
import appeng.tile.grid.AENetworkInvBlockEntity;
|
||||
import appeng.tile.inventory.AppEngInternalInventory;
|
||||
import appeng.util.helpers.ItemHandlerUtil;
|
||||
import appeng.util.inv.InvOperation;
|
||||
import appeng.util.inv.WrapperChainedItemHandler;
|
||||
import appeng.util.inv.WrapperFilteredItemHandler;
|
||||
import appeng.util.inv.filter.IAEItemFilter;
|
||||
import appeng.util.item.AEItemStack;
|
||||
|
||||
public class MolecularAssemblerBlockEntity extends AENetworkInvBlockEntity
|
||||
implements IUpgradeableHost, IConfigManagerHost, IGridTickable, ICraftingMachine, IPowerChannelState {
|
||||
|
||||
public static final String INVENTORY_MAIN = "molecular_assembler";
|
||||
|
||||
private final CraftingInventory craftingInv;
|
||||
private final AppEngInternalInventory gridInv = new AppEngInternalInventory(this, 9 + 1, 1);
|
||||
private final AppEngInternalInventory patternInv = new AppEngInternalInventory(this, 1, 1);
|
||||
private final FixedItemInv gridInvExt = new WrapperFilteredItemHandler(this.gridInv, new CraftingGridFilter());
|
||||
private final FixedItemInv internalInv = new WrapperChainedItemHandler(this.gridInv, this.patternInv);
|
||||
private final IConfigManager settings;
|
||||
private final UpgradeInventory upgrades;
|
||||
private boolean isPowered = false;
|
||||
private AEPartLocation pushDirection = AEPartLocation.INTERNAL;
|
||||
private ItemStack myPattern = ItemStack.EMPTY;
|
||||
private ICraftingPatternDetails myPlan = null;
|
||||
private double progress = 0;
|
||||
private boolean isAwake = false;
|
||||
private boolean forcePlan = false;
|
||||
private boolean reboot = true;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
private AssemblerAnimationStatus animationStatus;
|
||||
|
||||
public MolecularAssemblerBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
final ITileDefinition assembler = AEApi.instance().definitions().blocks().molecularAssembler();
|
||||
|
||||
this.settings = new ConfigManager(this);
|
||||
this.settings.registerSetting(Settings.REDSTONE_CONTROLLED, RedstoneMode.IGNORE);
|
||||
this.getProxy().setIdlePowerUsage(0.0);
|
||||
this.upgrades = new DefinitionUpgradeInventory(assembler, this, this.getUpgradeSlots());
|
||||
this.craftingInv = new CraftingInventory(new ContainerNull(), 3, 3);
|
||||
|
||||
}
|
||||
|
||||
private int getUpgradeSlots() {
|
||||
return 5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean pushPattern(final ICraftingPatternDetails patternDetails, final CraftingInventory table,
|
||||
final Direction where) {
|
||||
if (this.myPattern.isEmpty()) {
|
||||
boolean isEmpty = ItemHandlerUtil.isEmpty(this.gridInv) && ItemHandlerUtil.isEmpty(this.patternInv);
|
||||
|
||||
if (isEmpty && patternDetails.isCraftable()) {
|
||||
this.forcePlan = true;
|
||||
this.myPlan = patternDetails;
|
||||
this.pushDirection = AEPartLocation.fromFacing(where);
|
||||
|
||||
for (int x = 0; x < table.size(); x++) {
|
||||
this.gridInv.setInvStack(x, table.getStack(x));
|
||||
}
|
||||
|
||||
this.updateSleepiness();
|
||||
this.saveChanges();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void updateSleepiness() {
|
||||
final boolean wasEnabled = this.isAwake;
|
||||
this.isAwake = this.myPlan != null && this.hasMats() || this.canPush();
|
||||
if (wasEnabled != this.isAwake) {
|
||||
try {
|
||||
if (this.isAwake) {
|
||||
this.getProxy().getTick().wakeDevice(this.getProxy().getNode());
|
||||
} else {
|
||||
this.getProxy().getTick().sleepDevice(this.getProxy().getNode());
|
||||
}
|
||||
} catch (final GridAccessException e) {
|
||||
// :P
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean canPush() {
|
||||
return !this.gridInv.getInvStack(9).isEmpty();
|
||||
}
|
||||
|
||||
private boolean hasMats() {
|
||||
if (this.myPlan == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int x = 0; x < this.craftingInv.size(); x++) {
|
||||
this.craftingInv.setStack(x, this.gridInv.getInvStack(x));
|
||||
}
|
||||
|
||||
return !this.myPlan.getOutput(this.craftingInv, this.getWorld()).isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptsPlans() {
|
||||
return ItemHandlerUtil.isEmpty(this.patternInv);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInstalledUpgrades(final Upgrades u) {
|
||||
return this.upgrades.getInstalledUpgrades(u);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean readFromStream(final PacketByteBuf data) throws IOException {
|
||||
final boolean c = super.readFromStream(data);
|
||||
final boolean oldPower = this.isPowered;
|
||||
this.isPowered = data.readBoolean();
|
||||
return this.isPowered != oldPower || c;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeToStream(final PacketByteBuf data) throws IOException {
|
||||
super.writeToStream(data);
|
||||
data.writeBoolean(this.isPowered);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag toTag(final CompoundTag data) {
|
||||
super.toTag(data);
|
||||
if (this.forcePlan && this.myPlan != null) {
|
||||
final ItemStack pattern = this.myPlan.getPattern();
|
||||
if (!pattern.isEmpty()) {
|
||||
final CompoundTag compound = new CompoundTag();
|
||||
pattern.toTag(compound);
|
||||
data.put("myPlan", compound);
|
||||
data.putInt("pushDirection", this.pushDirection.ordinal());
|
||||
}
|
||||
}
|
||||
|
||||
this.upgrades.writeToNBT(data, "upgrades");
|
||||
this.settings.writeToNBT(data);
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromTag(BlockState state, final CompoundTag data) {
|
||||
super.fromTag(state, data);
|
||||
if (data.contains("myPlan")) {
|
||||
final ItemStack myPat = ItemStack.fromTag(data.getCompound("myPlan"));
|
||||
|
||||
if (!myPat.isEmpty() && myPat.getItem() instanceof EncodedPatternItem) {
|
||||
final World w = this.getWorld();
|
||||
final EncodedPatternItem iep = (EncodedPatternItem) myPat.getItem();
|
||||
final ICraftingPatternDetails ph = iep.getPatternForItem(myPat, w);
|
||||
if (ph != null && ph.isCraftable()) {
|
||||
this.forcePlan = true;
|
||||
this.myPlan = ph;
|
||||
this.pushDirection = AEPartLocation.fromOrdinal(data.getInt("pushDirection"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.upgrades.readFromNBT(data, "upgrades");
|
||||
this.settings.readFromNBT(data);
|
||||
this.recalculatePlan();
|
||||
}
|
||||
|
||||
private void recalculatePlan() {
|
||||
this.reboot = true;
|
||||
|
||||
if (this.forcePlan) {
|
||||
return;
|
||||
}
|
||||
|
||||
final ItemStack is = this.patternInv.getInvStack(0);
|
||||
|
||||
if (!is.isEmpty() && is.getItem() instanceof EncodedPatternItem) {
|
||||
if (!ItemStack.areItemsEqual(is, this.myPattern)) {
|
||||
final World w = this.getWorld();
|
||||
final EncodedPatternItem iep = (EncodedPatternItem) is.getItem();
|
||||
final ICraftingPatternDetails ph = iep.getPatternForItem(is, w);
|
||||
|
||||
if (ph != null && ph.isCraftable()) {
|
||||
this.progress = 0;
|
||||
this.myPattern = is;
|
||||
this.myPlan = ph;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.progress = 0;
|
||||
this.forcePlan = false;
|
||||
this.myPlan = null;
|
||||
this.myPattern = ItemStack.EMPTY;
|
||||
this.pushDirection = AEPartLocation.INTERNAL;
|
||||
}
|
||||
|
||||
this.updateSleepiness();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AECableType getCableConnectionType(final AEPartLocation dir) {
|
||||
return AECableType.COVERED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DimensionalCoord getLocation() {
|
||||
return new DimensionalCoord(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IConfigManager getConfigManager() {
|
||||
return this.settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FixedItemInv getInventoryByName(final String name) {
|
||||
if (name.equals("upgrades")) {
|
||||
return this.upgrades;
|
||||
}
|
||||
|
||||
if (name.equals("molecular_assembler")) {
|
||||
return this.internalInv;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSetting(final IConfigManager manager, final Settings settingName, final Enum<?> newValue) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public FixedItemInv getInternalInventory() {
|
||||
return this.internalInv;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FixedItemInv getItemHandlerForSide(Direction side) {
|
||||
return this.gridInvExt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeInventory(final FixedItemInv inv, final int slot, final InvOperation mc,
|
||||
final ItemStack removed, final ItemStack added) {
|
||||
if (inv == this.gridInv || inv == this.patternInv) {
|
||||
this.recalculatePlan();
|
||||
}
|
||||
}
|
||||
|
||||
public int getCraftingProgress() {
|
||||
return (int) this.progress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getDrops(final World w, final BlockPos pos, final List<ItemStack> drops) {
|
||||
super.getDrops(w, pos, drops);
|
||||
|
||||
for (int h = 0; h < this.upgrades.getSlotCount(); h++) {
|
||||
final ItemStack is = this.upgrades.getInvStack(h);
|
||||
if (!is.isEmpty()) {
|
||||
drops.add(is);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickingRequest getTickingRequest(final IGridNode node) {
|
||||
this.recalculatePlan();
|
||||
this.updateSleepiness();
|
||||
return new TickingRequest(1, 1, !this.isAwake, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickRateModulation tickingRequest(final IGridNode node, int ticksSinceLastCall) {
|
||||
if (!this.gridInv.getInvStack(9).isEmpty()) {
|
||||
this.pushOut(this.gridInv.getInvStack(9));
|
||||
|
||||
// did it eject?
|
||||
if (this.gridInv.getInvStack(9).isEmpty()) {
|
||||
this.saveChanges();
|
||||
}
|
||||
|
||||
this.ejectHeldItems();
|
||||
this.updateSleepiness();
|
||||
this.progress = 0;
|
||||
return this.isAwake ? TickRateModulation.IDLE : TickRateModulation.SLEEP;
|
||||
}
|
||||
|
||||
if (this.myPlan == null) {
|
||||
this.updateSleepiness();
|
||||
return TickRateModulation.SLEEP;
|
||||
}
|
||||
|
||||
if (this.reboot) {
|
||||
ticksSinceLastCall = 1;
|
||||
}
|
||||
|
||||
if (!this.isAwake) {
|
||||
return TickRateModulation.SLEEP;
|
||||
}
|
||||
|
||||
this.reboot = false;
|
||||
int speed = 10;
|
||||
switch (this.upgrades.getInstalledUpgrades(Upgrades.SPEED)) {
|
||||
case 0:
|
||||
this.progress += this.userPower(ticksSinceLastCall, speed = 10, 1.0);
|
||||
break;
|
||||
case 1:
|
||||
this.progress += this.userPower(ticksSinceLastCall, speed = 13, 1.3);
|
||||
break;
|
||||
case 2:
|
||||
this.progress += this.userPower(ticksSinceLastCall, speed = 17, 1.7);
|
||||
break;
|
||||
case 3:
|
||||
this.progress += this.userPower(ticksSinceLastCall, speed = 20, 2.0);
|
||||
break;
|
||||
case 4:
|
||||
this.progress += this.userPower(ticksSinceLastCall, speed = 25, 2.5);
|
||||
break;
|
||||
case 5:
|
||||
this.progress += this.userPower(ticksSinceLastCall, speed = 50, 5.0);
|
||||
break;
|
||||
}
|
||||
|
||||
if (this.progress >= 100) {
|
||||
for (int x = 0; x < this.craftingInv.size(); x++) {
|
||||
this.craftingInv.setStack(x, this.gridInv.getInvStack(x));
|
||||
}
|
||||
|
||||
this.progress = 0;
|
||||
final ItemStack output = this.myPlan.getOutput(this.craftingInv, this.getWorld());
|
||||
if (!output.isEmpty()) {
|
||||
BasicEventHooks.firePlayerCraftingEvent((PlayerEntity) FakePlayer.getOrCreate((ServerWorld) this.getWorld()), output,
|
||||
this.craftingInv);
|
||||
|
||||
this.pushOut(output.copy());
|
||||
|
||||
for (int x = 0; x < this.craftingInv.size(); x++) {
|
||||
this.gridInv.setInvStack(x, Platform.getRecipeRemainder(this.craftingInv.getStack(x)));
|
||||
}
|
||||
|
||||
if (ItemHandlerUtil.isEmpty(this.patternInv)) {
|
||||
this.forcePlan = false;
|
||||
this.myPlan = null;
|
||||
this.pushDirection = AEPartLocation.INTERNAL;
|
||||
}
|
||||
|
||||
this.ejectHeldItems();
|
||||
|
||||
final IAEItemStack item = AEItemStack.fromItemStack(output);
|
||||
if (item != null) {
|
||||
final TargetPoint where = new TargetPoint(this.pos.getX(), this.pos.getY(), this.pos.getZ(), 32,
|
||||
this.world.getDimension().getType());
|
||||
NetworkHandler.instance()
|
||||
.sendToAllAround(new AssemblerAnimationPacket(this.pos, (byte) speed, item), where);
|
||||
}
|
||||
|
||||
this.saveChanges();
|
||||
this.updateSleepiness();
|
||||
return this.isAwake ? TickRateModulation.IDLE : TickRateModulation.SLEEP;
|
||||
}
|
||||
}
|
||||
|
||||
return TickRateModulation.FASTER;
|
||||
}
|
||||
|
||||
private void ejectHeldItems() {
|
||||
if (this.gridInv.getInvStack(9).isEmpty()) {
|
||||
for (int x = 0; x < 9; x++) {
|
||||
final ItemStack is = this.gridInv.getInvStack(x);
|
||||
if (!is.isEmpty()) {
|
||||
if (this.myPlan == null || !this.myPlan.isValidItemForSlot(x, is, this.world)) {
|
||||
this.gridInv.setInvStack(9, is);
|
||||
this.gridInv.setInvStack(x, ItemStack.EMPTY);
|
||||
this.saveChanges();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int userPower(final int ticksPassed, final int bonusValue, final double acceleratorTax) {
|
||||
try {
|
||||
return (int) (this.getProxy().getEnergy().extractAEPower(ticksPassed * bonusValue * acceleratorTax,
|
||||
Actionable.MODULATE, PowerMultiplier.CONFIG) / acceleratorTax);
|
||||
} catch (final GridAccessException e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void pushOut(ItemStack output) {
|
||||
if (this.pushDirection == AEPartLocation.INTERNAL) {
|
||||
for (final Direction d : Direction.values()) {
|
||||
output = this.pushTo(output, d);
|
||||
}
|
||||
} else {
|
||||
output = this.pushTo(output, this.pushDirection.getFacing());
|
||||
}
|
||||
|
||||
if (output.isEmpty() && this.forcePlan) {
|
||||
this.forcePlan = false;
|
||||
this.recalculatePlan();
|
||||
}
|
||||
|
||||
this.gridInv.setInvStack(9, output);
|
||||
}
|
||||
|
||||
private ItemStack pushTo(ItemStack output, final Direction d) {
|
||||
if (output.isEmpty()) {
|
||||
return output;
|
||||
}
|
||||
|
||||
final BlockEntity te = this.getWorld().getBlockEntity(this.pos.offset(d));
|
||||
|
||||
if (te == null) {
|
||||
return output;
|
||||
}
|
||||
|
||||
final InventoryAdaptor adaptor = InventoryAdaptor.getAdaptor(te, d.getOpposite());
|
||||
|
||||
if (adaptor == null) {
|
||||
return output;
|
||||
}
|
||||
|
||||
final int size = output.getCount();
|
||||
output = adaptor.addItems(output);
|
||||
final int newSize = output.isEmpty() ? 0 : output.getCount();
|
||||
|
||||
if (size != newSize) {
|
||||
this.saveChanges();
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void onPowerEvent(final MENetworkPowerStatusChange p) {
|
||||
this.updatePowerState();
|
||||
}
|
||||
|
||||
private void updatePowerState() {
|
||||
boolean newState = false;
|
||||
|
||||
try {
|
||||
newState = this.getProxy().isActive() && this.getProxy().getEnergy().extractAEPower(1, Actionable.SIMULATE,
|
||||
PowerMultiplier.CONFIG) > 0.0001;
|
||||
} catch (final GridAccessException ignored) {
|
||||
|
||||
}
|
||||
|
||||
if (newState != this.isPowered) {
|
||||
this.isPowered = newState;
|
||||
this.markForUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPowered() {
|
||||
return this.isPowered;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
return this.isPowered;
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public void setAnimationStatus(@Nullable AssemblerAnimationStatus status) {
|
||||
this.animationStatus = status;
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
@Nullable
|
||||
public AssemblerAnimationStatus getAnimationStatus() {
|
||||
return this.animationStatus;
|
||||
}
|
||||
|
||||
private class CraftingGridFilter implements IAEItemFilter {
|
||||
private boolean hasPattern() {
|
||||
return MolecularAssemblerBlockEntity.this.myPlan != null
|
||||
&& !ItemHandlerUtil.isEmpty(MolecularAssemblerBlockEntity.this.patternInv);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowExtract(FixedItemInv inv, int slot, int amount) {
|
||||
return slot == 9;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowInsert(FixedItemInv inv, int slot, ItemStack stack) {
|
||||
if (slot >= 9) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.hasPattern()) {
|
||||
return MolecularAssemblerBlockEntity.this.myPlan.isValidItemForSlot(slot, stack,
|
||||
MolecularAssemblerBlockEntity.this.getWorld());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,163 +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.tile.crafting;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.render.RenderLayer;
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.render.VertexConsumerProvider;
|
||||
import net.minecraft.client.render.VertexFormats;
|
||||
import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher;
|
||||
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
|
||||
import net.minecraft.client.texture.SpriteAtlasTexture;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import net.minecraft.client.renderer.ItemRenderer;
|
||||
import net.minecraft.client.renderer.RenderState;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.model.json.ModelTransformation;
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||
import net.minecraft.item.BlockItem;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraftforge.client.model.data.EmptyModelData;
|
||||
import net.minecraftforge.fml.common.ObfuscationReflectionHelper;
|
||||
|
||||
import appeng.client.render.effects.ParticleTypes;
|
||||
import appeng.core.AppEng;
|
||||
|
||||
/**
|
||||
* Renders the item currently being crafted by the molecular assembler, as well
|
||||
* as the light strip when it's powered.
|
||||
*/
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class MolecularAssemblerRenderer extends BlockEntityRenderer<MolecularAssemblerBlockEntity> {
|
||||
|
||||
public static final Identifier LIGHTS_MODEL = new Identifier(AppEng.MOD_ID,
|
||||
"block/molecular_assembler_lights");
|
||||
|
||||
private static final RenderLayer MC_161917_RENDERTYPE_FIX = createRenderType();
|
||||
|
||||
private final Random particleRandom = new Random();
|
||||
|
||||
public MolecularAssemblerRenderer(BlockEntityRenderDispatcher rendererDispatcherIn) {
|
||||
super(rendererDispatcherIn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(MolecularAssemblerBlockEntity molecularAssembler, float partialTicks, MatrixStack ms,
|
||||
VertexConsumerProvider bufferIn, int combinedLightIn, int combinedOverlayIn) {
|
||||
|
||||
AssemblerAnimationStatus status = molecularAssembler.getAnimationStatus();
|
||||
if (status != null) {
|
||||
if (!MinecraftClient.getInstance().isGamePaused()) {
|
||||
if (status.isExpired()) {
|
||||
molecularAssembler.setAnimationStatus(null);
|
||||
}
|
||||
|
||||
status.setAccumulatedTicks(status.getAccumulatedTicks() + partialTicks);
|
||||
status.setTicksUntilParticles(status.getTicksUntilParticles() - partialTicks);
|
||||
}
|
||||
|
||||
renderStatus(molecularAssembler, ms, bufferIn, combinedLightIn, status);
|
||||
}
|
||||
|
||||
if (molecularAssembler.isPowered()) {
|
||||
renderPowerLight(ms, bufferIn, combinedLightIn, combinedOverlayIn);
|
||||
}
|
||||
}
|
||||
|
||||
private void renderPowerLight(MatrixStack ms, VertexConsumerProvider bufferIn, int combinedLightIn,
|
||||
int combinedOverlayIn) {
|
||||
// Render the translucent light overlay here instead of in the block, because
|
||||
// thanks to the following MC
|
||||
// bug, our particles would otherwise not be visible (because the glass pane
|
||||
// would also render as translucent,
|
||||
// even the fully transparent part)
|
||||
// https://bugs.mojang.com/browse/MC-161917
|
||||
MinecraftClient minecraft = MinecraftClient.getInstance();
|
||||
BakedModel lightsModel = minecraft.getModelManager().getModel(LIGHTS_MODEL);
|
||||
VertexConsumer buffer = bufferIn.getBuffer(MC_161917_RENDERTYPE_FIX);
|
||||
|
||||
minecraft.getBlockRenderManager().getModelRenderer().render(ms.peek(), buffer, null,
|
||||
lightsModel, 1, 1, 1, combinedLightIn, combinedOverlayIn, EmptyModelData.INSTANCE);
|
||||
}
|
||||
|
||||
private void renderStatus(MolecularAssemblerBlockEntity molecularAssembler, MatrixStack ms,
|
||||
VertexConsumerProvider bufferIn, int combinedLightIn, AssemblerAnimationStatus status) {
|
||||
double centerX = molecularAssembler.getPos().getX() + 0.5f;
|
||||
double centerY = molecularAssembler.getPos().getY() + 0.5f;
|
||||
double centerZ = molecularAssembler.getPos().getZ() + 0.5f;
|
||||
|
||||
// Spawn crafting FX that fly towards the block's center
|
||||
MinecraftClient minecraft = MinecraftClient.getInstance();
|
||||
if (status.getTicksUntilParticles() <= 0) {
|
||||
status.setTicksUntilParticles(4);
|
||||
|
||||
if (AppEng.instance().shouldAddParticles(particleRandom)) {
|
||||
for (int x = 0; x < (int) Math.ceil(status.getSpeed() / 5.0); x++) {
|
||||
minecraft.particleManager.addParticle(ParticleTypes.CRAFTING, centerX, centerY, centerZ, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ItemStack is = status.getIs();
|
||||
|
||||
ItemRenderer itemRenderer = minecraft.getItemRenderer();
|
||||
ms.push();
|
||||
ms.translate(0.5, 0.5, 0.5); // Translate to center of block
|
||||
|
||||
if (!(is.getItem().getItem() instanceof BlockItem)) {
|
||||
ms.translate(0, -0.3f, 0);
|
||||
} else {
|
||||
ms.translate(0, -0.2f, 0);
|
||||
}
|
||||
|
||||
itemRenderer.renderItem(is, ModelTransformation.Mode.GROUND, combinedLightIn,
|
||||
OverlayTexture.NO_OVERLAY, ms, bufferIn);
|
||||
ms.pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* See above for when this can be removed. It creates a RenderType that is
|
||||
* equivalent to {@link RenderLayer#getTranslucent()}, but enables alpha testing.
|
||||
* This prevents the fully transparents parts of the rendered block model from
|
||||
* occluding our particles.
|
||||
*/
|
||||
private static RenderLayer createRenderType() {
|
||||
RenderState.TransparencyState TRANSLUCENT_TRANSPARENCY = ObfuscationReflectionHelper
|
||||
.getPrivateValue(RenderState.class, null, "field_228515_g_");
|
||||
RenderState.TextureState mipmapBlockAtlasTexture = new RenderState.TextureState(
|
||||
SpriteAtlasTexture.BLOCK_ATLAS_TEX, false, true);
|
||||
RenderState.LightmapState disableLightmap = new RenderState.LightmapState(false);
|
||||
RenderLayer.State glState = RenderLayer.State.getBuilder().texture(mipmapBlockAtlasTexture)
|
||||
.transparency(TRANSLUCENT_TRANSPARENCY).alpha(new RenderState.AlphaState(0.05F))
|
||||
.lightmap(disableLightmap).build(true);
|
||||
|
||||
return RenderLayer.makeType("ae2_translucent_alphatest", VertexFormats.POSITION_COLOR_TEX_LIGHTMAP,
|
||||
GL11.GL_QUADS, 256, glState);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,112 +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.tile.grid;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
|
||||
import appeng.api.networking.IGridNode;
|
||||
import appeng.api.networking.security.IActionHost;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
import appeng.api.util.DimensionalCoord;
|
||||
import appeng.me.helpers.AENetworkProxy;
|
||||
import appeng.me.helpers.IGridProxyable;
|
||||
import appeng.tile.AEBaseBlockEntity;
|
||||
|
||||
public class AENetworkBlockEntity extends AEBaseBlockEntity implements IActionHost, IGridProxyable {
|
||||
|
||||
private final AENetworkProxy gridProxy = this.createProxy();
|
||||
|
||||
public AENetworkBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromTag(BlockState state, final CompoundTag data) {
|
||||
super.fromTag(state, data);
|
||||
this.getProxy().readFromNBT(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag toTag(final CompoundTag data) {
|
||||
super.toTag(data);
|
||||
this.getProxy().writeToNBT(data);
|
||||
return data;
|
||||
}
|
||||
|
||||
protected AENetworkProxy createProxy() {
|
||||
return new AENetworkProxy(this, "proxy", this.getItemFromTile(this), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IGridNode getGridNode(final AEPartLocation dir) {
|
||||
return this.getProxy().getNode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AECableType getCableConnectionType(final AEPartLocation dir) {
|
||||
return AECableType.SMART;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkUnloaded() {
|
||||
super.onChunkUnloaded();
|
||||
this.getProxy().onChunkUnloaded();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReady() {
|
||||
super.onReady();
|
||||
this.getProxy().onReady();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markRemoved() {
|
||||
super.markRemoved();
|
||||
this.getProxy().remove();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelRemoval() {
|
||||
super.cancelRemoval();
|
||||
this.getProxy().validate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AENetworkProxy getProxy() {
|
||||
return this.gridProxy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DimensionalCoord getLocation() {
|
||||
return new DimensionalCoord(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void gridChanged() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public IGridNode getActionableNode() {
|
||||
return this.getProxy().getNode();
|
||||
}
|
||||
}
|
||||
@@ -1,96 +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.tile.grid;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
|
||||
import appeng.api.networking.IGridNode;
|
||||
import appeng.api.networking.security.IActionHost;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
import appeng.me.helpers.AENetworkProxy;
|
||||
import appeng.me.helpers.IGridProxyable;
|
||||
import appeng.tile.AEBaseInvBlockEntity;
|
||||
|
||||
public abstract class AENetworkInvBlockEntity extends AEBaseInvBlockEntity implements IActionHost, IGridProxyable {
|
||||
|
||||
private final AENetworkProxy gridProxy = new AENetworkProxy(this, "proxy", this.getItemFromTile(this), true);
|
||||
|
||||
public AENetworkInvBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromTag(BlockState state, final CompoundTag data) {
|
||||
super.fromTag(state, data);
|
||||
this.getProxy().readFromNBT(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag toTag(final CompoundTag data) {
|
||||
super.toTag(data);
|
||||
this.getProxy().writeToNBT(data);
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AENetworkProxy getProxy() {
|
||||
return this.gridProxy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void gridChanged() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public IGridNode getGridNode(final AEPartLocation dir) {
|
||||
return this.getProxy().getNode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkUnloaded() {
|
||||
super.onChunkUnloaded();
|
||||
this.getProxy().onChunkUnloaded();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReady() {
|
||||
super.onReady();
|
||||
this.getProxy().onReady();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markRemoved() {
|
||||
super.markRemoved();
|
||||
this.getProxy().remove();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelRemoval() {
|
||||
super.cancelRemoval();
|
||||
this.getProxy().validate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IGridNode getActionableNode() {
|
||||
return this.getProxy().getNode();
|
||||
}
|
||||
}
|
||||
@@ -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.tile.grid;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
|
||||
import appeng.api.networking.IGridNode;
|
||||
import appeng.api.networking.security.IActionHost;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
import appeng.api.util.DimensionalCoord;
|
||||
import appeng.me.helpers.AENetworkProxy;
|
||||
import appeng.me.helpers.IGridProxyable;
|
||||
import appeng.tile.powersink.AEBasePoweredBlockEntity;
|
||||
|
||||
public abstract class AENetworkPowerBlockEntity extends AEBasePoweredBlockEntity implements IActionHost, IGridProxyable {
|
||||
|
||||
private final AENetworkProxy gridProxy = new AENetworkProxy(this, "proxy", this.getItemFromTile(this), true);
|
||||
|
||||
public AENetworkPowerBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromTag(BlockState state, final CompoundTag data) {
|
||||
super.fromTag(state, data);
|
||||
this.getProxy().readFromNBT(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag toTag(final CompoundTag data) {
|
||||
super.toTag(data);
|
||||
this.getProxy().writeToNBT(data);
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AENetworkProxy getProxy() {
|
||||
return this.gridProxy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DimensionalCoord getLocation() {
|
||||
return new DimensionalCoord(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void gridChanged() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public IGridNode getGridNode(final AEPartLocation dir) {
|
||||
return this.getProxy().getNode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AECableType getCableConnectionType(final AEPartLocation dir) {
|
||||
return AECableType.SMART;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelRemoval() {
|
||||
super.cancelRemoval();
|
||||
this.getProxy().validate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markRemoved() {
|
||||
super.markRemoved();
|
||||
this.getProxy().remove();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkUnloaded() {
|
||||
super.onChunkUnloaded();
|
||||
this.getProxy().onChunkUnloaded();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReady() {
|
||||
super.onReady();
|
||||
this.getProxy().onReady();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IGridNode getActionableNode() {
|
||||
return this.getProxy().getNode();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,133 +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.tile.grindstone;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.util.Tickable;
|
||||
import net.minecraft.util.math.Direction;
|
||||
|
||||
import appeng.api.implementations.tiles.ICrankable;
|
||||
import appeng.tile.AEBaseBlockEntity;
|
||||
|
||||
public class CrankBlockEntity extends AEBaseBlockEntity implements Tickable {
|
||||
|
||||
private final int ticksPerRotation = 18;
|
||||
|
||||
// sided values..
|
||||
private float visibleRotation = 0; // This is in degrees
|
||||
private int charge = 0;
|
||||
|
||||
private int hits = 0;
|
||||
private int rotation = 0;
|
||||
|
||||
public CrankBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
if (this.rotation > 0) {
|
||||
this.setVisibleRotation(this.getVisibleRotation() - 360.0f / (this.ticksPerRotation));
|
||||
this.charge++;
|
||||
if (this.charge >= this.ticksPerRotation) {
|
||||
this.charge -= this.ticksPerRotation;
|
||||
final ICrankable g = this.getGrinder();
|
||||
if (g != null) {
|
||||
g.applyTurn();
|
||||
}
|
||||
}
|
||||
|
||||
this.rotation--;
|
||||
}
|
||||
}
|
||||
|
||||
private ICrankable getGrinder() {
|
||||
if (isClient()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final Direction grinder = this.getUp().getOpposite();
|
||||
final BlockEntity te = this.world.getBlockEntity(this.pos.offset(grinder));
|
||||
if (te instanceof ICrankable) {
|
||||
return (ICrankable) te;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean readFromStream(final PacketByteBuf data) throws IOException {
|
||||
final boolean c = super.readFromStream(data);
|
||||
this.rotation = data.readInt();
|
||||
return c;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeToStream(final PacketByteBuf data) throws IOException {
|
||||
super.writeToStream(data);
|
||||
data.writeInt(this.rotation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOrientation(final Direction inForward, final Direction inUp) {
|
||||
super.setOrientation(inForward, inUp);
|
||||
final BlockState state = this.world.getBlockState(this.pos);
|
||||
state.getBlock().neighborUpdate(state, this.world, this.pos, state.getBlock(), this.pos, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* return true if this should count towards stats.
|
||||
*/
|
||||
public boolean power() {
|
||||
if (isClient()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.rotation < 3) {
|
||||
final ICrankable g = this.getGrinder();
|
||||
if (g != null) {
|
||||
if (g.canTurn()) {
|
||||
this.hits = 0;
|
||||
this.rotation += this.ticksPerRotation;
|
||||
this.markForUpdate();
|
||||
return true;
|
||||
} else {
|
||||
this.hits++;
|
||||
if (this.hits > 10) {
|
||||
this.world.breakBlock(this.pos, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public float getVisibleRotation() {
|
||||
return this.visibleRotation;
|
||||
}
|
||||
|
||||
private void setVisibleRotation(final float visibleRotation) {
|
||||
this.visibleRotation = visibleRotation;
|
||||
}
|
||||
}
|
||||
@@ -1,179 +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.tile.grindstone;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import alexiil.mc.lib.attributes.item.FixedItemInv;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraftforge.items.wrapper.RangedWrapper;
|
||||
|
||||
import appeng.api.implementations.tiles.ICrankable;
|
||||
import appeng.recipes.handlers.GrinderOptionalResult;
|
||||
import appeng.recipes.handlers.GrinderRecipe;
|
||||
import appeng.recipes.handlers.GrinderRecipes;
|
||||
import appeng.tile.AEBaseInvBlockEntity;
|
||||
import appeng.tile.inventory.AppEngInternalInventory;
|
||||
import appeng.util.InventoryAdaptor;
|
||||
import appeng.util.Platform;
|
||||
import appeng.util.inv.AdaptorFixedInv;
|
||||
import appeng.util.inv.InvOperation;
|
||||
import appeng.util.inv.WrapperFilteredItemHandler;
|
||||
import appeng.util.inv.filter.IAEItemFilter;
|
||||
|
||||
public class GrinderBlockEntity extends AEBaseInvBlockEntity implements ICrankable {
|
||||
private static final int SLOT_PROCESSING = 6;
|
||||
|
||||
private final AppEngInternalInventory inv = new AppEngInternalInventory(this, 7);
|
||||
private final FixedItemInv invExt = new WrapperFilteredItemHandler(this.inv, new GrinderFilter());
|
||||
private int points;
|
||||
|
||||
public GrinderBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOrientation(final Direction inForward, final Direction inUp) {
|
||||
super.setOrientation(inForward, inUp);
|
||||
final BlockState state = this.world.getBlockState(this.pos);
|
||||
state.getBlock().neighborUpdate(state, this.world, this.pos, state.getBlock(), this.pos, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FixedItemInv getInternalInventory() {
|
||||
return this.inv;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FixedItemInv getItemHandlerForSide(Direction side) {
|
||||
return this.invExt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeInventory(final FixedItemInv inv, final int slot, final InvOperation mc,
|
||||
final ItemStack removed, final ItemStack added) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canTurn() {
|
||||
if (isClient()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.inv.getInvStack(6).isEmpty()) // Add if there isn't one...
|
||||
{
|
||||
for (int x = 0; x < 3; x++) {
|
||||
ItemStack item = this.inv.getInvStack(x);
|
||||
if (item.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
GrinderRecipe r = GrinderRecipes.findForInput(world, item);
|
||||
if (r != null) {
|
||||
final ItemStack ais = item.copy();
|
||||
ais.setCount(r.getIngredientCount());
|
||||
item.decrement(r.getIngredientCount());
|
||||
|
||||
if (item.getCount() <= 0) {
|
||||
item = ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
this.inv.setInvStack(x, item);
|
||||
this.inv.setInvStack(6, ais);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyTurn() {
|
||||
if (isClient()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.points++;
|
||||
|
||||
final ItemStack processing = this.inv.getInvStack(SLOT_PROCESSING);
|
||||
GrinderRecipe r = GrinderRecipes.findForInput(world, processing);
|
||||
if (r != null) {
|
||||
if (r.getTurns() > this.points) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.points = 0;
|
||||
final InventoryAdaptor sia = new AdaptorFixedInv(new RangedWrapper(this.inv, 3, 6));
|
||||
|
||||
this.addItem(sia, r.getOutput());
|
||||
|
||||
for (GrinderOptionalResult optionalResult : r.getOptionalResults()) {
|
||||
final float chance = (Platform.getRandomInt() % 2000) / 2000.0f;
|
||||
|
||||
if (chance <= optionalResult.getChance()) {
|
||||
this.addItem(sia, optionalResult.getResult());
|
||||
}
|
||||
}
|
||||
|
||||
this.inv.setInvStack(6, ItemStack.EMPTY);
|
||||
}
|
||||
}
|
||||
|
||||
private void addItem(final InventoryAdaptor sia, final ItemStack output) {
|
||||
if (output.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final ItemStack notAdded = sia.addItems(output);
|
||||
if (!notAdded.isEmpty()) {
|
||||
final List<ItemStack> out = new ArrayList<>();
|
||||
out.add(notAdded);
|
||||
|
||||
Platform.spawnDrops(this.world, this.pos.offset(this.getForward()), out);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canCrankAttach(final Direction directionToCrank) {
|
||||
return this.getUp() == directionToCrank;
|
||||
}
|
||||
|
||||
private class GrinderFilter implements IAEItemFilter {
|
||||
@Override
|
||||
public boolean allowExtract(FixedItemInv inv, int slotIndex, int amount) {
|
||||
return slotIndex >= 3 && slotIndex <= 5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowInsert(FixedItemInv inv, int slotIndex, ItemStack stack) {
|
||||
if (!GrinderRecipes.isValidIngredient(world, stack)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return slotIndex >= 0 && slotIndex <= 2;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
|
||||
package appeng.tile.inventory;
|
||||
|
||||
import alexiil.mc.lib.attributes.Simulation;
|
||||
import alexiil.mc.lib.attributes.item.impl.DelegatingFixedItemInv;
|
||||
import appeng.api.storage.cells.ICellInventory;
|
||||
import appeng.api.storage.cells.ICellInventoryHandler;
|
||||
import appeng.util.inv.IAEAppEngInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
public class AppEngCellInventory extends DelegatingFixedItemInv {
|
||||
private final ICellInventoryHandler<?>[] handlerForSlot;
|
||||
|
||||
public AppEngCellInventory(final IAEAppEngInventory host, final int slots) {
|
||||
super(new AppEngInternalInventory(host, slots, 1));
|
||||
this.handlerForSlot = new ICellInventoryHandler[slots];
|
||||
}
|
||||
|
||||
public void setHandler(final int slot, final ICellInventoryHandler<?> handler) {
|
||||
this.handlerForSlot[slot] = handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setInvStack(int slot, ItemStack to, Simulation simulation) {
|
||||
this.persist(slot);
|
||||
boolean result = super.setInvStack(slot, to, simulation);
|
||||
this.cleanup(slot);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getInvStack(int slot) {
|
||||
this.persist(slot);
|
||||
return super.getInvStack(slot);
|
||||
}
|
||||
|
||||
private void persist(int slot) {
|
||||
if (this.handlerForSlot[slot] != null) {
|
||||
final ICellInventory<?> ci = this.handlerForSlot[slot].getCellInv();
|
||||
if (ci != null) {
|
||||
ci.persist();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void cleanup(int slot) {
|
||||
if (this.handlerForSlot[slot] != null) {
|
||||
final ICellInventory<?> ci = this.handlerForSlot[slot].getCellInv();
|
||||
|
||||
if (ci == null || ci.getItemStack() != super.getInvStack(slot)) {
|
||||
this.handlerForSlot[slot] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* 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.tile.inventory;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import alexiil.mc.lib.attributes.ListenerRemovalToken;
|
||||
import alexiil.mc.lib.attributes.ListenerToken;
|
||||
import alexiil.mc.lib.attributes.Simulation;
|
||||
import alexiil.mc.lib.attributes.item.FixedItemInv;
|
||||
import alexiil.mc.lib.attributes.item.InvMarkDirtyListener;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.storage.channels.IItemStorageChannel;
|
||||
import appeng.api.storage.data.IAEItemStack;
|
||||
import appeng.core.AELog;
|
||||
import appeng.util.Platform;
|
||||
import appeng.util.inv.IAEAppEngInventory;
|
||||
import appeng.util.inv.InvOperation;
|
||||
import appeng.util.item.AEItemStack;
|
||||
import appeng.util.iterators.InvIterator;
|
||||
|
||||
public class AppEngInternalAEInventory implements FixedItemInv, Iterable<ItemStack> {
|
||||
private final IAEAppEngInventory te;
|
||||
private final IAEItemStack[] inv;
|
||||
private final int size;
|
||||
private int maxStack;
|
||||
private boolean dirtyFlag = false;
|
||||
|
||||
public AppEngInternalAEInventory(final IAEAppEngInventory te, final int s) {
|
||||
this.te = te;
|
||||
this.size = s;
|
||||
this.maxStack = 64;
|
||||
this.inv = new IAEItemStack[s];
|
||||
}
|
||||
|
||||
public void setMaxStackSize(final int s) {
|
||||
this.maxStack = s;
|
||||
}
|
||||
|
||||
public IAEItemStack getAEStackInSlot(final int var1) {
|
||||
return this.inv[var1];
|
||||
}
|
||||
|
||||
public void writeToNBT(final CompoundTag data, final String name) {
|
||||
final CompoundTag c = new CompoundTag();
|
||||
this.writeToNBT(c);
|
||||
data.put(name, c);
|
||||
}
|
||||
|
||||
private void writeToNBT(final CompoundTag target) {
|
||||
for (int x = 0; x < this.size; x++) {
|
||||
try {
|
||||
final CompoundTag c = new CompoundTag();
|
||||
|
||||
if (this.inv[x] != null) {
|
||||
this.inv[x].writeToNBT(c);
|
||||
}
|
||||
|
||||
target.put("#" + x, c);
|
||||
} catch (final Exception ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void readFromNBT(final CompoundTag data, final String name) {
|
||||
final CompoundTag c = data.getCompound(name);
|
||||
if (c != null) {
|
||||
this.readFromNBT(c);
|
||||
}
|
||||
}
|
||||
|
||||
private void readFromNBT(final CompoundTag target) {
|
||||
for (int x = 0; x < this.size; x++) {
|
||||
try {
|
||||
final CompoundTag c = target.getCompound("#" + x);
|
||||
|
||||
if (c != null) {
|
||||
this.inv[x] = AEItemStack.fromNBT(c);
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
AELog.debug(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected int getStackLimit(int slot, @Nonnull ItemStack stack) {
|
||||
return Math.min(this.getMaxAmount(slot, stack), stack.getMaxCount());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getInvStack(int slot) {
|
||||
if (this.inv[slot] == null) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
return this.inv[slot].createItemStack();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setInvStack(int slot, ItemStack to, Simulation simulation) {
|
||||
if (this.te == null || !Platform.isServer()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// FIXME: We need to implement the actual checks here, stacking /caninsert/canremove
|
||||
if (true) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
if (simulation == Simulation.SIMULATE) {
|
||||
return true;
|
||||
}
|
||||
|
||||
ItemStack oldStack = this.getInvStack(slot).copy();
|
||||
this.inv[slot] = AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class)
|
||||
.createStack(to);
|
||||
|
||||
ItemStack newStack = to.copy();
|
||||
InvOperation op = InvOperation.SET;
|
||||
|
||||
if (ItemStack.areItemsEqual(oldStack, newStack)) {
|
||||
if (newStack.getCount() > oldStack.getCount()) {
|
||||
newStack.decrement(oldStack.getCount());
|
||||
oldStack = ItemStack.EMPTY;
|
||||
op = InvOperation.INSERT;
|
||||
} else {
|
||||
oldStack.decrement(newStack.getCount());
|
||||
newStack = ItemStack.EMPTY;
|
||||
op = InvOperation.EXTRACT;
|
||||
}
|
||||
}
|
||||
this.fireOnChangeInventory(slot, op, oldStack, newStack);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSlotCount() {
|
||||
return this.size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isItemValidForSlot(int slot, ItemStack stack) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChangeValue() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public ListenerToken addListener(InvMarkDirtyListener listener, ListenerRemovalToken removalToken) {
|
||||
return null;
|
||||
}
|
||||
|
||||
private void fireOnChangeInventory(int slot, InvOperation op, ItemStack removed, ItemStack inserted) {
|
||||
if (this.te != null && Platform.isServer() && !this.dirtyFlag) {
|
||||
this.dirtyFlag = true;
|
||||
this.te.onChangeInventory(this, slot, op, removed, inserted);
|
||||
this.te.saveChanges();
|
||||
this.dirtyFlag = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxAmount(int slot, ItemStack is) {
|
||||
return Math.min(this.maxStack, 64);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<ItemStack> iterator() {
|
||||
return new InvIterator(this);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* 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.tile.inventory;
|
||||
|
||||
import alexiil.mc.lib.attributes.Simulation;
|
||||
import alexiil.mc.lib.attributes.item.FixedItemInvView;
|
||||
import alexiil.mc.lib.attributes.item.filter.ConstantItemFilter;
|
||||
import alexiil.mc.lib.attributes.item.filter.ItemFilter;
|
||||
import alexiil.mc.lib.attributes.item.impl.FullFixedItemInv;
|
||||
import appeng.util.Platform;
|
||||
import appeng.util.inv.IAEAppEngInventory;
|
||||
import appeng.util.inv.InvOperation;
|
||||
import appeng.util.inv.filter.IAEItemFilter;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
|
||||
// FIXME: the filtering is not correctly implemented and need to be reworked
|
||||
public class AppEngInternalInventory extends FullFixedItemInv implements Iterable<ItemStack> {
|
||||
private boolean enableClientEvents = false;
|
||||
private IAEAppEngInventory te;
|
||||
private final int[] maxStack;
|
||||
private IAEItemFilter filter;
|
||||
private boolean dirtyFlag = false;
|
||||
|
||||
public AppEngInternalInventory(final IAEAppEngInventory inventory, final int size, final int maxStack,
|
||||
IAEItemFilter filter) {
|
||||
super(size);
|
||||
this.setTileEntity(inventory);
|
||||
this.setFilter(filter);
|
||||
this.maxStack = new int[size];
|
||||
Arrays.fill(this.maxStack, maxStack);
|
||||
|
||||
setOwnerListener(this::onContentsChanged);
|
||||
}
|
||||
|
||||
public AppEngInternalInventory(final IAEAppEngInventory inventory, final int size, final int maxStack) {
|
||||
this(inventory, size, maxStack, null);
|
||||
}
|
||||
|
||||
public AppEngInternalInventory(final IAEAppEngInventory inventory, final int size) {
|
||||
this(inventory, size, 64);
|
||||
}
|
||||
|
||||
public void setFilter(IAEItemFilter filter) {
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxAmount(int slot, ItemStack stack) {
|
||||
return Math.min(maxStack[slot], super.getMaxAmount(slot, stack));
|
||||
}
|
||||
|
||||
protected void onContentsChanged(FixedItemInvView inv, int slot, ItemStack previous, ItemStack current) {
|
||||
if (this.getBlockEntity() != null && this.eventsEnabled() && !this.dirtyFlag) {
|
||||
this.dirtyFlag = true;
|
||||
ItemStack newStack = current.copy();
|
||||
ItemStack oldStack = previous;
|
||||
InvOperation op = InvOperation.SET;
|
||||
|
||||
if (newStack.isEmpty() || oldStack.isEmpty() || ItemStack.areItemsEqual(newStack, oldStack)) {
|
||||
if (newStack.getCount() > oldStack.getCount()) {
|
||||
newStack.decrement(oldStack.getCount());
|
||||
oldStack = ItemStack.EMPTY;
|
||||
op = InvOperation.INSERT;
|
||||
} else {
|
||||
oldStack.decrement(newStack.getCount());
|
||||
newStack = ItemStack.EMPTY;
|
||||
op = InvOperation.EXTRACT;
|
||||
}
|
||||
}
|
||||
|
||||
this.getBlockEntity().onChangeInventory(this, slot, op, oldStack, newStack);
|
||||
this.getBlockEntity().saveChanges();
|
||||
this.dirtyFlag = false;
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean eventsEnabled() {
|
||||
return Platform.isServer() || this.isEnableClientEvents();
|
||||
}
|
||||
|
||||
public void setMaxStackSize(final int slot, final int size) {
|
||||
this.maxStack[slot] = size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemFilter getFilterForSlot(int slot) {
|
||||
if (this.maxStack[slot] == 0) {
|
||||
return ConstantItemFilter.NOTHING;
|
||||
}
|
||||
if (this.filter != null) {
|
||||
return stack -> {
|
||||
// FIXME: This is not correct...
|
||||
if (stack == ItemStack.EMPTY) {
|
||||
return filter.allowExtract(this, slot, this.getSlot(slot).get().getCount());
|
||||
} else {
|
||||
return filter.allowExtract(this, slot, this.getSlot(slot).get().getCount());
|
||||
}
|
||||
};
|
||||
}
|
||||
return ConstantItemFilter.ANYTHING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isItemValidForSlot(int slot, ItemStack stack) {
|
||||
if (this.maxStack[slot] == 0) {
|
||||
return false;
|
||||
}
|
||||
if (this.filter != null) {
|
||||
return this.filter.allowInsert(this, slot, stack);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void writeToNBT(final CompoundTag data, final String name) {
|
||||
data.put(name, this.toTag());
|
||||
}
|
||||
|
||||
public void readFromNBT(final CompoundTag data, final String name) {
|
||||
final CompoundTag c = data.getCompound(name);
|
||||
if (c != null) {
|
||||
this.readFromNBT(c);
|
||||
}
|
||||
}
|
||||
|
||||
public void readFromNBT(final CompoundTag data) {
|
||||
this.fromTag(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<ItemStack> iterator() {
|
||||
return stackIterable().iterator();
|
||||
}
|
||||
|
||||
private boolean isEnableClientEvents() {
|
||||
return this.enableClientEvents;
|
||||
}
|
||||
|
||||
public void setEnableClientEvents(final boolean enableClientEvents) {
|
||||
this.enableClientEvents = enableClientEvents;
|
||||
}
|
||||
|
||||
private IAEAppEngInventory getBlockEntity() {
|
||||
return this.te;
|
||||
}
|
||||
|
||||
public void setTileEntity(final IAEAppEngInventory te) {
|
||||
this.te = te;
|
||||
}
|
||||
}
|
||||
@@ -1,219 +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.tile.misc;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import alexiil.mc.lib.attributes.item.FixedItemInv;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import appeng.api.config.CopyMode;
|
||||
import appeng.api.config.Settings;
|
||||
import appeng.api.config.Upgrades;
|
||||
import appeng.api.implementations.IUpgradeableHost;
|
||||
import appeng.api.storage.cells.ICellWorkbenchItem;
|
||||
import appeng.api.util.IConfigManager;
|
||||
import appeng.tile.AEBaseBlockEntity;
|
||||
import appeng.tile.inventory.AppEngInternalAEInventory;
|
||||
import appeng.tile.inventory.AppEngInternalInventory;
|
||||
import appeng.util.ConfigManager;
|
||||
import appeng.util.IConfigManagerHost;
|
||||
import appeng.util.helpers.ItemHandlerUtil;
|
||||
import appeng.util.inv.IAEAppEngInventory;
|
||||
import appeng.util.inv.InvOperation;
|
||||
|
||||
public class CellWorkbenchBlockEntity extends AEBaseBlockEntity
|
||||
implements IUpgradeableHost, IAEAppEngInventory, IConfigManagerHost {
|
||||
|
||||
private final AppEngInternalInventory cell = new AppEngInternalInventory(this, 1);
|
||||
private final AppEngInternalAEInventory config = new AppEngInternalAEInventory(this, 63);
|
||||
private final ConfigManager manager = new ConfigManager(this);
|
||||
|
||||
private FixedItemInv cacheUpgrades = null;
|
||||
private FixedItemInv cacheConfig = null;
|
||||
private boolean locked = false;
|
||||
|
||||
public CellWorkbenchBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
this.manager.registerSetting(Settings.COPY_MODE, CopyMode.CLEAR_ON_REMOVE);
|
||||
this.cell.setEnableClientEvents(true);
|
||||
}
|
||||
|
||||
public FixedItemInv getCellUpgradeInventory() {
|
||||
if (this.cacheUpgrades == null) {
|
||||
final ICellWorkbenchItem cell = this.getCell();
|
||||
if (cell == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final ItemStack is = this.cell.getInvStack(0);
|
||||
if (is.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final FixedItemInv inv = cell.getUpgradesInventory(is);
|
||||
if (inv == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.cacheUpgrades = inv;
|
||||
}
|
||||
return this.cacheUpgrades;
|
||||
}
|
||||
|
||||
public ICellWorkbenchItem getCell() {
|
||||
if (this.cell.getInvStack(0).isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (this.cell.getInvStack(0).getItem() instanceof ICellWorkbenchItem) {
|
||||
return ((ICellWorkbenchItem) this.cell.getInvStack(0).getItem());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag toTag(final CompoundTag data) {
|
||||
super.toTag(data);
|
||||
this.cell.writeToNBT(data, "cell");
|
||||
this.config.writeToNBT(data, "config");
|
||||
this.manager.writeToNBT(data);
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromTag(BlockState state, final CompoundTag data) {
|
||||
super.fromTag(state, data);
|
||||
this.cell.readFromNBT(data, "cell");
|
||||
this.config.readFromNBT(data, "config");
|
||||
this.manager.readFromNBT(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FixedItemInv getInventoryByName(final String name) {
|
||||
if (name.equals("config")) {
|
||||
return this.config;
|
||||
}
|
||||
|
||||
if (name.equals("cell")) {
|
||||
return this.cell;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInstalledUpgrades(final Upgrades u) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeInventory(final FixedItemInv inv, final int slot, final InvOperation mc,
|
||||
final ItemStack removedStack, final ItemStack newStack) {
|
||||
if (inv == this.cell && !this.locked) {
|
||||
this.locked = true;
|
||||
|
||||
this.cacheUpgrades = null;
|
||||
this.cacheConfig = null;
|
||||
|
||||
final FixedItemInv configInventory = this.getCellConfigInventory();
|
||||
if (configInventory != null) {
|
||||
boolean cellHasConfig = false;
|
||||
for (int x = 0; x < configInventory.getSlotCount(); x++) {
|
||||
if (!configInventory.getInvStack(x).isEmpty()) {
|
||||
cellHasConfig = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cellHasConfig) {
|
||||
for (int x = 0; x < this.config.getSlotCount(); x++) {
|
||||
this.config.setInvStack(x, configInventory.getInvStack(x));
|
||||
}
|
||||
} else {
|
||||
ItemHandlerUtil.copy(this.config, configInventory, false);
|
||||
}
|
||||
} else if (this.manager.getSetting(Settings.COPY_MODE) == CopyMode.CLEAR_ON_REMOVE) {
|
||||
for (int x = 0; x < this.config.getSlotCount(); x++) {
|
||||
this.config.setInvStack(x, ItemStack.EMPTY);
|
||||
}
|
||||
|
||||
this.saveChanges();
|
||||
}
|
||||
|
||||
this.locked = false;
|
||||
} else if (inv == this.config && !this.locked) {
|
||||
this.locked = true;
|
||||
final FixedItemInv c = this.getCellConfigInventory();
|
||||
if (c != null) {
|
||||
ItemHandlerUtil.copy(this.config, c, false);
|
||||
// copy items back. The ConfigInventory may changed the items on insert
|
||||
ItemHandlerUtil.copy(c, this.config, false);
|
||||
}
|
||||
this.locked = false;
|
||||
}
|
||||
}
|
||||
|
||||
private FixedItemInv getCellConfigInventory() {
|
||||
if (this.cacheConfig == null) {
|
||||
final ICellWorkbenchItem cell = this.getCell();
|
||||
if (cell == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final ItemStack is = this.cell.getInvStack(0);
|
||||
if (is.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final FixedItemInv inv = cell.getConfigInventory(is);
|
||||
if (inv == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
this.cacheConfig = inv;
|
||||
}
|
||||
return this.cacheConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getDrops(final World w, final BlockPos pos, final List<ItemStack> drops) {
|
||||
super.getDrops(w, pos, drops);
|
||||
|
||||
if (this.cell.getInvStack(0) != null) {
|
||||
drops.add(this.cell.getInvStack(0));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IConfigManager getConfigManager() {
|
||||
return this.manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSetting(final IConfigManager manager, final Settings settingName, final Enum<?> newValue) {
|
||||
// nothing here..
|
||||
}
|
||||
}
|
||||
@@ -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.tile.misc;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import alexiil.mc.lib.attributes.item.FixedItemInv;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.config.Actionable;
|
||||
import appeng.api.config.PowerMultiplier;
|
||||
import appeng.api.config.PowerUnits;
|
||||
import appeng.api.definitions.IItemDefinition;
|
||||
import appeng.api.definitions.IMaterials;
|
||||
import appeng.api.implementations.items.IAEItemPowerStorage;
|
||||
import appeng.api.implementations.tiles.ICrankable;
|
||||
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.storage.data.IAEItemStack;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
import appeng.api.util.DimensionalCoord;
|
||||
import appeng.core.settings.TickRates;
|
||||
import appeng.me.GridAccessException;
|
||||
import appeng.tile.grid.AENetworkPowerBlockEntity;
|
||||
import appeng.tile.inventory.AppEngInternalInventory;
|
||||
import appeng.util.Platform;
|
||||
import appeng.util.inv.InvOperation;
|
||||
import appeng.util.inv.filter.IAEItemFilter;
|
||||
import appeng.util.item.AEItemStack;
|
||||
|
||||
public class ChargerBlockEntity extends AENetworkPowerBlockEntity implements ICrankable, IGridTickable {
|
||||
private static final int POWER_MAXIMUM_AMOUNT = 1600;
|
||||
private static final int POWER_THRESHOLD = POWER_MAXIMUM_AMOUNT - 1;
|
||||
private static final int POWER_PER_CRANK_TURN = 160;
|
||||
|
||||
private final AppEngInternalInventory inv = new AppEngInternalInventory(this, 1, 1, new ChargerInvFilter());
|
||||
|
||||
public ChargerBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
this.getProxy().setValidSides(EnumSet.noneOf(Direction.class));
|
||||
this.getProxy().setFlags();
|
||||
this.setInternalMaxPower(POWER_MAXIMUM_AMOUNT);
|
||||
this.getProxy().setIdlePowerUsage(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AECableType getCableConnectionType(final AEPartLocation dir) {
|
||||
return AECableType.COVERED;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean readFromStream(final PacketByteBuf data) throws IOException {
|
||||
final boolean c = super.readFromStream(data);
|
||||
try {
|
||||
final IAEItemStack item = AEItemStack.fromPacket(data);
|
||||
final ItemStack is = item.createItemStack();
|
||||
this.inv.setInvStack(0, is);
|
||||
} catch (final Throwable t) {
|
||||
this.inv.setInvStack(0, ItemStack.EMPTY);
|
||||
}
|
||||
return c; // TESR doesn't need updates!
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeToStream(final PacketByteBuf data) throws IOException {
|
||||
super.writeToStream(data);
|
||||
final AEItemStack is = AEItemStack.fromItemStack(this.inv.getInvStack(0));
|
||||
if (is != null) {
|
||||
is.writeToPacket(data);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOrientation(final Direction inForward, final Direction inUp) {
|
||||
super.setOrientation(inForward, inUp);
|
||||
this.getProxy().setValidSides(EnumSet.of(this.getUp(), this.getUp().getOpposite()));
|
||||
this.setPowerSides(EnumSet.of(this.getUp(), this.getUp().getOpposite()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canTurn() {
|
||||
return this.getInternalCurrentPower() < this.getInternalMaxPower();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyTurn() {
|
||||
this.injectExternalPower(PowerUnits.AE, POWER_PER_CRANK_TURN, Actionable.MODULATE);
|
||||
|
||||
final ItemStack myItem = this.inv.getInvStack(0);
|
||||
if (this.getInternalCurrentPower() > POWER_THRESHOLD) {
|
||||
final IMaterials materials = AEApi.instance().definitions().materials();
|
||||
|
||||
if (materials.certusQuartzCrystal().isSameAs(myItem)) {
|
||||
this.extractAEPower(this.getInternalMaxPower(), Actionable.MODULATE, PowerMultiplier.CONFIG);
|
||||
|
||||
materials.certusQuartzCrystalCharged().maybeStack(myItem.getCount())
|
||||
.ifPresent(charged -> this.inv.setInvStack(0, charged));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canCrankAttach(final Direction directionToCrank) {
|
||||
return this.getUp() == directionToCrank || this.getUp().getOpposite() == directionToCrank;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FixedItemInv getInternalInventory() {
|
||||
return this.inv;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeInventory(final FixedItemInv inv, final int slot, final InvOperation mc,
|
||||
final ItemStack removed, final ItemStack added) {
|
||||
try {
|
||||
this.getProxy().getTick().wakeDevice(this.getProxy().getNode());
|
||||
} catch (final GridAccessException e) {
|
||||
// :P
|
||||
}
|
||||
|
||||
this.markForUpdate();
|
||||
}
|
||||
|
||||
public void activate(final PlayerEntity player) {
|
||||
if (!Platform.hasPermissions(new DimensionalCoord(this), player)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final ItemStack myItem = this.inv.getInvStack(0);
|
||||
if (myItem.isEmpty()) {
|
||||
ItemStack held = player.inventory.getCurrentItem();
|
||||
|
||||
if (AEApi.instance().definitions().materials().certusQuartzCrystal().isSameAs(held)
|
||||
|| Platform.isChargeable(held)) {
|
||||
held = player.inventory.decrStackSize(player.inventory.currentItem, 1);
|
||||
this.inv.setInvStack(0, held);
|
||||
}
|
||||
} else {
|
||||
final List<ItemStack> drops = new ArrayList<>();
|
||||
drops.add(myItem);
|
||||
this.inv.setInvStack(0, ItemStack.EMPTY);
|
||||
Platform.spawnDrops(this.world, this.pos.offset(this.getForward()), drops);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickingRequest getTickingRequest(IGridNode node) {
|
||||
return new TickingRequest(TickRates.Charger.getMin(), TickRates.Charger.getMin(), false, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickRateModulation tickingRequest(IGridNode node, int TicksSinceLastCall) {
|
||||
return this.doWork() ? TickRateModulation.FASTER : TickRateModulation.SLEEP;
|
||||
}
|
||||
|
||||
private boolean doWork() {
|
||||
final ItemStack myItem = this.inv.getInvStack(0);
|
||||
boolean changed = false;
|
||||
|
||||
if (!myItem.isEmpty()) {
|
||||
final IMaterials materials = AEApi.instance().definitions().materials();
|
||||
|
||||
if (Platform.isChargeable(myItem)) {
|
||||
final IAEItemPowerStorage ps = (IAEItemPowerStorage) myItem.getItem();
|
||||
|
||||
if (ps.getAEMaxPower(myItem) > ps.getAECurrentPower(myItem)) {
|
||||
final double chargeRate = AEApi.instance().registries().charger().getChargeRate(myItem.getItem());
|
||||
|
||||
double extractedAmount = this.extractAEPower(chargeRate, Actionable.MODULATE,
|
||||
PowerMultiplier.CONFIG);
|
||||
|
||||
final double missingChargeRate = chargeRate - extractedAmount;
|
||||
final double missingAEPower = ps.getAEMaxPower(myItem) - ps.getAECurrentPower(myItem);
|
||||
final double toExtract = Math.min(missingChargeRate, missingAEPower);
|
||||
|
||||
try {
|
||||
extractedAmount += this.getProxy().getEnergy().extractAEPower(toExtract, Actionable.MODULATE,
|
||||
PowerMultiplier.ONE);
|
||||
} catch (GridAccessException e1) {
|
||||
// Ignore.
|
||||
}
|
||||
|
||||
if (extractedAmount > 0) {
|
||||
final double adjustment = ps.injectAEPower(myItem, extractedAmount, Actionable.MODULATE);
|
||||
|
||||
this.setInternalCurrentPower(this.getInternalCurrentPower() + adjustment);
|
||||
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
} else if (this.getInternalCurrentPower() > POWER_THRESHOLD
|
||||
&& materials.certusQuartzCrystal().isSameAs(myItem)) {
|
||||
if (Platform.getRandomFloat() > 0.8f) // simulate wait
|
||||
{
|
||||
this.extractAEPower(this.getInternalMaxPower(), Actionable.MODULATE, PowerMultiplier.CONFIG);
|
||||
|
||||
materials.certusQuartzCrystalCharged().maybeStack(myItem.getCount())
|
||||
.ifPresent(charged -> this.inv.setInvStack(0, charged));
|
||||
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// charge from the network!
|
||||
if (this.getInternalCurrentPower() < POWER_THRESHOLD) {
|
||||
try {
|
||||
final double toExtract = Math.min(800.0, this.getInternalMaxPower() - this.getInternalCurrentPower());
|
||||
final double extracted = this.getProxy().getEnergy().extractAEPower(toExtract, Actionable.MODULATE,
|
||||
PowerMultiplier.ONE);
|
||||
|
||||
this.injectExternalPower(PowerUnits.AE, extracted, Actionable.MODULATE);
|
||||
} catch (final GridAccessException e) {
|
||||
// continue!
|
||||
}
|
||||
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
this.markForUpdate();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private class ChargerInvFilter implements IAEItemFilter {
|
||||
@Override
|
||||
public boolean allowInsert(FixedItemInv inv, final int i, final ItemStack itemstack) {
|
||||
final IItemDefinition cert = AEApi.instance().definitions().materials().certusQuartzCrystal();
|
||||
|
||||
return Platform.isChargeable(itemstack) || cert.isSameAs(itemstack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowExtract(FixedItemInv inv, final int slotIndex, int amount) {
|
||||
ItemStack extractedItem = inv.getInvStack(slotIndex);
|
||||
|
||||
if (Platform.isChargeable(extractedItem)) {
|
||||
final IAEItemPowerStorage ips = (IAEItemPowerStorage) extractedItem.getItem();
|
||||
if (ips.getAECurrentPower(extractedItem) >= ips.getAEMaxPower(extractedItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return AEApi.instance().definitions().materials().certusQuartzCrystalCharged().isSameAs(extractedItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,356 +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.tile.misc;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import alexiil.mc.lib.attributes.fluid.volume.FluidVolume;
|
||||
import alexiil.mc.lib.attributes.item.FixedItemInv;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.fluids.FluidAttributes;
|
||||
import net.minecraftforge.fluids.IFluidTank;
|
||||
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler;
|
||||
import net.minecraftforge.items.CapabilityItemHandler;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.config.CondenserOutput;
|
||||
import appeng.api.config.Settings;
|
||||
import appeng.api.definitions.IMaterials;
|
||||
import appeng.api.implementations.items.IStorageComponent;
|
||||
import appeng.api.networking.security.IActionSource;
|
||||
import appeng.api.storage.IMEMonitor;
|
||||
import appeng.api.storage.IStorageChannel;
|
||||
import appeng.api.storage.IStorageMonitorable;
|
||||
import appeng.api.storage.IStorageMonitorableAccessor;
|
||||
import appeng.api.storage.channels.IFluidStorageChannel;
|
||||
import appeng.api.storage.channels.IItemStorageChannel;
|
||||
import appeng.api.storage.data.IAEFluidStack;
|
||||
import appeng.api.storage.data.IAEStack;
|
||||
import appeng.api.util.IConfigManager;
|
||||
import appeng.api.util.IConfigurableObject;
|
||||
import appeng.capabilities.Capabilities;
|
||||
import appeng.tile.AEBaseInvBlockEntity;
|
||||
import appeng.tile.inventory.AppEngInternalInventory;
|
||||
import appeng.util.ConfigManager;
|
||||
import appeng.util.IConfigManagerHost;
|
||||
import appeng.util.inv.InvOperation;
|
||||
import appeng.util.inv.WrapperChainedItemHandler;
|
||||
import appeng.util.inv.WrapperFilteredItemHandler;
|
||||
import appeng.util.inv.filter.AEItemFilters;
|
||||
|
||||
public class CondenserBlockEntity extends AEBaseInvBlockEntity implements IConfigManagerHost, IConfigurableObject {
|
||||
|
||||
public static final int BYTE_MULTIPLIER = 8;
|
||||
|
||||
private final ConfigManager cm = new ConfigManager(this);
|
||||
|
||||
private final AppEngInternalInventory outputSlot = new AppEngInternalInventory(this, 1);
|
||||
private final AppEngInternalInventory storageSlot = new AppEngInternalInventory(this, 1);
|
||||
private final FixedItemInv inputSlot = new CondenseItemHandler();
|
||||
private final IFluidHandler fluidHandler = new FluidHandler();
|
||||
private final MEHandler meHandler = new MEHandler();
|
||||
|
||||
private final FixedItemInv externalInv = new WrapperChainedItemHandler(this.inputSlot,
|
||||
new WrapperFilteredItemHandler(this.outputSlot, AEItemFilters.EXTRACT_ONLY));
|
||||
private final FixedItemInv combinedInv = new WrapperChainedItemHandler(this.inputSlot, this.outputSlot,
|
||||
this.storageSlot);
|
||||
|
||||
private double storedPower = 0;
|
||||
|
||||
public CondenserBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
this.cm.registerSetting(Settings.CONDENSER_OUTPUT, CondenserOutput.TRASH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag toTag(final CompoundTag data) {
|
||||
super.toTag(data);
|
||||
this.cm.writeToNBT(data);
|
||||
data.putDouble("storedPower", this.getStoredPower());
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromTag(BlockState state, final CompoundTag data) {
|
||||
super.fromTag(state, data);
|
||||
this.cm.readFromNBT(data);
|
||||
this.setStoredPower(data.getDouble("storedPower"));
|
||||
}
|
||||
|
||||
public double getStorage() {
|
||||
final ItemStack is = this.storageSlot.getInvStack(0);
|
||||
if (!is.isEmpty()) {
|
||||
if (is.getItem() instanceof IStorageComponent) {
|
||||
final IStorageComponent sc = (IStorageComponent) is.getItem();
|
||||
if (sc.isStorageComponent(is)) {
|
||||
return sc.getBytes(is) * BYTE_MULTIPLIER;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void addPower(final double rawPower) {
|
||||
this.setStoredPower(this.getStoredPower() + rawPower);
|
||||
this.setStoredPower(Math.max(0.0, Math.min(this.getStorage(), this.getStoredPower())));
|
||||
|
||||
final double requiredPower = this.getRequiredPower();
|
||||
final ItemStack output = this.getOutput();
|
||||
while (requiredPower <= this.getStoredPower() && !output.isEmpty() && requiredPower > 0) {
|
||||
if (this.canAddOutput(output)) {
|
||||
this.setStoredPower(this.getStoredPower() - requiredPower);
|
||||
this.addOutput(output);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean canAddOutput(final ItemStack output) {
|
||||
return this.outputSlot.insertItem(0, output, true).isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* make sure you validate with canAddOutput prior to this.
|
||||
*
|
||||
* @param output to be added output
|
||||
*/
|
||||
private void addOutput(final ItemStack output) {
|
||||
this.outputSlot.insertItem(0, output, false);
|
||||
}
|
||||
|
||||
FixedItemInv getOutputSlot() {
|
||||
return this.outputSlot;
|
||||
}
|
||||
|
||||
private ItemStack getOutput() {
|
||||
final IMaterials materials = AEApi.instance().definitions().materials();
|
||||
|
||||
switch ((CondenserOutput) this.cm.getSetting(Settings.CONDENSER_OUTPUT)) {
|
||||
case MATTER_BALLS:
|
||||
return materials.matterBall().maybeStack(1).orElse(ItemStack.EMPTY);
|
||||
|
||||
case SINGULARITY:
|
||||
return materials.singularity().maybeStack(1).orElse(ItemStack.EMPTY);
|
||||
|
||||
case TRASH:
|
||||
default:
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
public double getRequiredPower() {
|
||||
return ((CondenserOutput) this.cm.getSetting(Settings.CONDENSER_OUTPUT)).requiredPower;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FixedItemInv getInternalInventory() {
|
||||
return this.combinedInv;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeInventory(final FixedItemInv inv, final int slot, final InvOperation mc,
|
||||
final ItemStack removed, final ItemStack added) {
|
||||
if (inv == this.outputSlot) {
|
||||
this.meHandler.outputChanged(added, removed);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSetting(final IConfigManager manager, final Settings settingName, final Enum<?> newValue) {
|
||||
this.addPower(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IConfigManager getConfigManager() {
|
||||
return this.cm;
|
||||
}
|
||||
|
||||
public double getStoredPower() {
|
||||
return this.storedPower;
|
||||
}
|
||||
|
||||
private void setStoredPower(final double storedPower) {
|
||||
this.storedPower = storedPower;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> LazyOptional<T> getCapability(Capability<T> capability, @Nullable Direction facing) {
|
||||
if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
|
||||
return (LazyOptional<T>) LazyOptional.of(() -> this.externalInv);
|
||||
} else if (capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) {
|
||||
return (LazyOptional<T>) LazyOptional.of(() -> this.fluidHandler);
|
||||
} else if (capability == Capabilities.STORAGE_MONITORABLE_ACCESSOR) {
|
||||
return (LazyOptional<T>) LazyOptional.of(() -> this.meHandler);
|
||||
}
|
||||
return super.getCapability(capability, facing);
|
||||
}
|
||||
|
||||
private class CondenseItemHandler implements FixedItemInv {
|
||||
|
||||
@Override
|
||||
public int getSlots() {
|
||||
// We only expose the void slot
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isItemValid(int slot, @Nonnull ItemStack stack) {
|
||||
return slot == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getStackInSlot(int slot) {
|
||||
// The void slot never has any content
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) {
|
||||
if (slot != 0) {
|
||||
return stack;
|
||||
}
|
||||
if (!simulate && !stack.isEmpty()) {
|
||||
CondenserBlockEntity.this.addPower(stack.getCount());
|
||||
}
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack extractItem(int slot, int amount, boolean simulate) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxAmount(int slot, ItemStack is) {
|
||||
return 64;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A fluid handler that exposes a 1 bucket tank that can only be filled, and -
|
||||
* when filled - will add power to this condenser.
|
||||
*/
|
||||
private class FluidHandler implements IFluidTank, IFluidHandler {
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public FluidVolume getFluid() {
|
||||
return FluidVolumeUtil.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFluidAmount() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCapacity() {
|
||||
return FluidAttributes.BUCKET_VOLUME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFluidValid(FluidVolume stack) {
|
||||
return !stack.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int fill(FluidVolume resource, FluidAction action) {
|
||||
if (action == FluidAction.EXECUTE) {
|
||||
final IStorageChannel<IAEFluidStack> chan = AEApi.instance().storage()
|
||||
.getStorageChannel(IFluidStorageChannel.class);
|
||||
CondenserBlockEntity.this
|
||||
.addPower((resource.isEmpty() ? 0.0 : (double) resource.getAmount()) / chan.transferFactor());
|
||||
}
|
||||
|
||||
return resource.isEmpty() ? 0 : resource.getAmount();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public FluidVolume drain(int maxDrain, FluidAction action) {
|
||||
return FluidVolumeUtil.EMPTY;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public FluidVolume drain(FluidVolume resource, FluidAction action) {
|
||||
return FluidVolumeUtil.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTanks() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public FluidVolume getFluidInTank(int tank) {
|
||||
return FluidVolumeUtil.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTankCapacity(int tank) {
|
||||
return tank == 0 ? getCapacity() : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFluidValid(int tank, @Nonnull FluidVolume stack) {
|
||||
return tank == 0 && isFluidValid(stack);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is used to expose a fake ME subnetwork that is only composed of this
|
||||
* condenser tile. The purpose of this is to enable the condenser to override
|
||||
* the {@link appeng.api.storage.IMEInventoryHandler#validForPass(int)} method
|
||||
* to make sure a condenser is only ever used if an item can't go anywhere else.
|
||||
*/
|
||||
private class MEHandler implements IStorageMonitorableAccessor, IStorageMonitorable {
|
||||
private final CondenserItemInventory itemInventory = new CondenserItemInventory(CondenserBlockEntity.this);
|
||||
|
||||
void outputChanged(ItemStack added, ItemStack removed) {
|
||||
this.itemInventory.updateOutput(added, removed);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public IStorageMonitorable getInventory(IActionSource src) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends IAEStack<T>> IMEMonitor<T> getInventory(IStorageChannel<T> channel) {
|
||||
if (channel == AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class)) {
|
||||
return (IMEMonitor<T>) this.itemInventory;
|
||||
} else {
|
||||
return new CondenserVoidInventory<>(CondenserBlockEntity.this, channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,175 +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.tile.misc;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.config.AccessRestriction;
|
||||
import appeng.api.config.Actionable;
|
||||
import appeng.api.networking.security.IActionSource;
|
||||
import appeng.api.networking.ticking.TickRateModulation;
|
||||
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.IItemList;
|
||||
import appeng.me.helpers.BaseActionSource;
|
||||
import appeng.me.storage.ITickingMonitor;
|
||||
import appeng.util.item.AEItemStack;
|
||||
import appeng.util.item.ItemList;
|
||||
|
||||
class CondenserItemInventory implements IMEMonitor<IAEItemStack>, ITickingMonitor {
|
||||
private final HashMap<IMEMonitorHandlerReceiver<IAEItemStack>, Object> listeners = new HashMap<>();
|
||||
private final CondenserBlockEntity target;
|
||||
private boolean hasChanged = true;
|
||||
private final ItemList cachedList = new ItemList();
|
||||
private IActionSource actionSource = new BaseActionSource();
|
||||
private ItemList changeSet = new ItemList();
|
||||
|
||||
CondenserItemInventory(final CondenserBlockEntity te) {
|
||||
this.target = te;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAEItemStack injectItems(final IAEItemStack input, final Actionable mode, final IActionSource src) {
|
||||
if (mode == Actionable.MODULATE && input != null) {
|
||||
this.target.addPower(input.getStackSize());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAEItemStack extractItems(final IAEItemStack request, final Actionable mode, final IActionSource src) {
|
||||
AEItemStack ret = null;
|
||||
ItemStack slotItem = this.target.getOutputSlot().getInvStack(0);
|
||||
if (!slotItem.isEmpty() && request.isSameType(slotItem)) {
|
||||
int count = (int) Math.min(request.getStackSize(), Integer.MAX_VALUE);
|
||||
ret = AEItemStack
|
||||
.fromItemStack(this.target.getOutputSlot().extractItem(0, count, mode == Actionable.SIMULATE));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IItemList<IAEItemStack> getAvailableItems(final IItemList<IAEItemStack> out) {
|
||||
if (!this.target.getOutputSlot().getInvStack(0).isEmpty()) {
|
||||
out.add(AEItemStack.fromItemStack(this.target.getOutputSlot().getInvStack(0)));
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IItemList<IAEItemStack> getStorageList() {
|
||||
if (this.hasChanged) {
|
||||
this.hasChanged = false;
|
||||
this.cachedList.resetStatus();
|
||||
return this.getAvailableItems(this.cachedList);
|
||||
}
|
||||
return this.cachedList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IStorageChannel<IAEItemStack> getChannel() {
|
||||
return AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessRestriction getAccess() {
|
||||
return AccessRestriction.READ_WRITE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrioritized(final IAEItemStack input) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAccept(final IAEItemStack input) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSlot() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validForPass(final int i) {
|
||||
return i == 2;
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
public void updateOutput(ItemStack added, ItemStack removed) {
|
||||
this.hasChanged = true;
|
||||
if (!added.isEmpty()) {
|
||||
this.changeSet.add(AEItemStack.fromItemStack(added));
|
||||
}
|
||||
if (!removed.isEmpty()) {
|
||||
this.changeSet.add(AEItemStack.fromItemStack(removed).setStackSize(-removed.getCount()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickRateModulation onTick() {
|
||||
final ItemList currentChanges = this.changeSet;
|
||||
|
||||
if (currentChanges.isEmpty()) {
|
||||
return TickRateModulation.IDLE;
|
||||
}
|
||||
|
||||
this.changeSet = new ItemList();
|
||||
final Iterator<Entry<IMEMonitorHandlerReceiver<IAEItemStack>, Object>> i = this.listeners.entrySet().iterator();
|
||||
while (i.hasNext()) {
|
||||
final Entry<IMEMonitorHandlerReceiver<IAEItemStack>, Object> l = i.next();
|
||||
final IMEMonitorHandlerReceiver<IAEItemStack> key = l.getKey();
|
||||
if (key.isValid(l.getValue())) {
|
||||
key.postChange(this, currentChanges, this.actionSource);
|
||||
} else {
|
||||
i.remove();
|
||||
}
|
||||
}
|
||||
|
||||
return TickRateModulation.URGENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActionSource(IActionSource actionSource) {
|
||||
this.actionSource = actionSource;
|
||||
}
|
||||
}
|
||||
@@ -1,112 +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.tile.misc;
|
||||
|
||||
import appeng.api.config.AccessRestriction;
|
||||
import appeng.api.config.Actionable;
|
||||
import appeng.api.networking.security.IActionSource;
|
||||
import appeng.api.storage.IMEMonitor;
|
||||
import appeng.api.storage.IMEMonitorHandlerReceiver;
|
||||
import appeng.api.storage.IStorageChannel;
|
||||
import appeng.api.storage.data.IAEStack;
|
||||
import appeng.api.storage.data.IItemList;
|
||||
|
||||
class CondenserVoidInventory<T extends IAEStack<T>> implements IMEMonitor<T> {
|
||||
|
||||
private final CondenserBlockEntity target;
|
||||
private final IStorageChannel<T> channel;
|
||||
|
||||
CondenserVoidInventory(final CondenserBlockEntity te, final IStorageChannel<T> channel) {
|
||||
this.target = te;
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T injectItems(final T input, final Actionable mode, final IActionSource src) {
|
||||
if (mode == Actionable.SIMULATE) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (input != null) {
|
||||
this.target.addPower(input.getStackSize() / (double) this.channel.transferFactor());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@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 IItemList<T> getStorageList() {
|
||||
return this.channel.createList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IStorageChannel<T> getChannel() {
|
||||
return this.channel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessRestriction getAccess() {
|
||||
return AccessRestriction.WRITE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrioritized(final T input) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAccept(final T input) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSlot() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validForPass(final int i) {
|
||||
return i == 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener(IMEMonitorHandlerReceiver<T> l, Object verificationToken) {
|
||||
// Not implemented since the Condenser automatically voids everything, and there
|
||||
// are no updates
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListener(IMEMonitorHandlerReceiver<T> l) {
|
||||
// Not implemented since we don't remember registered listeners anyway
|
||||
}
|
||||
}
|
||||
@@ -1,443 +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.tile.misc;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import alexiil.mc.lib.attributes.item.FixedItemInv;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.items.IItemHandlerModifiable;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.config.Actionable;
|
||||
import appeng.api.config.PowerMultiplier;
|
||||
import appeng.api.config.Settings;
|
||||
import appeng.api.config.Upgrades;
|
||||
import appeng.api.definitions.ITileDefinition;
|
||||
import appeng.api.features.InscriberProcessType;
|
||||
import appeng.api.implementations.IUpgradeableHost;
|
||||
import appeng.api.networking.IGridNode;
|
||||
import appeng.api.networking.energy.IEnergyGrid;
|
||||
import appeng.api.networking.energy.IEnergySource;
|
||||
import appeng.api.networking.ticking.IGridTickable;
|
||||
import appeng.api.networking.ticking.TickRateModulation;
|
||||
import appeng.api.networking.ticking.TickingRequest;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
import appeng.api.util.IConfigManager;
|
||||
import appeng.core.settings.TickRates;
|
||||
import appeng.me.GridAccessException;
|
||||
import appeng.parts.automation.DefinitionUpgradeInventory;
|
||||
import appeng.parts.automation.UpgradeInventory;
|
||||
import appeng.recipes.handlers.InscriberRecipe;
|
||||
import appeng.tile.grid.AENetworkPowerBlockEntity;
|
||||
import appeng.tile.inventory.AppEngInternalInventory;
|
||||
import appeng.util.ConfigManager;
|
||||
import appeng.util.IConfigManagerHost;
|
||||
import appeng.util.inv.InvOperation;
|
||||
import appeng.util.inv.WrapperChainedItemHandler;
|
||||
import appeng.util.inv.WrapperFilteredItemHandler;
|
||||
import appeng.util.inv.filter.IAEItemFilter;
|
||||
import appeng.util.item.AEItemStack;
|
||||
|
||||
/**
|
||||
* @author AlgorithmX2
|
||||
* @author thatsIch
|
||||
* @version rv2
|
||||
* @since rv0
|
||||
*/
|
||||
public class InscriberBlockEntity extends AENetworkPowerBlockEntity
|
||||
implements IGridTickable, IUpgradeableHost, IConfigManagerHost {
|
||||
private final int maxProcessingTime = 100;
|
||||
|
||||
private final IConfigManager settings;
|
||||
private final UpgradeInventory upgrades;
|
||||
private int processingTime = 0;
|
||||
// cycles from 0 - 16, at 8 it preforms the action, at 16 it re-enables the
|
||||
// normal routine.
|
||||
private boolean smash;
|
||||
private int finalStep;
|
||||
private long clientStart;
|
||||
private final AppEngInternalInventory topItemHandler = new AppEngInternalInventory(this, 1, 1);
|
||||
private final AppEngInternalInventory bottomItemHandler = new AppEngInternalInventory(this, 1, 1);
|
||||
private final AppEngInternalInventory sideItemHandler = new AppEngInternalInventory(this, 2, 1);
|
||||
|
||||
private final FixedItemInv topItemHandlerExtern;
|
||||
private final FixedItemInv bottomItemHandlerExtern;
|
||||
private final FixedItemInv sideItemHandlerExtern;
|
||||
|
||||
private InscriberRecipe cachedTask = null;
|
||||
|
||||
private final IItemHandlerModifiable inv = new WrapperChainedItemHandler(this.topItemHandler,
|
||||
this.bottomItemHandler, this.sideItemHandler);
|
||||
|
||||
public InscriberBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
|
||||
this.getProxy().setValidSides(EnumSet.noneOf(Direction.class));
|
||||
this.setInternalMaxPower(1600);
|
||||
this.getProxy().setIdlePowerUsage(0);
|
||||
this.settings = new ConfigManager(this);
|
||||
|
||||
final ITileDefinition inscriberDefinition = AEApi.instance().definitions().blocks().inscriber();
|
||||
this.upgrades = new DefinitionUpgradeInventory(inscriberDefinition, this, this.getUpgradeSlots());
|
||||
|
||||
this.sideItemHandler.setMaxStackSize(1, 64);
|
||||
|
||||
final IAEItemFilter filter = new ItemHandlerFilter();
|
||||
this.topItemHandlerExtern = new WrapperFilteredItemHandler(this.topItemHandler, filter);
|
||||
this.bottomItemHandlerExtern = new WrapperFilteredItemHandler(this.bottomItemHandler, filter);
|
||||
this.sideItemHandlerExtern = new WrapperFilteredItemHandler(this.sideItemHandler, filter);
|
||||
}
|
||||
|
||||
private int getUpgradeSlots() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AECableType getCableConnectionType(final AEPartLocation dir) {
|
||||
return AECableType.COVERED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag toTag(final CompoundTag data) {
|
||||
super.toTag(data);
|
||||
this.upgrades.writeToNBT(data, "upgrades");
|
||||
this.settings.writeToNBT(data);
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromTag(BlockState state, final CompoundTag data) {
|
||||
super.fromTag(state, data);
|
||||
this.upgrades.readFromNBT(data, "upgrades");
|
||||
this.settings.readFromNBT(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean readFromStream(final PacketByteBuf data) throws IOException {
|
||||
final boolean c = super.readFromStream(data);
|
||||
final int slot = data.readByte();
|
||||
|
||||
final boolean oldSmash = this.isSmash();
|
||||
final boolean newSmash = (slot & 64) == 64;
|
||||
|
||||
if (oldSmash != newSmash && newSmash) {
|
||||
this.setSmash(true);
|
||||
this.setClientStart(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
for (int num = 0; num < this.inv.getSlots(); num++) {
|
||||
if ((slot & (1 << num)) > 0) {
|
||||
this.inv.setStackInSlot(num, AEItemStack.fromPacket(data).createItemStack());
|
||||
} else {
|
||||
this.inv.setStackInSlot(num, ItemStack.EMPTY);
|
||||
}
|
||||
}
|
||||
this.cachedTask = null;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeToStream(final PacketByteBuf data) throws IOException {
|
||||
super.writeToStream(data);
|
||||
int slot = this.isSmash() ? 64 : 0;
|
||||
|
||||
for (int num = 0; num < this.inv.getSlots(); num++) {
|
||||
if (!this.inv.getStackInSlot(num).isEmpty()) {
|
||||
slot |= (1 << num);
|
||||
}
|
||||
}
|
||||
|
||||
data.writeByte(slot);
|
||||
for (int num = 0; num < this.inv.getSlots(); num++) {
|
||||
if ((slot & (1 << num)) > 0) {
|
||||
final AEItemStack st = AEItemStack.fromItemStack(this.inv.getStackInSlot(num));
|
||||
st.writeToPacket(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOrientation(final Direction inForward, final Direction inUp) {
|
||||
super.setOrientation(inForward, inUp);
|
||||
this.getProxy().setValidSides(EnumSet.complementOf(EnumSet.of(this.getForward())));
|
||||
this.setPowerSides(EnumSet.complementOf(EnumSet.of(this.getForward())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getDrops(final World w, final BlockPos pos, final List<ItemStack> drops) {
|
||||
super.getDrops(w, pos, drops);
|
||||
|
||||
for (int h = 0; h < this.upgrades.getSlotCount(); h++) {
|
||||
final ItemStack is = this.upgrades.getInvStack(h);
|
||||
if (!is.isEmpty()) {
|
||||
drops.add(is);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FixedItemInv getInternalInventory() {
|
||||
return this.inv;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeInventory(final FixedItemInv inv, final int slot, final InvOperation mc,
|
||||
final ItemStack removed, final ItemStack added) {
|
||||
try {
|
||||
if (slot == 0) {
|
||||
this.setProcessingTime(0);
|
||||
}
|
||||
|
||||
if (!this.isSmash()) {
|
||||
this.markForUpdate();
|
||||
}
|
||||
|
||||
this.cachedTask = null;
|
||||
this.getProxy().getTick().wakeDevice(this.getProxy().getNode());
|
||||
} catch (final GridAccessException e) {
|
||||
// :P
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// @Override
|
||||
@Override
|
||||
public TickingRequest getTickingRequest(final IGridNode node) {
|
||||
return new TickingRequest(TickRates.Inscriber.getMin(), TickRates.Inscriber.getMax(), !this.hasWork(), false);
|
||||
}
|
||||
|
||||
private boolean hasWork() {
|
||||
if (this.getTask() != null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
this.setProcessingTime(0);
|
||||
return this.isSmash();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public InscriberRecipe getTask() {
|
||||
if (this.cachedTask == null && world != null) {
|
||||
ItemStack input = this.sideItemHandler.getInvStack(0);
|
||||
ItemStack plateA = this.topItemHandler.getInvStack(0);
|
||||
ItemStack plateB = this.bottomItemHandler.getInvStack(0);
|
||||
if (input.isEmpty()) {
|
||||
return null; // No input to handle
|
||||
}
|
||||
|
||||
// If the player somehow managed to insert more than one item, we bail here
|
||||
if (input.getCount() > 1 || plateA.getCount() > 1 || plateB.getCount() > 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
this.cachedTask = InscriberRecipes.findRecipe(world, input, plateA, plateB, true);
|
||||
}
|
||||
return this.cachedTask;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickRateModulation tickingRequest(final IGridNode node, final int ticksSinceLastCall) {
|
||||
if (this.isSmash()) {
|
||||
this.finalStep++;
|
||||
if (this.finalStep == 8) {
|
||||
final InscriberRecipe out = this.getTask();
|
||||
if (out != null) {
|
||||
final ItemStack outputCopy = out.getOutput().copy();
|
||||
|
||||
if (this.sideItemHandler.insertItem(1, outputCopy, false).isEmpty()) {
|
||||
this.setProcessingTime(0);
|
||||
if (out.getProcessType() == InscriberProcessType.PRESS) {
|
||||
this.topItemHandler.setInvStack(0, ItemStack.EMPTY);
|
||||
this.bottomItemHandler.setInvStack(0, ItemStack.EMPTY);
|
||||
}
|
||||
this.sideItemHandler.setInvStack(0, ItemStack.EMPTY);
|
||||
}
|
||||
}
|
||||
this.saveChanges();
|
||||
} else if (this.finalStep == 16) {
|
||||
this.finalStep = 0;
|
||||
this.setSmash(false);
|
||||
this.markForUpdate();
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
final IEnergyGrid eg = this.getProxy().getEnergy();
|
||||
IEnergySource src = this;
|
||||
|
||||
// Base 1, increase by 1 for each card
|
||||
final int speedFactor = 1 + this.upgrades.getInstalledUpgrades(Upgrades.SPEED);
|
||||
final int powerConsumption = 10 * speedFactor;
|
||||
final double powerThreshold = powerConsumption - 0.01;
|
||||
double powerReq = this.extractAEPower(powerConsumption, Actionable.SIMULATE, PowerMultiplier.CONFIG);
|
||||
|
||||
if (powerReq <= powerThreshold) {
|
||||
src = eg;
|
||||
powerReq = eg.extractAEPower(powerConsumption, Actionable.SIMULATE, PowerMultiplier.CONFIG);
|
||||
}
|
||||
|
||||
if (powerReq > powerThreshold) {
|
||||
src.extractAEPower(powerConsumption, Actionable.MODULATE, PowerMultiplier.CONFIG);
|
||||
|
||||
if (this.getProcessingTime() == 0) {
|
||||
this.setProcessingTime(this.getProcessingTime() + speedFactor);
|
||||
} else {
|
||||
this.setProcessingTime(this.getProcessingTime() + ticksSinceLastCall * speedFactor);
|
||||
}
|
||||
}
|
||||
} catch (final GridAccessException e) {
|
||||
// :P
|
||||
}
|
||||
|
||||
if (this.getProcessingTime() > this.getMaxProcessingTime()) {
|
||||
this.setProcessingTime(this.getMaxProcessingTime());
|
||||
final InscriberRecipe out = this.getTask();
|
||||
if (out != null) {
|
||||
final ItemStack outputCopy = out.getOutput().copy();
|
||||
if (this.sideItemHandler.insertItem(1, outputCopy, true).isEmpty()) {
|
||||
this.setSmash(true);
|
||||
this.finalStep = 0;
|
||||
this.markForUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this.hasWork() ? TickRateModulation.URGENT : TickRateModulation.SLEEP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IConfigManager getConfigManager() {
|
||||
return this.settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FixedItemInv getInventoryByName(final String name) {
|
||||
if (name.equals("inv")) {
|
||||
return this.getInternalInventory();
|
||||
}
|
||||
|
||||
if (name.equals("upgrades")) {
|
||||
return this.upgrades;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FixedItemInv getItemHandlerForSide(@Nonnull Direction facing) {
|
||||
if (facing == this.getUp()) {
|
||||
return this.topItemHandlerExtern;
|
||||
} else if (facing == this.getUp().getOpposite()) {
|
||||
return this.bottomItemHandlerExtern;
|
||||
} else {
|
||||
return this.sideItemHandlerExtern;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInstalledUpgrades(final Upgrades u) {
|
||||
return this.upgrades.getInstalledUpgrades(u);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSetting(final IConfigManager manager, final Settings settingName, final Enum<?> newValue) {
|
||||
}
|
||||
|
||||
public long getClientStart() {
|
||||
return this.clientStart;
|
||||
}
|
||||
|
||||
private void setClientStart(final long clientStart) {
|
||||
this.clientStart = clientStart;
|
||||
}
|
||||
|
||||
public boolean isSmash() {
|
||||
return this.smash;
|
||||
}
|
||||
|
||||
public void setSmash(final boolean smash) {
|
||||
this.smash = smash;
|
||||
}
|
||||
|
||||
public int getMaxProcessingTime() {
|
||||
return this.maxProcessingTime;
|
||||
}
|
||||
|
||||
public int getProcessingTime() {
|
||||
return this.processingTime;
|
||||
}
|
||||
|
||||
private void setProcessingTime(final int processingTime) {
|
||||
this.processingTime = processingTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is an item handler that exposes the inscribers inventory while providing
|
||||
* simulation capabilities that do not reset the progress if there's already an
|
||||
* item in a slot. Previously, the progress of the inscriber was reset when
|
||||
* another mod attempted insertion of items when there were already items in the
|
||||
* slot.
|
||||
*/
|
||||
private class ItemHandlerFilter implements IAEItemFilter {
|
||||
@Override
|
||||
public boolean allowExtract(FixedItemInv inv, int slot, int amount) {
|
||||
if (InscriberBlockEntity.this.isSmash()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return inv == InscriberBlockEntity.this.topItemHandler || inv == InscriberBlockEntity.this.bottomItemHandler
|
||||
|| slot == 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowInsert(FixedItemInv inv, int slot, ItemStack stack) {
|
||||
// output slot
|
||||
if (slot == 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (InscriberBlockEntity.this.isSmash()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (inv == InscriberBlockEntity.this.topItemHandler || inv == InscriberBlockEntity.this.bottomItemHandler) {
|
||||
if (AEApi.instance().definitions().materials().namePress().isSameAs(stack)) {
|
||||
return true;
|
||||
}
|
||||
return InscriberRecipes.isValidOptionalIngredient(getWorld(), stack);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,136 +0,0 @@
|
||||
package appeng.tile.misc;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import net.minecraft.inventory.Inventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.recipe.Ingredient;
|
||||
import net.minecraft.recipe.Recipe;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.text.LiteralText;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.definitions.IComparableDefinition;
|
||||
import appeng.api.features.InscriberProcessType;
|
||||
import appeng.core.AppEng;
|
||||
import appeng.items.materials.MaterialItem;
|
||||
import appeng.recipes.handlers.InscriberRecipe;
|
||||
|
||||
/**
|
||||
* This class indexes all inscriber recipes to find valid inputs for the top and
|
||||
* bottom optional slots. This speeds up checks whether inputs for those two
|
||||
* slots are valid.
|
||||
*/
|
||||
public final class InscriberRecipes {
|
||||
|
||||
public static final Identifier NAMEPLATE_RECIPE_ID = new Identifier(AppEng.MOD_ID, "nameplate");
|
||||
|
||||
private InscriberRecipes() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an unmodifiable view of all registered inscriber recipes.
|
||||
*/
|
||||
public static Iterable<InscriberRecipe> getRecipes(World world) {
|
||||
Collection<Recipe<Inventory>> unfilteredRecipes = world.getRecipeManager().getRecipes(InscriberRecipe.TYPE)
|
||||
.values();
|
||||
return Iterables.filter(unfilteredRecipes, InscriberRecipe.class);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static InscriberRecipe findRecipe(World world, ItemStack input, ItemStack plateA, ItemStack plateB,
|
||||
boolean supportNamePress) {
|
||||
if (supportNamePress) {
|
||||
IComparableDefinition namePress = AEApi.instance().definitions().materials().namePress();
|
||||
boolean isNameA = namePress.isSameAs(plateA);
|
||||
boolean isNameB = namePress.isSameAs(plateB);
|
||||
|
||||
if ((isNameA && isNameB) || isNameA && plateB.isEmpty()) {
|
||||
return makeNamePressRecipe(input, plateA, plateB);
|
||||
} else if (plateA.isEmpty() && isNameB) {
|
||||
return makeNamePressRecipe(input, plateB, plateA);
|
||||
}
|
||||
}
|
||||
|
||||
for (final InscriberRecipe recipe : getRecipes(world)) {
|
||||
// The recipe can be flipped at will
|
||||
final boolean matchA = recipe.getTopOptional().test(plateA) && recipe.getBottomOptional().test(plateB);
|
||||
final boolean matchB = recipe.getTopOptional().test(plateB) && recipe.getBottomOptional().test(plateA);
|
||||
|
||||
if (matchA || matchB) {
|
||||
if (recipe.getMiddleInput().test(input)) {
|
||||
return recipe;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static InscriberRecipe makeNamePressRecipe(ItemStack input, ItemStack plateA, ItemStack plateB) {
|
||||
String name = "";
|
||||
|
||||
if (!plateA.isEmpty()) {
|
||||
final CompoundTag tag = plateA.getOrCreateTag();
|
||||
name += tag.getString(MaterialItem.TAG_INSCRIBE_NAME);
|
||||
}
|
||||
|
||||
if (!plateB.isEmpty()) {
|
||||
final CompoundTag tag = plateB.getOrCreateTag();
|
||||
name += " " + tag.getString(MaterialItem.TAG_INSCRIBE_NAME);
|
||||
}
|
||||
|
||||
final Ingredient startingItem = Ingredient.fromStacks(input.copy());
|
||||
final ItemStack renamedItem = input.copy();
|
||||
|
||||
if (!name.isEmpty()) {
|
||||
renamedItem.setDisplayName(new LiteralText(name));
|
||||
} else {
|
||||
renamedItem.setDisplayName(null);
|
||||
}
|
||||
|
||||
final InscriberProcessType type = InscriberProcessType.INSCRIBE;
|
||||
|
||||
return new InscriberRecipe(NAMEPLATE_RECIPE_ID, "", startingItem, renamedItem,
|
||||
plateA.isEmpty() ? Ingredient.EMPTY : Ingredient.fromStacks(plateA),
|
||||
plateB.isEmpty() ? Ingredient.EMPTY : Ingredient.fromStacks(plateB), type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if there is an inscriber recipe that supports the given combination of
|
||||
* top/bottom presses. Both the given combination and the reverse will be
|
||||
* searched.
|
||||
*/
|
||||
public static boolean isValidOptionalIngredientCombination(World world, ItemStack pressA, ItemStack pressB) {
|
||||
for (InscriberRecipe recipe : getRecipes(world)) {
|
||||
if (recipe.getTopOptional().test(pressA) && recipe.getBottomOptional().test(pressB)
|
||||
|| recipe.getTopOptional().test(pressB) && recipe.getBottomOptional().test(pressA)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if there is an inscriber recipe that would use the given item stack as
|
||||
* an optional ingredient. Bottom and top can be used interchangeably here,
|
||||
* because the inscriber will flip the recipe if needed.
|
||||
*/
|
||||
public static boolean isValidOptionalIngredient(World world, ItemStack is) {
|
||||
for (InscriberRecipe recipe : getRecipes(world)) {
|
||||
if (recipe.getTopOptional().test(is) || recipe.getBottomOptional().test(is)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,317 +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.tile.misc;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.inventory.CraftingInventory;
|
||||
import net.minecraft.screen.ScreenHandlerType;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import alexiil.mc.lib.attributes.item.FixedItemInv;
|
||||
|
||||
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.storage.data.IAEItemStack;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
import appeng.api.util.DimensionalCoord;
|
||||
import appeng.api.util.IConfigManager;
|
||||
import appeng.container.implementations.InterfaceContainer;
|
||||
import appeng.helpers.DualityInterface;
|
||||
import appeng.helpers.IInterfaceHost;
|
||||
import appeng.helpers.IPriorityHost;
|
||||
import appeng.tile.grid.AENetworkInvBlockEntity;
|
||||
import appeng.util.Platform;
|
||||
import appeng.util.inv.IInventoryDestination;
|
||||
import appeng.util.inv.InvOperation;
|
||||
|
||||
public class InterfaceBlockEntity extends AENetworkInvBlockEntity
|
||||
implements IGridTickable, IInventoryDestination, IInterfaceHost, IPriorityHost {
|
||||
|
||||
private final DualityInterface duality = new DualityInterface(this.getProxy(), this);
|
||||
|
||||
// Indicates that this interface has no specific direction set
|
||||
private boolean omniDirectional = true;
|
||||
|
||||
public InterfaceBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void stateChange(final MENetworkChannelsChanged c) {
|
||||
this.duality.notifyNeighbors();
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void stateChange(final MENetworkPowerStatusChange c) {
|
||||
this.duality.notifyNeighbors();
|
||||
}
|
||||
|
||||
public void setSide(final Direction facing) {
|
||||
if (isClient()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Direction newForward = facing;
|
||||
|
||||
if (!this.omniDirectional && this.getForward() == facing.getOpposite()) {
|
||||
newForward = facing;
|
||||
} else if (!this.omniDirectional
|
||||
&& (this.getForward() == facing || this.getForward() == facing.getOpposite())) {
|
||||
this.omniDirectional = true;
|
||||
} else if (this.omniDirectional) {
|
||||
newForward = facing.getOpposite();
|
||||
this.omniDirectional = false;
|
||||
} else {
|
||||
newForward = Platform.rotateAround(this.getForward(), facing);
|
||||
}
|
||||
|
||||
if (this.omniDirectional) {
|
||||
this.setOrientation(Direction.NORTH, Direction.UP);
|
||||
} else {
|
||||
Direction newUp = Direction.UP;
|
||||
if (newForward == Direction.UP || newForward == Direction.DOWN) {
|
||||
newUp = Direction.NORTH;
|
||||
}
|
||||
this.setOrientation(newForward, newUp);
|
||||
}
|
||||
|
||||
this.configureNodeSides();
|
||||
this.markForUpdate();
|
||||
this.saveChanges();
|
||||
}
|
||||
|
||||
private void configureNodeSides() {
|
||||
if (this.omniDirectional) {
|
||||
this.getProxy().setValidSides(EnumSet.allOf(Direction.class));
|
||||
} else {
|
||||
this.getProxy().setValidSides(EnumSet.complementOf(EnumSet.of(this.getForward())));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getDrops(final World w, final BlockPos pos, final List<ItemStack> drops) {
|
||||
this.duality.addDrops(drops);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void gridChanged() {
|
||||
this.duality.gridChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReady() {
|
||||
this.configureNodeSides();
|
||||
|
||||
super.onReady();
|
||||
this.duality.initialize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag toTag(final CompoundTag data) {
|
||||
super.toTag(data);
|
||||
data.putBoolean("omniDirectional", this.omniDirectional);
|
||||
this.duality.writeToNBT(data);
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromTag(BlockState state, final CompoundTag data) {
|
||||
super.fromTag(state, data);
|
||||
this.omniDirectional = data.getBoolean("omniDirectional");
|
||||
|
||||
this.duality.readFromNBT(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean readFromStream(final PacketByteBuf data) throws IOException {
|
||||
final boolean c = super.readFromStream(data);
|
||||
boolean oldOmniDirectional = this.omniDirectional;
|
||||
this.omniDirectional = data.readBoolean();
|
||||
return oldOmniDirectional != this.omniDirectional || c;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeToStream(final PacketByteBuf data) throws IOException {
|
||||
super.writeToStream(data);
|
||||
data.writeBoolean(this.omniDirectional);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AECableType getCableConnectionType(final AEPartLocation dir) {
|
||||
return this.duality.getCableConnectionType(dir);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DimensionalCoord getLocation() {
|
||||
return this.duality.getLocation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canInsert(final ItemStack stack) {
|
||||
return this.duality.canInsert(stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FixedItemInv getInventoryByName(final String name) {
|
||||
return this.duality.getInventoryByName(name);
|
||||
}
|
||||
|
||||
@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 FixedItemInv getInternalInventory() {
|
||||
return this.duality.getInternalInventory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeInventory(final FixedItemInv inv, final int slot, final InvOperation mc,
|
||||
final ItemStack removed, final ItemStack added) {
|
||||
this.duality.onChangeInventory(inv, slot, mc, removed, added);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DualityInterface getInterfaceDuality() {
|
||||
return this.duality;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumSet<Direction> getTargets() {
|
||||
if (this.omniDirectional) {
|
||||
return EnumSet.allOf(Direction.class);
|
||||
}
|
||||
return EnumSet.of(this.getForward());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntity getBlockEntity() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IConfigManager getConfigManager() {
|
||||
return this.duality.getConfigManager();
|
||||
}
|
||||
|
||||
@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 int getInstalledUpgrades(final Upgrades u) {
|
||||
return this.duality.getInstalledUpgrades(u);
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if this interface is omni-directional.
|
||||
*/
|
||||
public boolean isOmniDirectional() {
|
||||
return this.omniDirectional;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> LazyOptional<T> getCapability(Capability<T> capability, @Nullable Direction facing) {
|
||||
LazyOptional<T> result = this.duality.getCapability(capability, facing);
|
||||
if (result.isPresent()) {
|
||||
return result;
|
||||
}
|
||||
return super.getCapability(capability, facing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemStackRepresentation() {
|
||||
return AEApi.instance().definitions().blocks().iface().maybeStack(1).orElse(ItemStack.EMPTY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScreenHandlerType<?> getContainerType() {
|
||||
return InterfaceContainer.TYPE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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.tile.misc;
|
||||
|
||||
import net.minecraft.util.Tickable;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
|
||||
import appeng.tile.AEBaseBlockEntity;
|
||||
import appeng.util.Platform;
|
||||
|
||||
public class LightDetectorBlockEntity extends AEBaseBlockEntity implements Tickable {
|
||||
|
||||
private int lastCheck = 30;
|
||||
private int lastLight = 0;
|
||||
|
||||
public LightDetectorBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
}
|
||||
|
||||
public boolean isReady() {
|
||||
return this.lastLight > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
this.lastCheck++;
|
||||
if (this.lastCheck > 30) {
|
||||
this.lastCheck = 0;
|
||||
this.updateLight();
|
||||
}
|
||||
}
|
||||
|
||||
public void updateLight() {
|
||||
final int val = this.world.getLightLevel(this.pos);
|
||||
|
||||
if (this.lastLight != val) {
|
||||
this.lastLight = val;
|
||||
Platform.notifyBlocksOfNeighbors(this.world, this.pos);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeRotated() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,256 +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.tile.misc;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import io.netty.buffer.Unpooled;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.LightType;
|
||||
|
||||
import net.minecraftforge.client.model.data.ModelDataMap;
|
||||
import net.minecraftforge.client.model.data.ModelProperty;
|
||||
|
||||
import appeng.api.util.AEColor;
|
||||
import appeng.block.paint.PaintSplotches;
|
||||
import appeng.helpers.Splotch;
|
||||
import appeng.items.misc.PaintBallItem;
|
||||
import appeng.tile.AEBaseBlockEntity;
|
||||
|
||||
public class PaintSplotchesBlockEntity extends AEBaseBlockEntity {
|
||||
|
||||
public static final ModelProperty<PaintSplotches> SPLOTCHES = new ModelProperty<>();
|
||||
|
||||
private static final int LIGHT_PER_DOT = 12;
|
||||
|
||||
private int isLit = 0;
|
||||
private List<Splotch> dots = null;
|
||||
|
||||
public PaintSplotchesBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeRotated() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag toTag(final CompoundTag data) {
|
||||
super.toTag(data);
|
||||
final PacketByteBuf myDat = new PacketByteBuf(Unpooled.buffer());
|
||||
this.writeBuffer(myDat);
|
||||
if (myDat.hasArray()) {
|
||||
data.putByteArray("dots", myDat.array());
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
private void writeBuffer(final PacketByteBuf out) {
|
||||
if (this.dots == null) {
|
||||
out.writeByte(0);
|
||||
return;
|
||||
}
|
||||
|
||||
out.writeByte(this.dots.size());
|
||||
|
||||
for (final Splotch s : this.dots) {
|
||||
s.writeToStream(out);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromTag(BlockState state, final CompoundTag data) {
|
||||
super.fromTag(state, data);
|
||||
if (data.contains("dots")) {
|
||||
this.readBuffer(new PacketByteBuf(Unpooled.copiedBuffer(data.getByteArray("dots"))));
|
||||
}
|
||||
}
|
||||
|
||||
private void readBuffer(final PacketByteBuf in) {
|
||||
final byte howMany = in.readByte();
|
||||
|
||||
if (howMany == 0) {
|
||||
this.isLit = 0;
|
||||
this.dots = null;
|
||||
return;
|
||||
}
|
||||
|
||||
this.dots = new ArrayList(howMany);
|
||||
for (int x = 0; x < howMany; x++) {
|
||||
this.dots.add(new Splotch(in));
|
||||
}
|
||||
|
||||
this.isLit = 0;
|
||||
for (final Splotch s : this.dots) {
|
||||
if (s.isLumen()) {
|
||||
this.isLit += LIGHT_PER_DOT;
|
||||
}
|
||||
}
|
||||
|
||||
this.maxLit();
|
||||
}
|
||||
|
||||
private void maxLit() {
|
||||
if (this.isLit > 14) {
|
||||
this.isLit = 14;
|
||||
}
|
||||
|
||||
if (this.world != null) {
|
||||
this.world.getLightFor(LightType.BLOCK, this.pos);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeToStream(final PacketByteBuf data) throws IOException {
|
||||
super.writeToStream(data);
|
||||
this.writeBuffer(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean readFromStream(final PacketByteBuf data) throws IOException {
|
||||
super.readFromStream(data);
|
||||
this.readBuffer(data);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void neighborUpdate() {
|
||||
if (this.dots == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (final Direction side : Direction.values()) {
|
||||
if (!this.isSideValid(side)) {
|
||||
this.removeSide(side);
|
||||
}
|
||||
}
|
||||
|
||||
this.updateData();
|
||||
}
|
||||
|
||||
public boolean isSideValid(final Direction side) {
|
||||
final BlockPos p = this.pos.offset(side);
|
||||
final BlockState blk = this.world.getBlockState(p);
|
||||
return blk.isSideSolidFullSquare(world, p, side.getOpposite());
|
||||
}
|
||||
|
||||
private void removeSide(final Direction side) {
|
||||
final Iterator<Splotch> i = this.dots.iterator();
|
||||
while (i.hasNext()) {
|
||||
final Splotch s = i.next();
|
||||
if (s.getSide() == side) {
|
||||
i.remove();
|
||||
}
|
||||
}
|
||||
|
||||
this.markForUpdate();
|
||||
this.saveChanges();
|
||||
}
|
||||
|
||||
private void updateData() {
|
||||
this.isLit = 0;
|
||||
for (final Splotch s : this.dots) {
|
||||
if (s.isLumen()) {
|
||||
this.isLit += LIGHT_PER_DOT;
|
||||
}
|
||||
}
|
||||
|
||||
this.maxLit();
|
||||
|
||||
if (this.dots.isEmpty()) {
|
||||
this.dots = null;
|
||||
}
|
||||
|
||||
if (this.dots == null) {
|
||||
this.world.removeBlock(this.pos, false);
|
||||
}
|
||||
}
|
||||
|
||||
public void cleanSide(final Direction side) {
|
||||
if (this.dots == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.removeSide(side);
|
||||
|
||||
this.updateData();
|
||||
}
|
||||
|
||||
public int getLightLevel() {
|
||||
return this.isLit;
|
||||
}
|
||||
|
||||
public void addBlot(final ItemStack type, final Direction side, final Vec3d hitVec) {
|
||||
final BlockPos p = this.pos.offset(side);
|
||||
|
||||
final BlockState blk = this.world.getBlockState(p);
|
||||
if (blk.isSideSolidFullSquare(this.world, p, side.getOpposite())) {
|
||||
final PaintBallItem ipb = (PaintBallItem) type.getItem();
|
||||
|
||||
final AEColor col = ipb.getColor();
|
||||
final boolean lit = ipb.isLumen();
|
||||
|
||||
if (this.dots == null) {
|
||||
this.dots = new ArrayList<>();
|
||||
}
|
||||
|
||||
if (this.dots.size() > 20) {
|
||||
this.dots.remove(0);
|
||||
}
|
||||
|
||||
this.dots.add(new Splotch(col, lit, side, hitVec));
|
||||
if (lit) {
|
||||
this.isLit += LIGHT_PER_DOT;
|
||||
}
|
||||
|
||||
this.maxLit();
|
||||
this.markForUpdate();
|
||||
this.saveChanges();
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<Splotch> getDots() {
|
||||
if (this.dots == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return this.dots;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getRenderAttachmentData() {
|
||||
return new PaintSplotches(getDots());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,105 +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.tile.misc;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.EnumSet;
|
||||
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.util.math.Direction;
|
||||
|
||||
import appeng.api.implementations.IPowerChannelState;
|
||||
import appeng.api.implementations.tiles.ICrystalGrowthAccelerator;
|
||||
import appeng.api.networking.events.MENetworkEventSubscribe;
|
||||
import appeng.api.networking.events.MENetworkPowerStatusChange;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
import appeng.me.GridAccessException;
|
||||
import appeng.tile.grid.AENetworkBlockEntity;
|
||||
import appeng.util.Platform;
|
||||
|
||||
public class QuartzGrowthAcceleratorBlockEntity extends AENetworkBlockEntity
|
||||
implements IPowerChannelState, ICrystalGrowthAccelerator {
|
||||
|
||||
private boolean hasPower = false;
|
||||
|
||||
public QuartzGrowthAcceleratorBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
this.getProxy().setValidSides(EnumSet.noneOf(Direction.class));
|
||||
this.getProxy().setFlags();
|
||||
this.getProxy().setIdlePowerUsage(8);
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void onPower(final MENetworkPowerStatusChange ch) {
|
||||
this.markForUpdate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AECableType getCableConnectionType(final AEPartLocation dir) {
|
||||
return AECableType.COVERED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean readFromStream(final PacketByteBuf data) throws IOException {
|
||||
final boolean c = super.readFromStream(data);
|
||||
final boolean hadPower = this.isPowered();
|
||||
this.setPowered(data.readBoolean());
|
||||
return this.isPowered() != hadPower || c;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToStream(final PacketByteBuf data) throws IOException {
|
||||
super.writeToStream(data);
|
||||
try {
|
||||
data.writeBoolean(this.getProxy().getEnergy().isNetworkPowered());
|
||||
} catch (final GridAccessException e) {
|
||||
data.writeBoolean(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOrientation(final Direction inForward, final Direction inUp) {
|
||||
super.setOrientation(inForward, inUp);
|
||||
this.getProxy().setValidSides(EnumSet.of(this.getUp(), this.getUp().getOpposite()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPowered() {
|
||||
if (Platform.isServer()) {
|
||||
try {
|
||||
return this.getProxy().getEnergy().isNetworkPowered();
|
||||
} catch (final GridAccessException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return this.hasPower;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
return this.isPowered();
|
||||
}
|
||||
|
||||
private void setPowered(final boolean hasPower) {
|
||||
this.hasPower = hasPower;
|
||||
}
|
||||
}
|
||||
@@ -1,336 +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.tile.misc;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import alexiil.mc.lib.attributes.item.FixedItemInv;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.INBT;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.config.SecurityPermissions;
|
||||
import appeng.api.config.Settings;
|
||||
import appeng.api.config.SortDir;
|
||||
import appeng.api.config.SortOrder;
|
||||
import appeng.api.config.ViewItems;
|
||||
import appeng.api.events.LocatableEventAnnounce;
|
||||
import appeng.api.events.LocatableEventAnnounce.LocatableEvent;
|
||||
import appeng.api.features.ILocatable;
|
||||
import appeng.api.features.IPlayerRegistry;
|
||||
import appeng.api.implementations.items.IBiometricCard;
|
||||
import appeng.api.implementations.tiles.IColorableTile;
|
||||
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.api.networking.events.MENetworkSecurityChange;
|
||||
import appeng.api.networking.security.ISecurityProvider;
|
||||
import appeng.api.storage.IMEInventoryHandler;
|
||||
import appeng.api.storage.IMEMonitor;
|
||||
import appeng.api.storage.IStorageChannel;
|
||||
import appeng.api.storage.ITerminalHost;
|
||||
import appeng.api.storage.channels.IItemStorageChannel;
|
||||
import appeng.api.storage.data.IAEItemStack;
|
||||
import appeng.api.storage.data.IAEStack;
|
||||
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.PlayerSecurityWrapper;
|
||||
import appeng.me.GridAccessException;
|
||||
import appeng.me.helpers.MEMonitorHandler;
|
||||
import appeng.me.storage.SecurityStationInventory;
|
||||
import appeng.tile.grid.AENetworkBlockEntity;
|
||||
import appeng.tile.inventory.AppEngInternalInventory;
|
||||
import appeng.util.ConfigManager;
|
||||
import appeng.util.IConfigManagerHost;
|
||||
import appeng.util.Platform;
|
||||
import appeng.util.helpers.ItemHandlerUtil;
|
||||
import appeng.util.inv.IAEAppEngInventory;
|
||||
import appeng.util.inv.InvOperation;
|
||||
import appeng.util.item.AEItemStack;
|
||||
|
||||
public class SecurityStationBlockEntity extends AENetworkBlockEntity implements ITerminalHost, IAEAppEngInventory,
|
||||
ILocatable, IConfigManagerHost, ISecurityProvider, IColorableTile {
|
||||
|
||||
private static int difference = 0;
|
||||
private final AppEngInternalInventory configSlot = new AppEngInternalInventory(this, 1);
|
||||
private final IConfigManager cm = new ConfigManager(this);
|
||||
private final SecurityStationInventory inventory = new SecurityStationInventory(this);
|
||||
private final MEMonitorHandler<IAEItemStack> securityMonitor = new MEMonitorHandler<>(this.inventory);
|
||||
private long securityKey;
|
||||
private AEColor paintedColor = AEColor.TRANSPARENT;
|
||||
private boolean isActive = false;
|
||||
|
||||
public SecurityStationBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
this.getProxy().setFlags(GridFlags.REQUIRE_CHANNEL);
|
||||
this.getProxy().setIdlePowerUsage(2.0);
|
||||
difference++;
|
||||
|
||||
this.securityKey = System.currentTimeMillis() * 10 + difference;
|
||||
if (difference > 10) {
|
||||
difference = 0;
|
||||
}
|
||||
|
||||
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 onChangeInventory(final FixedItemInv inv, final int slot, final InvOperation mc,
|
||||
final ItemStack removedStack, final ItemStack newStack) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getDrops(final World w, final BlockPos pos, final List<ItemStack> drops) {
|
||||
if (!ItemHandlerUtil.isEmpty(this.getConfigSlot())) {
|
||||
drops.add(this.getConfigSlot().getInvStack(0));
|
||||
}
|
||||
|
||||
for (final IAEItemStack ais : this.inventory.getStoredItems()) {
|
||||
drops.add(ais.createItemStack());
|
||||
}
|
||||
}
|
||||
|
||||
IMEInventoryHandler<IAEItemStack> getSecurityInventory() {
|
||||
return this.inventory;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean readFromStream(final PacketByteBuf data) throws IOException {
|
||||
final boolean c = super.readFromStream(data);
|
||||
final boolean wasActive = this.isActive;
|
||||
this.isActive = data.readBoolean();
|
||||
|
||||
final AEColor oldPaintedColor = this.paintedColor;
|
||||
this.paintedColor = AEColor.values()[data.readByte()];
|
||||
|
||||
return oldPaintedColor != this.paintedColor || wasActive != this.isActive || c;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeToStream(final PacketByteBuf data) throws IOException {
|
||||
super.writeToStream(data);
|
||||
data.writeBoolean(this.getProxy().isActive());
|
||||
data.writeByte(this.paintedColor.ordinal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag toTag(final CompoundTag data) {
|
||||
super.toTag(data);
|
||||
this.cm.writeToNBT(data);
|
||||
data.putByte("paintedColor", (byte) this.paintedColor.ordinal());
|
||||
|
||||
data.putLong("securityKey", this.securityKey);
|
||||
this.getConfigSlot().writeToNBT(data, "config");
|
||||
|
||||
final CompoundTag storedItems = new CompoundTag();
|
||||
|
||||
int offset = 0;
|
||||
for (final IAEItemStack ais : this.inventory.getStoredItems()) {
|
||||
final CompoundTag it = new CompoundTag();
|
||||
ais.createItemStack().toTag(it);
|
||||
storedItems.put(String.valueOf(offset), it);
|
||||
offset++;
|
||||
}
|
||||
|
||||
data.put("storedItems", storedItems);
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromTag(BlockState state, final CompoundTag data) {
|
||||
super.fromTag(state, data);
|
||||
this.cm.readFromNBT(data);
|
||||
if (data.contains("paintedColor")) {
|
||||
this.paintedColor = AEColor.values()[data.getByte("paintedColor")];
|
||||
}
|
||||
|
||||
this.securityKey = data.getLong("securityKey");
|
||||
this.getConfigSlot().readFromNBT(data, "config");
|
||||
|
||||
final CompoundTag storedItems = data.getCompound("storedItems");
|
||||
for (final Object key : storedItems.getKeys()) {
|
||||
final INBT obj = storedItems.get((String) key);
|
||||
if (obj instanceof CompoundTag) {
|
||||
this.inventory.getStoredItems().add(AEItemStack.fromItemStack(ItemStack.fromTag((CompoundTag) obj)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void inventoryChanged() {
|
||||
try {
|
||||
this.saveChanges();
|
||||
this.getProxy().getGrid().postEvent(new MENetworkSecurityChange());
|
||||
} catch (final GridAccessException e) {
|
||||
// :P
|
||||
}
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void bootUpdate(final MENetworkChannelsChanged changed) {
|
||||
this.markForUpdate();
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void powerUpdate(final MENetworkPowerStatusChange changed) {
|
||||
this.markForUpdate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AECableType getCableConnectionType(final AEPartLocation dir) {
|
||||
return AECableType.SMART;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkUnloaded() {
|
||||
super.onChunkUnloaded();
|
||||
MinecraftForge.EVENT_BUS.post(new LocatableEventAnnounce(this, LocatableEvent.UNREGISTER));
|
||||
this.isActive = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReady() {
|
||||
super.onReady();
|
||||
if (Platform.isServer()) {
|
||||
this.isActive = true;
|
||||
MinecraftForge.EVENT_BUS.post(new LocatableEventAnnounce(this, LocatableEvent.REGISTER));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
super.remove();
|
||||
MinecraftForge.EVENT_BUS.post(new LocatableEventAnnounce(this, LocatableEvent.UNREGISTER));
|
||||
this.isActive = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DimensionalCoord getLocation() {
|
||||
return new DimensionalCoord(this);
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
if (world != null && !world.isClient) {
|
||||
return isPowered();
|
||||
} else {
|
||||
return this.isActive;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends IAEStack<T>> IMEMonitor<T> getInventory(IStorageChannel<T> channel) {
|
||||
if (channel == AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class)) {
|
||||
return (IMEMonitor<T>) this.securityMonitor;
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLocatableSerial() {
|
||||
return this.securityKey;
|
||||
}
|
||||
|
||||
public boolean isPowered() {
|
||||
return this.getProxy().isActive();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IConfigManager getConfigManager() {
|
||||
return this.cm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSetting(final IConfigManager manager, final Settings settingName, final Enum<?> newValue) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSecurityKey() {
|
||||
return this.securityKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readPermissions(final Map<Integer, EnumSet<SecurityPermissions>> playerPerms) {
|
||||
final IPlayerRegistry pr = AEApi.instance().registries().players();
|
||||
|
||||
// read permissions
|
||||
for (final IAEItemStack ais : this.inventory.getStoredItems()) {
|
||||
final ItemStack is = ais.createItemStack();
|
||||
final Item i = is.getItem();
|
||||
if (i instanceof IBiometricCard) {
|
||||
final IBiometricCard bc = (IBiometricCard) i;
|
||||
bc.registerPermissions(new PlayerSecurityWrapper(playerPerms), pr, is);
|
||||
}
|
||||
}
|
||||
|
||||
// make sure thea admin is Boss.
|
||||
playerPerms.put(this.getProxy().getNode().getPlayerID(), EnumSet.allOf(SecurityPermissions.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSecurityEnabled() {
|
||||
return this.isActive && this.getProxy().isActive();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOwner() {
|
||||
return this.getProxy().getNode().getPlayerID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AEColor getColor() {
|
||||
return this.paintedColor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean recolourBlock(final Direction side, final AEColor newPaintedColor, final PlayerEntity who) {
|
||||
if (this.paintedColor == newPaintedColor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.paintedColor = newPaintedColor;
|
||||
this.saveChanges();
|
||||
this.markForUpdate();
|
||||
return true;
|
||||
}
|
||||
|
||||
public AppEngInternalInventory getConfigSlot() {
|
||||
return this.configSlot;
|
||||
}
|
||||
}
|
||||
+5
-4
@@ -16,15 +16,16 @@
|
||||
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
|
||||
*/
|
||||
|
||||
package appeng.tile.networking;
|
||||
package appeng.tile.misc;
|
||||
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
|
||||
public class DenseEnergyCellBlockEntity extends EnergyCellBlockEntity {
|
||||
import appeng.tile.AEBaseBlockEntity;
|
||||
|
||||
public DenseEnergyCellBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
|
||||
public class SkyCompassBlockEntity extends AEBaseBlockEntity {
|
||||
|
||||
public SkyCompassBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
this.setInternalMaxPower(200000 * 8);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,282 +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.tile.misc;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import alexiil.mc.lib.attributes.item.FixedItemInv;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraftforge.common.ForgeHooks;
|
||||
|
||||
import appeng.api.config.Actionable;
|
||||
import appeng.api.networking.IGridNode;
|
||||
import appeng.api.networking.energy.IEnergyGrid;
|
||||
import appeng.api.networking.ticking.IGridTickable;
|
||||
import appeng.api.networking.ticking.TickRateModulation;
|
||||
import appeng.api.networking.ticking.TickingRequest;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
import appeng.api.util.DimensionalCoord;
|
||||
import appeng.core.settings.TickRates;
|
||||
import appeng.me.GridAccessException;
|
||||
import appeng.tile.grid.AENetworkInvBlockEntity;
|
||||
import appeng.tile.inventory.AppEngInternalInventory;
|
||||
import appeng.util.Platform;
|
||||
import appeng.util.inv.InvOperation;
|
||||
import appeng.util.inv.WrapperFilteredItemHandler;
|
||||
import appeng.util.inv.filter.IAEItemFilter;
|
||||
|
||||
public class VibrationChamberBlockEntity extends AENetworkInvBlockEntity implements IGridTickable {
|
||||
public static final double POWER_PER_TICK = 5;
|
||||
public static final int MIN_BURN_SPEED = 20;
|
||||
public static final int MAX_BURN_SPEED = 200;
|
||||
public static final double DILATION_SCALING = 25.0; // x4 ~ 40 AE/t at max
|
||||
private final AppEngInternalInventory inv = new AppEngInternalInventory(this, 1);
|
||||
private final FixedItemInv invExt = new WrapperFilteredItemHandler(this.inv, new FuelSlotFilter());
|
||||
|
||||
private int burnSpeed = 100;
|
||||
private double burnTime = 0;
|
||||
private double maxBurnTime = 0;
|
||||
|
||||
// client side..
|
||||
public boolean isOn;
|
||||
|
||||
public VibrationChamberBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
this.getProxy().setIdlePowerUsage(0);
|
||||
this.getProxy().setFlags();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AECableType getCableConnectionType(final AEPartLocation dir) {
|
||||
return AECableType.COVERED;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean readFromStream(final PacketByteBuf data) throws IOException {
|
||||
final boolean c = super.readFromStream(data);
|
||||
final boolean wasOn = this.isOn;
|
||||
|
||||
this.isOn = data.readBoolean();
|
||||
|
||||
return wasOn != this.isOn || c; // TESR doesn't need updates!
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeToStream(final PacketByteBuf data) throws IOException {
|
||||
super.writeToStream(data);
|
||||
data.writeBoolean(this.getBurnTime() > 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag toTag(final CompoundTag data) {
|
||||
super.toTag(data);
|
||||
data.putDouble("burnTime", this.getBurnTime());
|
||||
data.putDouble("maxBurnTime", this.getMaxBurnTime());
|
||||
data.putInt("burnSpeed", this.getBurnSpeed());
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromTag(BlockState state, final CompoundTag data) {
|
||||
super.fromTag(state, data);
|
||||
this.setBurnTime(data.getDouble("burnTime"));
|
||||
this.setMaxBurnTime(data.getDouble("maxBurnTime"));
|
||||
this.setBurnSpeed(data.getInt("burnSpeed"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FixedItemInv getItemHandlerForSide(@Nonnull Direction facing) {
|
||||
return this.invExt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FixedItemInv getInternalInventory() {
|
||||
return this.inv;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeInventory(final FixedItemInv inv, final int slot, final InvOperation mc,
|
||||
final ItemStack removed, final ItemStack added) {
|
||||
if (this.getBurnTime() <= 0) {
|
||||
if (this.canEatFuel()) {
|
||||
try {
|
||||
this.getProxy().getTick().wakeDevice(this.getProxy().getNode());
|
||||
} catch (final GridAccessException e) {
|
||||
// wake up!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean canEatFuel() {
|
||||
final ItemStack is = this.inv.getInvStack(0);
|
||||
if (!is.isEmpty()) {
|
||||
final int newBurnTime = ForgeHooks.getBurnTime(is);
|
||||
if (newBurnTime > 0 && is.getCount() > 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DimensionalCoord getLocation() {
|
||||
return new DimensionalCoord(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickingRequest getTickingRequest(final IGridNode node) {
|
||||
if (this.getBurnTime() <= 0) {
|
||||
this.eatFuel();
|
||||
}
|
||||
|
||||
return new TickingRequest(TickRates.VibrationChamber.getMin(), TickRates.VibrationChamber.getMax(),
|
||||
this.getBurnTime() <= 0, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickRateModulation tickingRequest(final IGridNode node, final int ticksSinceLastCall) {
|
||||
if (this.getBurnTime() <= 0) {
|
||||
this.eatFuel();
|
||||
|
||||
if (this.getBurnTime() > 0) {
|
||||
return TickRateModulation.URGENT;
|
||||
}
|
||||
|
||||
this.setBurnSpeed(100);
|
||||
return TickRateModulation.SLEEP;
|
||||
}
|
||||
|
||||
this.setBurnSpeed(Math.max(MIN_BURN_SPEED, Math.min(this.getBurnSpeed(), MAX_BURN_SPEED)));
|
||||
final double dilation = this.getBurnSpeed() / DILATION_SCALING;
|
||||
|
||||
double timePassed = ticksSinceLastCall * dilation;
|
||||
this.setBurnTime(this.getBurnTime() - timePassed);
|
||||
if (this.getBurnTime() < 0) {
|
||||
timePassed += this.getBurnTime();
|
||||
this.setBurnTime(0);
|
||||
}
|
||||
|
||||
try {
|
||||
final IEnergyGrid grid = this.getProxy().getEnergy();
|
||||
final double newPower = timePassed * POWER_PER_TICK;
|
||||
final double overFlow = grid.injectPower(newPower, Actionable.SIMULATE);
|
||||
|
||||
// burn the over flow.
|
||||
grid.injectPower(Math.max(0.0, newPower - overFlow), Actionable.MODULATE);
|
||||
|
||||
if (overFlow > 0) {
|
||||
this.setBurnSpeed(this.getBurnSpeed() - ticksSinceLastCall);
|
||||
} else {
|
||||
this.setBurnSpeed(this.getBurnSpeed() + ticksSinceLastCall);
|
||||
}
|
||||
|
||||
this.setBurnSpeed(Math.max(MIN_BURN_SPEED, Math.min(this.getBurnSpeed(), MAX_BURN_SPEED)));
|
||||
return overFlow > 0 ? TickRateModulation.SLOWER : TickRateModulation.FASTER;
|
||||
} catch (final GridAccessException e) {
|
||||
this.setBurnSpeed(this.getBurnSpeed() - ticksSinceLastCall);
|
||||
this.setBurnSpeed(Math.max(MIN_BURN_SPEED, Math.min(this.getBurnSpeed(), MAX_BURN_SPEED)));
|
||||
return TickRateModulation.SLOWER;
|
||||
}
|
||||
}
|
||||
|
||||
private void eatFuel() {
|
||||
final ItemStack is = this.inv.getInvStack(0);
|
||||
if (!is.isEmpty()) {
|
||||
final int newBurnTime = ForgeHooks.getBurnTime(is);
|
||||
if (newBurnTime > 0 && is.getCount() > 0) {
|
||||
this.setBurnTime(this.getBurnTime() + newBurnTime);
|
||||
this.setMaxBurnTime(this.getBurnTime());
|
||||
|
||||
final Item fuelItem = is.getItem();
|
||||
is.decrement(1);
|
||||
|
||||
if (is.isEmpty()) {
|
||||
this.inv.setInvStack(0, fuelItem.getRecipeRemainder(is));
|
||||
} else {
|
||||
this.inv.setInvStack(0, is);
|
||||
}
|
||||
this.saveChanges();
|
||||
}
|
||||
}
|
||||
|
||||
if (this.getBurnTime() > 0) {
|
||||
try {
|
||||
this.getProxy().getTick().wakeDevice(this.getProxy().getNode());
|
||||
} catch (final GridAccessException e) {
|
||||
// gah!
|
||||
}
|
||||
}
|
||||
|
||||
// state change
|
||||
if ((!this.isOn && this.getBurnTime() > 0) || (this.isOn && this.getBurnTime() <= 0)) {
|
||||
this.isOn = this.getBurnTime() > 0;
|
||||
this.markForUpdate();
|
||||
|
||||
if (this.hasWorld()) {
|
||||
Platform.notifyBlocksOfNeighbors(this.world, this.pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getBurnSpeed() {
|
||||
return this.burnSpeed;
|
||||
}
|
||||
|
||||
private void setBurnSpeed(final int burnSpeed) {
|
||||
this.burnSpeed = burnSpeed;
|
||||
}
|
||||
|
||||
public double getMaxBurnTime() {
|
||||
return this.maxBurnTime;
|
||||
}
|
||||
|
||||
private void setMaxBurnTime(final double maxBurnTime) {
|
||||
this.maxBurnTime = maxBurnTime;
|
||||
}
|
||||
|
||||
public double getBurnTime() {
|
||||
return this.burnTime;
|
||||
}
|
||||
|
||||
private void setBurnTime(final double burnTime) {
|
||||
this.burnTime = burnTime;
|
||||
}
|
||||
|
||||
private class FuelSlotFilter implements IAEItemFilter {
|
||||
@Override
|
||||
public boolean allowExtract(FixedItemInv inv, int slot, int amount) {
|
||||
return ForgeHooks.getBurnTime(inv.getInvStack(slot)) == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowInsert(FixedItemInv inv, int slot, ItemStack stack) {
|
||||
return ForgeHooks.getBurnTime(stack) != 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,327 @@
|
||||
/*
|
||||
* 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.tile.networking;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import alexiil.mc.lib.attributes.AttributeList;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
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.world.World;
|
||||
|
||||
import appeng.api.networking.IGridNode;
|
||||
import appeng.api.parts.IFacadeContainer;
|
||||
import appeng.api.parts.IPart;
|
||||
import appeng.api.parts.LayerFlags;
|
||||
import appeng.api.parts.SelectedPart;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.api.util.AEColor;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
import appeng.api.util.DimensionalCoord;
|
||||
import appeng.client.render.cablebus.CableBusRenderState;
|
||||
import appeng.helpers.AEMultiTile;
|
||||
import appeng.hooks.TickHandler;
|
||||
import appeng.parts.CableBusContainer;
|
||||
import appeng.tile.AEBaseBlockEntity;
|
||||
import appeng.util.Platform;
|
||||
|
||||
public class CableBusBlockEntity extends AEBaseBlockEntity implements AEMultiTile {
|
||||
|
||||
private CableBusContainer cb = new CableBusContainer(this);
|
||||
|
||||
private int oldLV = -1; // on re-calculate light when it changes
|
||||
|
||||
public CableBusBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromTag(BlockState state, final CompoundTag data) {
|
||||
super.fromTag(state, data);
|
||||
this.getCableBus().readFromNBT(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag toTag(final CompoundTag data) {
|
||||
super.toTag(data);
|
||||
this.getCableBus().writeToNBT(data);
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean readFromStream(final PacketByteBuf data) throws IOException {
|
||||
final boolean c = super.readFromStream(data);
|
||||
boolean ret = this.getCableBus().readFromStream(data);
|
||||
|
||||
final int newLV = this.getCableBus().getLightValue();
|
||||
if (newLV != this.oldLV) {
|
||||
this.oldLV = newLV;
|
||||
this.world.getLightingProvider().checkBlock(this.pos);
|
||||
ret = true;
|
||||
}
|
||||
|
||||
this.updateTileSetting();
|
||||
return ret || c;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeToStream(final PacketByteBuf data) throws IOException {
|
||||
super.writeToStream(data);
|
||||
this.getCableBus().writeToStream(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes this tile to the TESR version if any of the parts require dynamic
|
||||
* rendering.
|
||||
*/
|
||||
protected void updateTileSetting() {
|
||||
// FIXME: potentially invalidate voxel shape cache?
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getSquaredRenderDistance() {
|
||||
return 900.0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markRemoved() {
|
||||
super.markRemoved();
|
||||
this.getCableBus().removeFromWorld();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelRemoval() {
|
||||
super.cancelRemoval();
|
||||
TickHandler.INSTANCE.addInit(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IGridNode getGridNode(final AEPartLocation dir) {
|
||||
return this.getCableBus().getGridNode(dir);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AECableType getCableConnectionType(final AEPartLocation side) {
|
||||
return this.getCableBus().getCableConnectionType(side);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getCableConnectionLength(AECableType cable) {
|
||||
return this.getCableBus().getCableConnectionLength(cable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkUnloaded() {
|
||||
super.onChunkUnloaded();
|
||||
this.getCableBus().removeFromWorld();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markForUpdate() {
|
||||
if (this.world == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final int newLV = this.getCableBus().getLightValue();
|
||||
if (newLV != this.oldLV) {
|
||||
this.oldLV = newLV;
|
||||
this.world.getLightingProvider().checkBlock(this.pos);
|
||||
}
|
||||
|
||||
super.markForUpdate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeRotated() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getDrops(final World w, final BlockPos pos, final List drops) {
|
||||
this.getCableBus().getDrops(drops);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getNoDrops(final World w, final BlockPos pos, final List<ItemStack> drops) {
|
||||
this.getCableBus().getNoDrops(drops);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReady() {
|
||||
super.onReady();
|
||||
if (this.getCableBus().isEmpty()) {
|
||||
if (this.world.getBlockEntity(this.pos) == this) {
|
||||
this.world.breakBlock(this.pos, true);
|
||||
}
|
||||
} else {
|
||||
this.getCableBus().addToWorld();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IFacadeContainer getFacadeContainer() {
|
||||
return this.getCableBus().getFacadeContainer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAddPart(final ItemStack is, final AEPartLocation side) {
|
||||
return this.getCableBus().canAddPart(is, side);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AEPartLocation addPart(final ItemStack is, final AEPartLocation side, final PlayerEntity player,
|
||||
final Hand hand) {
|
||||
return this.getCableBus().addPart(is, side, player, hand);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPart getPart(final AEPartLocation side) {
|
||||
return this.cb.getPart(side);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPart getPart(final Direction side) {
|
||||
return this.getCableBus().getPart(side);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removePart(final AEPartLocation side, final boolean suppressUpdate) {
|
||||
this.getCableBus().removePart(side, suppressUpdate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DimensionalCoord getLocation() {
|
||||
return new DimensionalCoord(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AEColor getColor() {
|
||||
return this.getCableBus().getColor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearContainer() {
|
||||
this.setCableBus(new CableBusContainer(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBlocked(final Direction side) {
|
||||
// TODO 1.10.2-R - Stuff.
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SelectedPart selectPart(final Vec3d pos) {
|
||||
return this.getCableBus().selectPart(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markForSave() {
|
||||
this.saveChanges();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void partChanged() {
|
||||
this.notifyNeighbors();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasRedstone(final AEPartLocation side) {
|
||||
return this.getCableBus().hasRedstone(side);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return this.getCableBus().isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<LayerFlags> getLayerFlags() {
|
||||
return this.getCableBus().getLayerFlags();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanup() {
|
||||
this.getWorld().removeBlock(this.pos, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyNeighbors() {
|
||||
if (this.world != null && this.world.isChunkLoaded(this.pos) && !CableBusContainer.isLoading()) {
|
||||
Platform.notifyBlocksOfNeighbors(this.world, this.pos);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInWorld() {
|
||||
return this.getCableBus().isInWorld();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean recolourBlock(final Direction side, final AEColor colour, final PlayerEntity who) {
|
||||
return this.getCableBus().recolourBlock(side, colour, who);
|
||||
}
|
||||
|
||||
public CableBusContainer getCableBus() {
|
||||
return this.cb;
|
||||
}
|
||||
|
||||
private void setCableBus(final CableBusContainer cb) {
|
||||
this.cb = cb;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAllAttributes(World world, BlockPos pos, BlockState state, AttributeList<?> to) {
|
||||
super.addAllAttributes(world, pos, state, to);
|
||||
|
||||
for (AEPartLocation location : AEPartLocation.values()) {
|
||||
IPart part = this.cb.getPart(location);
|
||||
if (part != null) {
|
||||
part.addAllAttributes(to);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CableBusRenderState getRenderAttachmentData() {
|
||||
World world = getWorld();
|
||||
if (world == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
CableBusRenderState renderState = this.cb.getRenderState();
|
||||
renderState.setWorld(world);
|
||||
renderState.setPos(pos);
|
||||
return renderState;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.tile.networking;
|
||||
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
|
||||
import net.minecraft.client.render.VertexConsumerProvider;
|
||||
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
|
||||
import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher;
|
||||
import net.minecraft.util.math.Direction;
|
||||
|
||||
import appeng.api.parts.IPart;
|
||||
|
||||
public class CableBusTESR extends BlockEntityRenderer<CableBusBlockEntity> {
|
||||
|
||||
public CableBusTESR(BlockEntityRenderDispatcher rendererDispatcherIn) {
|
||||
super(rendererDispatcherIn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(CableBusBlockEntity te, float partialTicks, MatrixStack ms, VertexConsumerProvider buffers,
|
||||
int combinedLightIn, int combinedOverlayIn) {
|
||||
if (!te.getCableBus().isRequiresDynamicRender()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Direction facing : Direction.values()) {
|
||||
IPart part = te.getPart(facing);
|
||||
if (part != null && part.requireDynamicRender()) {
|
||||
part.renderDynamic(partialTicks, ms, buffers, combinedLightIn, combinedOverlayIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,192 +1,34 @@
|
||||
/*
|
||||
* 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.tile.networking;
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import alexiil.mc.lib.attributes.item.FixedItemInv;
|
||||
import alexiil.mc.lib.attributes.item.impl.EmptyFixedItemInv;
|
||||
|
||||
import appeng.api.config.Actionable;
|
||||
import appeng.api.networking.GridFlags;
|
||||
import appeng.api.networking.energy.IEnergyGrid;
|
||||
import appeng.api.networking.events.MENetworkControllerChange;
|
||||
import appeng.api.networking.events.MENetworkEventSubscribe;
|
||||
import appeng.api.networking.events.MENetworkPowerStatusChange;
|
||||
import appeng.api.networking.events.MENetworkPowerStorage;
|
||||
import appeng.api.networking.events.MENetworkPowerStorage.PowerEventType;
|
||||
import appeng.api.networking.pathing.ControllerState;
|
||||
import appeng.api.networking.IGridHost;
|
||||
import appeng.api.networking.IGridNode;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
import appeng.block.networking.ControllerBlock;
|
||||
import appeng.block.networking.ControllerBlock.ControllerBlockState;
|
||||
import appeng.me.GridAccessException;
|
||||
import appeng.tile.grid.AENetworkPowerBlockEntity;
|
||||
import appeng.util.inv.InvOperation;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
public class ControllerBlockEntity extends AENetworkPowerBlockEntity {
|
||||
private boolean isValid = false;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public ControllerBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
this.setInternalMaxPower(8000);
|
||||
this.setInternalPublicPowerStorage(true);
|
||||
this.getProxy().setIdlePowerUsage(3);
|
||||
this.getProxy().setFlags(GridFlags.CANNOT_CARRY, GridFlags.DENSE_CAPACITY);
|
||||
// FIXME FABRIC DUMMY
|
||||
public class ControllerBlockEntity implements IGridHost {
|
||||
@Nullable
|
||||
@Override
|
||||
public IGridNode getGridNode(@Nonnull AEPartLocation dir) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public AECableType getCableConnectionType(@Nonnull AEPartLocation dir) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AECableType getCableConnectionType(final AEPartLocation dir) {
|
||||
return AECableType.DENSE_SMART;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReady() {
|
||||
this.onNeighborChange(true);
|
||||
super.onReady();
|
||||
}
|
||||
|
||||
public void onNeighborChange(final boolean force) {
|
||||
final boolean xx = this.checkController(this.pos.offset(Direction.EAST))
|
||||
&& this.checkController(this.pos.offset(Direction.WEST));
|
||||
final boolean yy = this.checkController(this.pos.offset(Direction.UP))
|
||||
&& this.checkController(this.pos.offset(Direction.DOWN));
|
||||
final boolean zz = this.checkController(this.pos.offset(Direction.NORTH))
|
||||
&& this.checkController(this.pos.offset(Direction.SOUTH));
|
||||
|
||||
// int meta = world.getBlockMetadata( xCoord, yCoord, zCoord );
|
||||
// boolean hasPower = meta > 0;
|
||||
// boolean isConflict = meta == 2;
|
||||
|
||||
final boolean oldValid = this.isValid;
|
||||
|
||||
this.isValid = (xx && !yy && !zz) || (!xx && yy && !zz) || (!xx && !yy && zz)
|
||||
|| ((xx ? 1 : 0) + (yy ? 1 : 0) + (zz ? 1 : 0) <= 1);
|
||||
|
||||
if (oldValid != this.isValid || force) {
|
||||
if (this.isValid) {
|
||||
this.getProxy().setValidSides(EnumSet.allOf(Direction.class));
|
||||
} else {
|
||||
this.getProxy().setValidSides(EnumSet.noneOf(Direction.class));
|
||||
}
|
||||
|
||||
this.updateMeta();
|
||||
}
|
||||
public void securityBreak() {
|
||||
|
||||
}
|
||||
|
||||
private void updateMeta() {
|
||||
if (!this.getProxy().isReady()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ControllerBlockState metaState = ControllerBlockState.offline;
|
||||
|
||||
try {
|
||||
if (this.getProxy().getEnergy().isNetworkPowered()) {
|
||||
metaState = ControllerBlockState.online;
|
||||
|
||||
if (this.getProxy().getPath().getControllerState() == ControllerState.CONTROLLER_CONFLICT) {
|
||||
metaState = ControllerBlockState.conflicted;
|
||||
}
|
||||
}
|
||||
} catch (final GridAccessException e) {
|
||||
metaState = ControllerBlockState.offline;
|
||||
}
|
||||
|
||||
if (this.checkController(this.pos)
|
||||
&& this.world.getBlockState(this.pos).get(ControllerBlock.CONTROLLER_STATE) != metaState) {
|
||||
this.world.setBlockState(this.pos,
|
||||
this.world.getBlockState(this.pos).with(ControllerBlock.CONTROLLER_STATE, metaState));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double getFunnelPowerDemand(final double maxReceived) {
|
||||
try {
|
||||
final IEnergyGrid grid = this.getProxy().getEnergy();
|
||||
|
||||
return grid.getEnergyDemand(maxReceived);
|
||||
} catch (final GridAccessException e) {
|
||||
// no grid? use local...
|
||||
return super.getFunnelPowerDemand(maxReceived);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double funnelPowerIntoStorage(final double power, final Actionable mode) {
|
||||
try {
|
||||
final IEnergyGrid grid = this.getProxy().getEnergy();
|
||||
final double leftOver = grid.injectPower(power, mode);
|
||||
|
||||
return leftOver;
|
||||
} catch (final GridAccessException e) {
|
||||
// no grid? use local...
|
||||
return super.funnelPowerIntoStorage(power, mode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void PowerEvent(final PowerEventType x) {
|
||||
try {
|
||||
this.getProxy().getGrid().postEvent(new MENetworkPowerStorage(this, x));
|
||||
} catch (final GridAccessException e) {
|
||||
// not ready!
|
||||
}
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void onControllerChange(final MENetworkControllerChange status) {
|
||||
this.updateMeta();
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void onPowerChange(final MENetworkPowerStatusChange status) {
|
||||
this.updateMeta();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FixedItemInv getInternalInventory() {
|
||||
return EmptyFixedItemInv.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeInventory(final FixedItemInv inv, final int slot, final InvOperation mc,
|
||||
final ItemStack removed, final ItemStack added) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for a controller at this coordinates as well as is it loaded.
|
||||
*
|
||||
* @return true if there is a loaded controller
|
||||
*/
|
||||
private boolean checkController(final BlockPos pos) {
|
||||
if (this.world.getChunkManager().isChunkLoaded(new ChunkPos(pos.getX() >> 4, pos.getZ() >> 4))) {
|
||||
return this.world.getBlockEntity(pos) instanceof ControllerBlockEntity;
|
||||
}
|
||||
|
||||
return false;
|
||||
public BlockPos getPos() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,72 +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.tile.networking;
|
||||
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
|
||||
import appeng.api.config.AccessRestriction;
|
||||
import appeng.api.config.Actionable;
|
||||
import appeng.api.config.PowerMultiplier;
|
||||
import appeng.api.networking.energy.IAEPowerStorage;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
import appeng.tile.grid.AENetworkBlockEntity;
|
||||
|
||||
public class CreativeEnergyCellBlockEntity extends AENetworkBlockEntity implements IAEPowerStorage {
|
||||
|
||||
public CreativeEnergyCellBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
this.getProxy().setIdlePowerUsage(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AECableType getCableConnectionType(final AEPartLocation dir) {
|
||||
return AECableType.COVERED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double injectAEPower(final double amt, final Actionable mode) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getAEMaxPower() {
|
||||
return Long.MAX_VALUE / 10000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getAECurrentPower() {
|
||||
return Long.MAX_VALUE / 10000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAEPublicPowerStorage() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessRestriction getPowerFlow() {
|
||||
return AccessRestriction.READ_WRITE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double extractAEPower(final double amt, final Actionable mode, final PowerMultiplier pm) {
|
||||
return amt;
|
||||
}
|
||||
}
|
||||
@@ -1,80 +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.tile.networking;
|
||||
|
||||
import alexiil.mc.lib.attributes.item.impl.EmptyFixedItemInv;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import alexiil.mc.lib.attributes.item.FixedItemInv;
|
||||
|
||||
import appeng.api.config.Actionable;
|
||||
import appeng.api.networking.energy.IEnergyGrid;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
import appeng.me.GridAccessException;
|
||||
import appeng.tile.grid.AENetworkPowerBlockEntity;
|
||||
import appeng.util.inv.InvOperation;
|
||||
|
||||
public class EnergyAcceptorBlockEntity extends AENetworkPowerBlockEntity {
|
||||
|
||||
public EnergyAcceptorBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
this.getProxy().setIdlePowerUsage(0.0);
|
||||
this.setInternalMaxPower(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AECableType getCableConnectionType(final AEPartLocation dir) {
|
||||
return AECableType.COVERED;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double getFunnelPowerDemand(final double maxRequired) {
|
||||
try {
|
||||
final IEnergyGrid grid = this.getProxy().getEnergy();
|
||||
|
||||
return grid.getEnergyDemand(maxRequired);
|
||||
} catch (final GridAccessException e) {
|
||||
return this.getInternalMaxPower();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double funnelPowerIntoStorage(final double power, final Actionable mode) {
|
||||
try {
|
||||
final IEnergyGrid grid = this.getProxy().getEnergy();
|
||||
final double leftOver = grid.injectPower(power, mode);
|
||||
|
||||
return leftOver;
|
||||
} catch (final GridAccessException e) {
|
||||
return super.funnelPowerIntoStorage(power, mode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FixedItemInv getInternalInventory() {
|
||||
return EmptyFixedItemInv.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeInventory(final FixedItemInv inv, final int slot, final InvOperation mc,
|
||||
final ItemStack removed, final ItemStack added) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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.tile.networking;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
|
||||
import appeng.api.config.AccessRestriction;
|
||||
import appeng.api.config.Actionable;
|
||||
import appeng.api.config.PowerMultiplier;
|
||||
import appeng.api.networking.energy.IAEPowerStorage;
|
||||
import appeng.api.networking.events.MENetworkPowerStorage;
|
||||
import appeng.api.networking.events.MENetworkPowerStorage.PowerEventType;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
import appeng.block.networking.EnergyCellBlock;
|
||||
import appeng.me.GridAccessException;
|
||||
import appeng.tile.grid.AENetworkBlockEntity;
|
||||
import appeng.util.SettingsFrom;
|
||||
|
||||
public class EnergyCellBlockEntity extends AENetworkBlockEntity implements IAEPowerStorage {
|
||||
|
||||
private double internalCurrentPower = 0.0;
|
||||
private double internalMaxPower = 200000.0;
|
||||
|
||||
private byte currentMeta = -1;
|
||||
|
||||
public EnergyCellBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
this.getProxy().setIdlePowerUsage(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AECableType getCableConnectionType(final AEPartLocation dir) {
|
||||
return AECableType.COVERED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReady() {
|
||||
super.onReady();
|
||||
final int value = this.world.getBlockState(this.pos).get(EnergyCellBlock.ENERGY_STORAGE);
|
||||
this.currentMeta = (byte) value;
|
||||
this.changePowerLevel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a fill factor, return the storage level (0-7) used for the state of the
|
||||
* block. This is also used for determining the item model.
|
||||
*/
|
||||
public static int getStorageLevelFromFillFactor(double fillFactor) {
|
||||
byte boundMetadata = (byte) (8.0 * (fillFactor));
|
||||
|
||||
if (boundMetadata > 7) {
|
||||
boundMetadata = 7;
|
||||
}
|
||||
if (boundMetadata < 0) {
|
||||
boundMetadata = 0;
|
||||
}
|
||||
return boundMetadata;
|
||||
}
|
||||
|
||||
private void changePowerLevel() {
|
||||
if (this.notLoaded() || this.isRemoved()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int storageLevel = getStorageLevelFromFillFactor(this.internalCurrentPower / this.getInternalMaxPower());
|
||||
|
||||
if (this.currentMeta != storageLevel) {
|
||||
this.currentMeta = (byte) storageLevel;
|
||||
this.world.setBlockState(this.pos,
|
||||
this.world.getBlockState(this.pos).with(EnergyCellBlock.ENERGY_STORAGE, storageLevel));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag toTag(final CompoundTag data) {
|
||||
super.toTag(data);
|
||||
data.putDouble("internalCurrentPower", this.internalCurrentPower);
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromTag(BlockState state, final CompoundTag data) {
|
||||
super.fromTag(state, data);
|
||||
this.internalCurrentPower = data.getDouble("internalCurrentPower");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeRotated() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uploadSettings(final SettingsFrom from, final CompoundTag compound) {
|
||||
if (from == SettingsFrom.DISMANTLE_ITEM) {
|
||||
this.internalCurrentPower = compound.getDouble("internalCurrentPower");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag downloadSettings(final SettingsFrom from) {
|
||||
if (from == SettingsFrom.DISMANTLE_ITEM) {
|
||||
final CompoundTag tag = new CompoundTag();
|
||||
tag.putDouble("internalCurrentPower", this.internalCurrentPower);
|
||||
tag.putDouble("internalMaxPower", this.getInternalMaxPower()); // used for tool tip.
|
||||
return tag;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final double injectAEPower(double amt, final Actionable mode) {
|
||||
if (mode == Actionable.SIMULATE) {
|
||||
final double fakeBattery = this.internalCurrentPower + amt;
|
||||
if (fakeBattery > this.getInternalMaxPower()) {
|
||||
return fakeBattery - this.getInternalMaxPower();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (this.internalCurrentPower < 0.01 && amt > 0.01) {
|
||||
this.getProxy().getNode().getGrid()
|
||||
.postEvent(new MENetworkPowerStorage(this, PowerEventType.PROVIDE_POWER));
|
||||
}
|
||||
|
||||
this.internalCurrentPower += amt;
|
||||
if (this.internalCurrentPower > this.getInternalMaxPower()) {
|
||||
amt = this.internalCurrentPower - this.getInternalMaxPower();
|
||||
this.internalCurrentPower = this.getInternalMaxPower();
|
||||
|
||||
this.changePowerLevel();
|
||||
return amt;
|
||||
}
|
||||
|
||||
this.changePowerLevel();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getAEMaxPower() {
|
||||
return this.getInternalMaxPower();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getAECurrentPower() {
|
||||
return this.internalCurrentPower;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAEPublicPowerStorage() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessRestriction getPowerFlow() {
|
||||
return AccessRestriction.READ_WRITE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final double extractAEPower(final double amt, final Actionable mode, final PowerMultiplier pm) {
|
||||
return pm.divide(this.extractAEPower(pm.multiply(amt), mode));
|
||||
}
|
||||
|
||||
private double extractAEPower(double amt, final Actionable mode) {
|
||||
if (mode == Actionable.SIMULATE) {
|
||||
if (this.internalCurrentPower > amt) {
|
||||
return amt;
|
||||
}
|
||||
return this.internalCurrentPower;
|
||||
}
|
||||
|
||||
final boolean wasFull = this.internalCurrentPower >= this.getInternalMaxPower() - 0.001;
|
||||
|
||||
if (wasFull && amt > 0.001) {
|
||||
try {
|
||||
this.getProxy().getGrid().postEvent(new MENetworkPowerStorage(this, PowerEventType.REQUEST_POWER));
|
||||
} catch (final GridAccessException ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (this.internalCurrentPower > amt) {
|
||||
this.internalCurrentPower -= amt;
|
||||
|
||||
this.changePowerLevel();
|
||||
return amt;
|
||||
}
|
||||
|
||||
amt = this.internalCurrentPower;
|
||||
this.internalCurrentPower = 0;
|
||||
|
||||
this.changePowerLevel();
|
||||
return amt;
|
||||
}
|
||||
|
||||
private double getInternalMaxPower() {
|
||||
return this.internalMaxPower;
|
||||
}
|
||||
|
||||
void setInternalMaxPower(final double internalMaxPower) {
|
||||
this.internalMaxPower = internalMaxPower;
|
||||
}
|
||||
}
|
||||
@@ -1,186 +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.tile.networking;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.EnumSet;
|
||||
|
||||
import alexiil.mc.lib.attributes.item.FixedItemInv;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.util.math.Direction;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.implementations.IPowerChannelState;
|
||||
import appeng.api.implementations.tiles.IWirelessAccessPoint;
|
||||
import appeng.api.networking.GridFlags;
|
||||
import appeng.api.networking.IGrid;
|
||||
import appeng.api.networking.events.MENetworkChannelsChanged;
|
||||
import appeng.api.networking.events.MENetworkEventSubscribe;
|
||||
import appeng.api.networking.events.MENetworkPowerStatusChange;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
import appeng.api.util.DimensionalCoord;
|
||||
import appeng.core.AEConfig;
|
||||
import appeng.me.GridAccessException;
|
||||
import appeng.tile.grid.AENetworkInvBlockEntity;
|
||||
import appeng.tile.inventory.AppEngInternalInventory;
|
||||
import appeng.util.inv.InvOperation;
|
||||
import appeng.util.inv.filter.AEItemDefinitionFilter;
|
||||
|
||||
public class WirelessBlockEntity extends AENetworkInvBlockEntity implements IWirelessAccessPoint, IPowerChannelState {
|
||||
|
||||
public static final int POWERED_FLAG = 1;
|
||||
public static final int CHANNEL_FLAG = 2;
|
||||
|
||||
private final AppEngInternalInventory inv = new AppEngInternalInventory(this, 1);
|
||||
|
||||
private int clientFlags = 0;
|
||||
|
||||
public WirelessBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
this.inv.setFilter(new AEItemDefinitionFilter(AEApi.instance().definitions().materials().wirelessBooster()));
|
||||
this.getProxy().setFlags(GridFlags.REQUIRE_CHANNEL);
|
||||
this.getProxy().setValidSides(EnumSet.noneOf(Direction.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOrientation(final Direction inForward, final Direction inUp) {
|
||||
super.setOrientation(inForward, inUp);
|
||||
this.getProxy().setValidSides(EnumSet.of(this.getForward().getOpposite()));
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void chanRender(final MENetworkChannelsChanged c) {
|
||||
this.markForUpdate();
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void powerRender(final MENetworkPowerStatusChange c) {
|
||||
this.markForUpdate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean readFromStream(final PacketByteBuf data) throws IOException {
|
||||
final boolean c = super.readFromStream(data);
|
||||
final int old = this.getClientFlags();
|
||||
this.setClientFlags(data.readByte());
|
||||
|
||||
return old != this.getClientFlags() || c;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected 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);
|
||||
}
|
||||
} catch (final GridAccessException e) {
|
||||
// meh
|
||||
}
|
||||
|
||||
data.writeByte((byte) this.getClientFlags());
|
||||
}
|
||||
|
||||
@Override
|
||||
public AECableType getCableConnectionType(final AEPartLocation dir) {
|
||||
return AECableType.SMART;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DimensionalCoord getLocation() {
|
||||
return new DimensionalCoord(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FixedItemInv getInternalInventory() {
|
||||
return this.inv;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeInventory(final FixedItemInv inv, final int slot, final InvOperation mc,
|
||||
final ItemStack removed, final ItemStack added) {
|
||||
// :P
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReady() {
|
||||
this.updatePower();
|
||||
super.onReady();
|
||||
}
|
||||
|
||||
private void updatePower() {
|
||||
this.getProxy().setIdlePowerUsage(AEConfig.instance().wireless_getPowerDrain(this.getBoosters()));
|
||||
}
|
||||
|
||||
private int getBoosters() {
|
||||
final ItemStack boosters = this.inv.getInvStack(0);
|
||||
return boosters == null ? 0 : boosters.getCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveChanges() {
|
||||
this.updatePower();
|
||||
super.saveChanges();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getRange() {
|
||||
return AEConfig.instance().wireless_getMaxRange(this.getBoosters());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
if (isClient()) {
|
||||
return this.isPowered() && (CHANNEL_FLAG == (this.getClientFlags() & CHANNEL_FLAG));
|
||||
}
|
||||
|
||||
return this.getProxy().isActive();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IGrid getGrid() {
|
||||
try {
|
||||
return this.getProxy().getGrid();
|
||||
} catch (final GridAccessException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPowered() {
|
||||
return POWERED_FLAG == (this.getClientFlags() & POWERED_FLAG);
|
||||
}
|
||||
|
||||
public int getClientFlags() {
|
||||
return this.clientFlags;
|
||||
}
|
||||
|
||||
private void setClientFlags(final int clientFlags) {
|
||||
this.clientFlags = clientFlags;
|
||||
}
|
||||
}
|
||||
@@ -1,265 +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.tile.powersink;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.energy.IEnergyStorage;
|
||||
|
||||
import appeng.api.config.AccessRestriction;
|
||||
import appeng.api.config.Actionable;
|
||||
import appeng.api.config.PowerMultiplier;
|
||||
import appeng.api.config.PowerUnits;
|
||||
import appeng.api.networking.energy.IAEPowerStorage;
|
||||
import appeng.api.networking.events.MENetworkPowerStorage.PowerEventType;
|
||||
import appeng.capabilities.Capabilities;
|
||||
import appeng.tile.AEBaseInvBlockEntity;
|
||||
|
||||
public abstract class AEBasePoweredBlockEntity extends AEBaseInvBlockEntity
|
||||
implements IAEPowerStorage, IExternalPowerSink {
|
||||
|
||||
// values that determine general function, are set by inheriting classes if
|
||||
// needed. These should generally remain static.
|
||||
private double internalMaxPower = 10000;
|
||||
private boolean internalPublicPowerStorage = false;
|
||||
private AccessRestriction internalPowerFlow = AccessRestriction.READ_WRITE;
|
||||
// the current power buffer.
|
||||
private double internalCurrentPower = 0;
|
||||
private static final Set<Direction> ALL_SIDES = ImmutableSet.copyOf(EnumSet.allOf(Direction.class));
|
||||
private Set<Direction> internalPowerSides = ALL_SIDES;
|
||||
private final IEnergyStorage forgeEnergyAdapter;
|
||||
// Cache the optional to not continuously re-allocate it or the supplier
|
||||
private final LazyOptional<IEnergyStorage> forgeEnergyAdapterOptional;
|
||||
|
||||
// IC2 private IC2PowerSink ic2Sink;
|
||||
|
||||
public AEBasePoweredBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
this.forgeEnergyAdapter = new ForgeEnergyAdapter(this);
|
||||
this.forgeEnergyAdapterOptional = LazyOptional.of(() -> forgeEnergyAdapter);
|
||||
// IC2 this.ic2Sink = Integrations.ic2().createPowerSink( this, this );
|
||||
// IC2 this.ic2Sink.setValidFaces( this.internalPowerSides );
|
||||
}
|
||||
|
||||
protected final Set<Direction> getPowerSides() {
|
||||
return this.internalPowerSides;
|
||||
}
|
||||
|
||||
protected void setPowerSides(final Set<Direction> sides) {
|
||||
this.internalPowerSides = ImmutableSet.copyOf(sides);
|
||||
// IC2 this.ic2Sink.setValidFaces( sides );
|
||||
// trigger re-calc!
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag toTag(final CompoundTag data) {
|
||||
super.toTag(data);
|
||||
data.putDouble("internalCurrentPower", this.getInternalCurrentPower());
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromTag(BlockState state, final CompoundTag data) {
|
||||
super.fromTag(state, data);
|
||||
this.setInternalCurrentPower(data.getDouble("internalCurrentPower"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final double getExternalPowerDemand(final PowerUnits externalUnit, final double maxPowerRequired) {
|
||||
return PowerUnits.AE.convertTo(externalUnit,
|
||||
Math.max(0.0, this.getFunnelPowerDemand(externalUnit.convertTo(PowerUnits.AE, maxPowerRequired))));
|
||||
}
|
||||
|
||||
protected double getFunnelPowerDemand(final double maxRequired) {
|
||||
return this.getInternalMaxPower() - this.getInternalCurrentPower();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final double injectExternalPower(final PowerUnits input, final double amt, Actionable mode) {
|
||||
return PowerUnits.AE.convertTo(input, this.funnelPowerIntoStorage(input.convertTo(PowerUnits.AE, amt), mode));
|
||||
}
|
||||
|
||||
protected double funnelPowerIntoStorage(final double power, final Actionable mode) {
|
||||
return this.injectAEPower(power, mode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final double injectAEPower(double amt, final Actionable mode) {
|
||||
if (amt < 0.000001) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
final double required = this.getAEMaxPower() - this.getAECurrentPower();
|
||||
final double insertable = Math.min(required, amt);
|
||||
|
||||
if (mode == Actionable.MODULATE) {
|
||||
if (this.getInternalCurrentPower() < 0.01 && insertable > 0.01) {
|
||||
this.PowerEvent(PowerEventType.PROVIDE_POWER);
|
||||
}
|
||||
|
||||
this.setInternalCurrentPower(this.getInternalCurrentPower() + insertable);
|
||||
}
|
||||
|
||||
return amt - insertable;
|
||||
}
|
||||
|
||||
protected void PowerEvent(final PowerEventType x) {
|
||||
// nothing.
|
||||
}
|
||||
|
||||
@Override
|
||||
public final double getAEMaxPower() {
|
||||
return this.getInternalMaxPower();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final double getAECurrentPower() {
|
||||
return this.getInternalCurrentPower();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isAEPublicPowerStorage() {
|
||||
return this.isInternalPublicPowerStorage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final AccessRestriction getPowerFlow() {
|
||||
return this.getInternalPowerFlow();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final double extractAEPower(final double amt, final Actionable mode, final PowerMultiplier multiplier) {
|
||||
return multiplier.divide(this.extractAEPower(multiplier.multiply(amt), mode));
|
||||
}
|
||||
|
||||
protected double extractAEPower(double amt, final Actionable mode) {
|
||||
if (mode == Actionable.SIMULATE) {
|
||||
if (this.getInternalCurrentPower() > amt) {
|
||||
return amt;
|
||||
}
|
||||
return this.getInternalCurrentPower();
|
||||
}
|
||||
|
||||
final boolean wasFull = this.getInternalCurrentPower() >= this.getInternalMaxPower() - 0.001;
|
||||
if (wasFull && amt > 0.001) {
|
||||
this.PowerEvent(PowerEventType.REQUEST_POWER);
|
||||
}
|
||||
|
||||
if (this.getInternalCurrentPower() > amt) {
|
||||
this.setInternalCurrentPower(this.getInternalCurrentPower() - amt);
|
||||
return amt;
|
||||
}
|
||||
|
||||
amt = this.getInternalCurrentPower();
|
||||
this.setInternalCurrentPower(0);
|
||||
return amt;
|
||||
}
|
||||
|
||||
public double getInternalCurrentPower() {
|
||||
return this.internalCurrentPower;
|
||||
}
|
||||
|
||||
public void setInternalCurrentPower(final double internalCurrentPower) {
|
||||
this.internalCurrentPower = internalCurrentPower;
|
||||
}
|
||||
|
||||
public double getInternalMaxPower() {
|
||||
return this.internalMaxPower;
|
||||
}
|
||||
|
||||
public void setInternalMaxPower(final double internalMaxPower) {
|
||||
this.internalMaxPower = internalMaxPower;
|
||||
}
|
||||
|
||||
private boolean isInternalPublicPowerStorage() {
|
||||
return this.internalPublicPowerStorage;
|
||||
}
|
||||
|
||||
public void setInternalPublicPowerStorage(final boolean internalPublicPowerStorage) {
|
||||
this.internalPublicPowerStorage = internalPublicPowerStorage;
|
||||
}
|
||||
|
||||
private AccessRestriction getInternalPowerFlow() {
|
||||
return this.internalPowerFlow;
|
||||
}
|
||||
|
||||
public void setInternalPowerFlow(final AccessRestriction internalPowerFlow) {
|
||||
this.internalPowerFlow = internalPowerFlow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReady() {
|
||||
super.onReady();
|
||||
|
||||
// IC2 this.ic2Sink.onLoad();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkUnloaded() {
|
||||
super.onChunkUnloaded();
|
||||
|
||||
// IC2 this.ic2Sink.onChunkUnloaded();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markRemoved() {
|
||||
super.markRemoved();
|
||||
|
||||
// IC2 this.ic2Sink.invalidate();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nonnull
|
||||
@Override
|
||||
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> capability) {
|
||||
|
||||
if (capability == Capabilities.FORGE_ENERGY) {
|
||||
if (this.getPowerSides().equals(ALL_SIDES)) {
|
||||
return (LazyOptional<T>) this.forgeEnergyAdapterOptional;
|
||||
}
|
||||
}
|
||||
|
||||
return super.getCapability(capability);
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nonnull
|
||||
@Override
|
||||
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> capability, Direction facing) {
|
||||
if (capability == Capabilities.FORGE_ENERGY) {
|
||||
if (this.getPowerSides().contains(facing)) {
|
||||
return (LazyOptional<T>) this.forgeEnergyAdapterOptional;
|
||||
}
|
||||
}
|
||||
return super.getCapability(capability, facing);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
|
||||
package appeng.tile.powersink;
|
||||
|
||||
import net.minecraftforge.energy.IEnergyStorage;
|
||||
|
||||
import appeng.api.config.Actionable;
|
||||
import appeng.api.config.PowerUnits;
|
||||
|
||||
/**
|
||||
* Adapts an {@link IExternalPowerSink} to Forges {@link IEnergyStorage}.
|
||||
*/
|
||||
class ForgeEnergyAdapter implements IEnergyStorage {
|
||||
|
||||
private final IExternalPowerSink sink;
|
||||
|
||||
ForgeEnergyAdapter(IExternalPowerSink sink) {
|
||||
this.sink = sink;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int receiveEnergy(int maxReceive, boolean simulate) {
|
||||
final double offered = maxReceive;
|
||||
final double overflow = this.sink.injectExternalPower(PowerUnits.RF, offered,
|
||||
simulate ? Actionable.SIMULATE : Actionable.MODULATE);
|
||||
|
||||
return (int) (maxReceive - overflow);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int getEnergyStored() {
|
||||
return (int) Math.floor(PowerUnits.AE.convertTo(PowerUnits.RF, this.sink.getAECurrentPower()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int getMaxEnergyStored() {
|
||||
return (int) Math.floor(PowerUnits.AE.convertTo(PowerUnits.RF, this.sink.getAEMaxPower()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int extractEnergy(int maxExtract, boolean simulate) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExtract() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canReceive() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,45 +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.tile.powersink;
|
||||
|
||||
import appeng.api.config.Actionable;
|
||||
import appeng.api.config.PowerUnits;
|
||||
import appeng.api.networking.energy.IAEPowerStorage;
|
||||
|
||||
public interface IExternalPowerSink extends IAEPowerStorage {
|
||||
|
||||
/**
|
||||
* Inject power into the network
|
||||
*
|
||||
* @param externalUnit The {@link PowerUnits} used by the input
|
||||
* @param amount The amount offered to the sink.
|
||||
* @param mode Modulate or simulate the operation.
|
||||
* @return The unused amount, which could not be inserted into the sink.
|
||||
*/
|
||||
double injectExternalPower(PowerUnits externalUnit, double amount, Actionable mode);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param externalUnit The {@link PowerUnits} used by the input
|
||||
* @param maxPowerRequired Limit the demand to this upper bound.
|
||||
* @return The amount of power demanded by the sink.
|
||||
*/
|
||||
double getExternalPowerDemand(PowerUnits externalUnit, double maxPowerRequired);
|
||||
|
||||
}
|
||||
@@ -1,304 +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.tile.qnb;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Optional;
|
||||
|
||||
import alexiil.mc.lib.attributes.item.FixedItemInv;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.util.Tickable;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.util.math.Direction;
|
||||
|
||||
import net.minecraftforge.client.model.data.ModelDataMap;
|
||||
import net.minecraftforge.client.model.data.ModelProperty;
|
||||
import alexiil.mc.lib.attributes.item.impl.EmptyFixedItemInv;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.definitions.IBlockDefinition;
|
||||
import appeng.api.networking.GridFlags;
|
||||
import appeng.api.networking.events.MENetworkEventSubscribe;
|
||||
import appeng.api.networking.events.MENetworkPowerStatusChange;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
import appeng.api.util.DimensionalCoord;
|
||||
import appeng.block.qnb.QnbFormedState;
|
||||
import appeng.me.GridAccessException;
|
||||
import appeng.me.cluster.IAECluster;
|
||||
import appeng.me.cluster.IAEMultiBlock;
|
||||
import appeng.me.cluster.implementations.QuantumCalculator;
|
||||
import appeng.me.cluster.implementations.QuantumCluster;
|
||||
import appeng.tile.grid.AENetworkInvBlockEntity;
|
||||
import appeng.tile.inventory.AppEngInternalInventory;
|
||||
import appeng.util.inv.InvOperation;
|
||||
|
||||
public class QuantumBridgeBlockEntity extends AENetworkInvBlockEntity implements IAEMultiBlock, Tickable {
|
||||
|
||||
public static final ModelProperty<QnbFormedState> FORMED_STATE = new ModelProperty<>();
|
||||
|
||||
private final byte corner = 16;
|
||||
private final AppEngInternalInventory internalInventory = new AppEngInternalInventory(this, 1, 1);
|
||||
private final byte hasSingularity = 32;
|
||||
private final byte powered = 64;
|
||||
|
||||
private final QuantumCalculator calc = new QuantumCalculator(this);
|
||||
private byte constructed = -1;
|
||||
private QuantumCluster cluster;
|
||||
private boolean updateStatus = false;
|
||||
|
||||
public QuantumBridgeBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
this.getProxy().setValidSides(EnumSet.noneOf(Direction.class));
|
||||
this.getProxy().setFlags(GridFlags.DENSE_CAPACITY);
|
||||
this.getProxy().setIdlePowerUsage(22);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
if (this.updateStatus) {
|
||||
this.updateStatus = false;
|
||||
if (this.cluster != null) {
|
||||
this.cluster.updateStatus(true);
|
||||
}
|
||||
this.markForUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeToStream(final PacketByteBuf data) throws IOException {
|
||||
super.writeToStream(data);
|
||||
int out = this.constructed;
|
||||
|
||||
if (!this.internalInventory.getInvStack(0).isEmpty() && this.constructed != -1) {
|
||||
out |= this.hasSingularity;
|
||||
}
|
||||
|
||||
if (this.getProxy().isActive() && this.constructed != -1) {
|
||||
out |= this.powered;
|
||||
}
|
||||
|
||||
data.writeByte((byte) out);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean readFromStream(final PacketByteBuf data) throws IOException {
|
||||
final boolean c = super.readFromStream(data);
|
||||
final int oldValue = this.constructed;
|
||||
this.constructed = data.readByte();
|
||||
return this.constructed != oldValue || c;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FixedItemInv getInternalInventory() {
|
||||
return this.internalInventory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeInventory(final FixedItemInv inv, final int slot, final InvOperation mc,
|
||||
final ItemStack removed, final ItemStack added) {
|
||||
if (this.cluster != null) {
|
||||
this.cluster.updateStatus(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FixedItemInv getItemHandlerForSide(Direction side) {
|
||||
if (this.isCenter()) {
|
||||
return this.internalInventory;
|
||||
}
|
||||
return EmptyFixedItemInv.INSTANCE;
|
||||
}
|
||||
|
||||
private boolean isCenter() {
|
||||
return AEApi.instance().definitions().blocks().quantumLink().maybeBlock()
|
||||
.map(link -> getCachedState().getBlock() == link).orElse(false);
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void onPowerStatusChange(final MENetworkPowerStatusChange c) {
|
||||
this.updateStatus = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkUnloaded() {
|
||||
this.disconnect(false);
|
||||
super.onChunkUnloaded();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReady() {
|
||||
super.onReady();
|
||||
|
||||
final IBlockDefinition quantumRing = AEApi.instance().definitions().blocks().quantumRing();
|
||||
final Optional<Block> maybeLinkBlock = quantumRing.maybeBlock();
|
||||
final Optional<ItemStack> maybeLinkStack = quantumRing.maybeStack(1);
|
||||
|
||||
final boolean isPresent = maybeLinkBlock.isPresent() && maybeLinkStack.isPresent();
|
||||
|
||||
if (isPresent && getCachedState().getBlock() == maybeLinkBlock.get()) {
|
||||
final ItemStack linkStack = maybeLinkStack.get();
|
||||
|
||||
this.getProxy().setVisualRepresentation(linkStack);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
this.disconnect(false);
|
||||
super.remove();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect(final boolean affectWorld) {
|
||||
if (this.cluster != null) {
|
||||
if (!affectWorld) {
|
||||
this.cluster.setUpdateStatus(false);
|
||||
}
|
||||
|
||||
this.cluster.destroy();
|
||||
}
|
||||
|
||||
this.cluster = null;
|
||||
|
||||
if (affectWorld) {
|
||||
this.getProxy().setValidSides(EnumSet.noneOf(Direction.class));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAECluster getCluster() {
|
||||
return this.cluster;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return !this.isRemoved();
|
||||
}
|
||||
|
||||
public void updateStatus(final QuantumCluster c, final byte flags, final boolean affectWorld) {
|
||||
this.cluster = c;
|
||||
|
||||
if (affectWorld) {
|
||||
if (this.constructed != flags) {
|
||||
this.constructed = flags;
|
||||
this.markForUpdate();
|
||||
}
|
||||
|
||||
if (this.isCorner() || this.isCenter()) {
|
||||
final EnumSet<Direction> sides = EnumSet.noneOf(Direction.class);
|
||||
for (final Direction dir : this.getAdjacentQuantumBridges()) {
|
||||
sides.add(dir);
|
||||
}
|
||||
|
||||
this.getProxy().setValidSides(sides);
|
||||
} else {
|
||||
this.getProxy().setValidSides(EnumSet.allOf(Direction.class));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isCorner() {
|
||||
return (this.constructed & this.getCorner()) == this.getCorner() && this.constructed != -1;
|
||||
}
|
||||
|
||||
public EnumSet<Direction> getAdjacentQuantumBridges() {
|
||||
final EnumSet<Direction> set = EnumSet.noneOf(Direction.class);
|
||||
|
||||
for (final Direction d : Direction.values()) {
|
||||
final BlockEntity te = this.world.getBlockEntity(this.pos.offset(d));
|
||||
if (te instanceof QuantumBridgeBlockEntity) {
|
||||
set.add(d);
|
||||
}
|
||||
}
|
||||
|
||||
return set;
|
||||
}
|
||||
|
||||
public long getQEFrequency() {
|
||||
final ItemStack is = this.internalInventory.getInvStack(0);
|
||||
if (!is.isEmpty()) {
|
||||
final CompoundTag c = is.getTag();
|
||||
if (c != null) {
|
||||
return c.getLong("freq");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public boolean isPowered() {
|
||||
if (isClient()) {
|
||||
return (this.constructed & this.powered) == this.powered && this.constructed != -1;
|
||||
}
|
||||
|
||||
try {
|
||||
return this.getProxy().getEnergy().isNetworkPowered();
|
||||
} catch (final GridAccessException e) {
|
||||
// :P
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isFormed() {
|
||||
return this.constructed != -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AECableType getCableConnectionType(final AEPartLocation dir) {
|
||||
return AECableType.DENSE_SMART;
|
||||
}
|
||||
|
||||
public void neighborUpdate() {
|
||||
this.calc.calculateMultiblock(this.world, this.getLocation());
|
||||
}
|
||||
|
||||
@Override
|
||||
public DimensionalCoord getLocation() {
|
||||
return new DimensionalCoord(this);
|
||||
}
|
||||
|
||||
public boolean hasQES() {
|
||||
if (this.constructed == -1) {
|
||||
return false;
|
||||
}
|
||||
return (this.constructed & this.hasSingularity) == this.hasSingularity;
|
||||
}
|
||||
|
||||
public void breakCluster() {
|
||||
if (this.cluster != null) {
|
||||
this.cluster.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
public byte getCorner() {
|
||||
return this.corner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QnbFormedState getRenderAttachmentData() {
|
||||
return new QnbFormedState(getAdjacentQuantumBridges(), isCorner(), isPowered());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,197 +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.tile.spatial;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import alexiil.mc.lib.attributes.item.FixedItemInv;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import appeng.api.config.Actionable;
|
||||
import appeng.api.config.PowerMultiplier;
|
||||
import appeng.api.config.YesNo;
|
||||
import appeng.api.implementations.TransitionResult;
|
||||
import appeng.api.implementations.items.ISpatialStorageCell;
|
||||
import appeng.api.networking.GridFlags;
|
||||
import appeng.api.networking.IGrid;
|
||||
import appeng.api.networking.energy.IEnergyGrid;
|
||||
import appeng.api.networking.events.MENetworkEvent;
|
||||
import appeng.api.networking.events.MENetworkSpatialEvent;
|
||||
import appeng.api.networking.spatial.ISpatialCache;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
import appeng.api.util.DimensionalCoord;
|
||||
import appeng.hooks.TickHandler;
|
||||
import appeng.me.cache.SpatialPylonCache;
|
||||
import appeng.tile.grid.AENetworkInvBlockEntity;
|
||||
import appeng.tile.inventory.AppEngInternalInventory;
|
||||
import appeng.util.IWorldCallable;
|
||||
import appeng.util.Platform;
|
||||
import appeng.util.inv.InvOperation;
|
||||
import appeng.util.inv.WrapperFilteredItemHandler;
|
||||
import appeng.util.inv.filter.IAEItemFilter;
|
||||
|
||||
public class SpatialIOPortBlockEntity extends AENetworkInvBlockEntity implements IWorldCallable<Void> {
|
||||
|
||||
private final AppEngInternalInventory inv = new AppEngInternalInventory(this, 2);
|
||||
private final FixedItemInv invExt = new WrapperFilteredItemHandler(this.inv, new SpatialIOFilter());
|
||||
private YesNo lastRedstoneState = YesNo.UNDECIDED;
|
||||
|
||||
public SpatialIOPortBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
this.getProxy().setFlags(GridFlags.REQUIRE_CHANNEL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag toTag(final CompoundTag data) {
|
||||
super.toTag(data);
|
||||
data.putInt("lastRedstoneState", this.lastRedstoneState.ordinal());
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromTag(BlockState state, final CompoundTag data) {
|
||||
super.fromTag(state, data);
|
||||
if (data.contains("lastRedstoneState")) {
|
||||
this.lastRedstoneState = YesNo.values()[data.getInt("lastRedstoneState")];
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getRedstoneState() {
|
||||
if (this.lastRedstoneState == YesNo.UNDECIDED) {
|
||||
this.updateRedstoneState();
|
||||
}
|
||||
|
||||
return this.lastRedstoneState == YesNo.YES;
|
||||
}
|
||||
|
||||
public void updateRedstoneState() {
|
||||
final YesNo currentState = this.world.getReceivedRedstonePower(this.pos) != 0 ? YesNo.YES : YesNo.NO;
|
||||
if (this.lastRedstoneState != currentState) {
|
||||
this.lastRedstoneState = currentState;
|
||||
if (this.lastRedstoneState == YesNo.YES) {
|
||||
this.triggerTransition();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void triggerTransition() {
|
||||
if (Platform.isServer()) {
|
||||
final ItemStack cell = this.inv.getInvStack(0);
|
||||
if (this.isSpatialCell(cell)) {
|
||||
TickHandler.INSTANCE.addCallable(null, this);// this needs to be cross world synced.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isSpatialCell(final ItemStack cell) {
|
||||
if (!cell.isEmpty() && cell.getItem() instanceof ISpatialStorageCell) {
|
||||
final ISpatialStorageCell sc = (ISpatialStorageCell) cell.getItem();
|
||||
return sc != null && sc.isSpatialStorage(cell);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void call(final World world) throws Exception {
|
||||
if (!(world instanceof ServerWorld)) {
|
||||
return null;
|
||||
}
|
||||
ServerWorld serverWorld = (ServerWorld) world;
|
||||
|
||||
final ItemStack cell = this.inv.getInvStack(0);
|
||||
if (this.isSpatialCell(cell) && this.inv.getInvStack(1).isEmpty()) {
|
||||
final IGrid gi = this.getProxy().getGrid();
|
||||
final IEnergyGrid energy = this.getProxy().getEnergy();
|
||||
|
||||
final ISpatialStorageCell sc = (ISpatialStorageCell) cell.getItem();
|
||||
|
||||
final SpatialPylonCache spc = gi.getCache(ISpatialCache.class);
|
||||
if (spc.hasRegion() && spc.isValidRegion()) {
|
||||
final double req = spc.requiredPower();
|
||||
final double pr = energy.extractAEPower(req, Actionable.SIMULATE, PowerMultiplier.CONFIG);
|
||||
if (Math.abs(pr - req) < req * 0.001) {
|
||||
final MENetworkEvent res = gi.postEvent(new MENetworkSpatialEvent(this, req));
|
||||
if (!res.isCanceled()) {
|
||||
int playerId = -1;
|
||||
if (this.getProxy().getSecurity().isAvailable()) {
|
||||
playerId = this.getProxy().getSecurity().getOwner();
|
||||
}
|
||||
|
||||
final TransitionResult tr = sc.doSpatialTransition(cell, serverWorld, spc.getMin(), spc.getMax(),
|
||||
playerId);
|
||||
if (tr.success) {
|
||||
energy.extractAEPower(req, Actionable.MODULATE, PowerMultiplier.CONFIG);
|
||||
this.inv.setInvStack(0, ItemStack.EMPTY);
|
||||
this.inv.setInvStack(1, cell);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AECableType getCableConnectionType(final AEPartLocation dir) {
|
||||
return AECableType.SMART;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DimensionalCoord getLocation() {
|
||||
return new DimensionalCoord(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nonnull
|
||||
FixedItemInv getItemHandlerForSide(@Nonnull Direction side) {
|
||||
return this.invExt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FixedItemInv getInternalInventory() {
|
||||
return this.inv;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeInventory(final FixedItemInv inv, final int slot, final InvOperation mc,
|
||||
final ItemStack removed, final ItemStack added) {
|
||||
|
||||
}
|
||||
|
||||
private class SpatialIOFilter implements IAEItemFilter {
|
||||
@Override
|
||||
public boolean allowExtract(FixedItemInv inv, int slot, int amount) {
|
||||
return slot == 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowInsert(FixedItemInv inv, int slot, ItemStack stack) {
|
||||
return (slot == 0 && SpatialIOPortBlockEntity.this.isSpatialCell(stack));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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.tile.spatial;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.EnumSet;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.util.math.Direction;
|
||||
|
||||
import net.minecraftforge.client.model.data.ModelDataMap;
|
||||
import net.minecraftforge.client.model.data.ModelProperty;
|
||||
|
||||
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;
|
||||
import appeng.me.cluster.IAEMultiBlock;
|
||||
import appeng.me.cluster.implementations.SpatialPylonCalculator;
|
||||
import appeng.me.cluster.implementations.SpatialPylonCluster;
|
||||
import appeng.me.helpers.AENetworkProxy;
|
||||
import appeng.me.helpers.AENetworkProxyMultiblock;
|
||||
import appeng.tile.grid.AENetworkBlockEntity;
|
||||
|
||||
public class SpatialPylonBlockEntity extends AENetworkBlockEntity implements IAEMultiBlock {
|
||||
|
||||
public static final ModelProperty<Integer> STATE = new ModelProperty<>(value -> {
|
||||
// The lower 6 bits are used
|
||||
return (value & ~0x3F) == 0;
|
||||
});
|
||||
|
||||
public static final int DISPLAY_END_MIN = 0x01;
|
||||
public static final int DISPLAY_END_MAX = 0x02;
|
||||
public static final int DISPLAY_MIDDLE = 0x01 + 0x02;
|
||||
public static final int DISPLAY_X = 0x04;
|
||||
public static final int DISPLAY_Y = 0x08;
|
||||
public static final int DISPLAY_Z = 0x04 + 0x08;
|
||||
public static final int MB_STATUS = 0x01 + 0x02 + 0x04 + 0x08;
|
||||
|
||||
public static final int DISPLAY_ENABLED = 0x10;
|
||||
public static final int DISPLAY_POWERED_ENABLED = 0x20;
|
||||
public static final int NET_STATUS = 0x10 + 0x20;
|
||||
|
||||
private final SpatialPylonCalculator calc = new SpatialPylonCalculator(this);
|
||||
private int displayBits = 0;
|
||||
private SpatialPylonCluster cluster;
|
||||
private boolean didHaveLight = false;
|
||||
|
||||
public SpatialPylonBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
this.getProxy().setFlags(GridFlags.REQUIRE_CHANNEL, GridFlags.MULTIBLOCK);
|
||||
this.getProxy().setIdlePowerUsage(0.5);
|
||||
this.getProxy().setValidSides(EnumSet.noneOf(Direction.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AENetworkProxy createProxy() {
|
||||
return new AENetworkProxyMultiblock(this, "proxy", this.getItemFromTile(this), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkUnloaded() {
|
||||
this.disconnect(false);
|
||||
super.onChunkUnloaded();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReady() {
|
||||
super.onReady();
|
||||
this.neighborUpdate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
this.disconnect(false);
|
||||
super.remove();
|
||||
}
|
||||
|
||||
public void neighborUpdate() {
|
||||
this.calc.calculateMultiblock(this.world, this.getLocation());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect(final boolean b) {
|
||||
if (this.cluster != null) {
|
||||
this.cluster.destroy();
|
||||
this.updateStatus(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpatialPylonCluster getCluster() {
|
||||
return this.cluster;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void updateStatus(final SpatialPylonCluster c) {
|
||||
this.cluster = c;
|
||||
this.getProxy().setValidSides(c == null ? EnumSet.noneOf(Direction.class) : EnumSet.allOf(Direction.class));
|
||||
this.recalculateDisplay();
|
||||
}
|
||||
|
||||
public void recalculateDisplay() {
|
||||
final int oldBits = this.displayBits;
|
||||
|
||||
this.displayBits = 0;
|
||||
|
||||
if (this.cluster != null) {
|
||||
if (this.cluster.getMin().equals(this.getLocation())) {
|
||||
this.displayBits = DISPLAY_END_MIN;
|
||||
} else if (this.cluster.getMax().equals(this.getLocation())) {
|
||||
this.displayBits = DISPLAY_END_MAX;
|
||||
} else {
|
||||
this.displayBits = DISPLAY_MIDDLE;
|
||||
}
|
||||
|
||||
switch (this.cluster.getCurrentAxis()) {
|
||||
case X:
|
||||
this.displayBits |= DISPLAY_X;
|
||||
break;
|
||||
case Y:
|
||||
this.displayBits |= DISPLAY_Y;
|
||||
break;
|
||||
case Z:
|
||||
this.displayBits |= DISPLAY_Z;
|
||||
break;
|
||||
default:
|
||||
this.displayBits = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
if (this.getProxy().getEnergy().isNetworkPowered()) {
|
||||
this.displayBits |= DISPLAY_POWERED_ENABLED;
|
||||
}
|
||||
|
||||
if (this.cluster.isValid() && this.getProxy().isActive()) {
|
||||
this.displayBits |= DISPLAY_ENABLED;
|
||||
}
|
||||
} catch (final GridAccessException e) {
|
||||
// nothing?
|
||||
}
|
||||
}
|
||||
|
||||
if (oldBits != this.displayBits) {
|
||||
this.markForUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markForUpdate() {
|
||||
super.markForUpdate();
|
||||
final boolean hasLight = this.getLightValue() > 0;
|
||||
if (hasLight != this.didHaveLight) {
|
||||
this.didHaveLight = hasLight;
|
||||
this.world.getLightingProvider().checkBlock(this.pos);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeRotated() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getLightValue() {
|
||||
if ((this.displayBits & DISPLAY_POWERED_ENABLED) == DISPLAY_POWERED_ENABLED) {
|
||||
return 8;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean readFromStream(final PacketByteBuf data) throws IOException {
|
||||
final boolean c = super.readFromStream(data);
|
||||
final int old = this.displayBits;
|
||||
this.displayBits = data.readByte();
|
||||
return old != this.displayBits || c;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeToStream(final PacketByteBuf data) throws IOException {
|
||||
super.writeToStream(data);
|
||||
data.writeByte(this.displayBits);
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void powerRender(final MENetworkPowerStatusChange c) {
|
||||
this.recalculateDisplay();
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void activeRender(final MENetworkChannelsChanged c) {
|
||||
this.recalculateDisplay();
|
||||
}
|
||||
|
||||
public int getDisplayBits() {
|
||||
return this.displayBits;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getRenderAttachmentData() {
|
||||
return getDisplayBits();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,838 +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.tile.storage;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import alexiil.mc.lib.attributes.fluid.volume.FluidVolume;
|
||||
import alexiil.mc.lib.attributes.item.FixedItemInv;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.screen.ScreenHandlerType;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.util.Tickable;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.fluids.FluidAttributes;
|
||||
import net.minecraftforge.fluids.IFluidTank;
|
||||
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.config.AccessRestriction;
|
||||
import appeng.api.config.Actionable;
|
||||
import appeng.api.config.PowerMultiplier;
|
||||
import appeng.api.config.SecurityPermissions;
|
||||
import appeng.api.config.Settings;
|
||||
import appeng.api.config.SortDir;
|
||||
import appeng.api.config.SortOrder;
|
||||
import appeng.api.config.ViewItems;
|
||||
import appeng.api.implementations.tiles.IColorableTile;
|
||||
import appeng.api.implementations.tiles.IMEChest;
|
||||
import appeng.api.networking.GridFlags;
|
||||
import appeng.api.networking.IGrid;
|
||||
import appeng.api.networking.IGridNode;
|
||||
import appeng.api.networking.energy.IEnergyGrid;
|
||||
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.events.MENetworkPowerStorage;
|
||||
import appeng.api.networking.events.MENetworkPowerStorage.PowerEventType;
|
||||
import appeng.api.networking.security.IActionHost;
|
||||
import appeng.api.networking.security.IActionSource;
|
||||
import appeng.api.networking.security.ISecurityGrid;
|
||||
import appeng.api.networking.storage.IBaseMonitor;
|
||||
import appeng.api.networking.storage.IStorageGrid;
|
||||
import appeng.api.storage.IMEInventoryHandler;
|
||||
import appeng.api.storage.IMEMonitor;
|
||||
import appeng.api.storage.IMEMonitorHandlerReceiver;
|
||||
import appeng.api.storage.IStorageChannel;
|
||||
import appeng.api.storage.IStorageMonitorable;
|
||||
import appeng.api.storage.IStorageMonitorableAccessor;
|
||||
import appeng.api.storage.ITerminalHost;
|
||||
import appeng.api.storage.cells.CellState;
|
||||
import appeng.api.storage.cells.ICellGuiHandler;
|
||||
import appeng.api.storage.cells.ICellHandler;
|
||||
import appeng.api.storage.cells.ICellInventory;
|
||||
import appeng.api.storage.cells.ICellInventoryHandler;
|
||||
import appeng.api.storage.channels.IFluidStorageChannel;
|
||||
import appeng.api.storage.channels.IItemStorageChannel;
|
||||
import appeng.api.storage.data.IAEFluidStack;
|
||||
import appeng.api.storage.data.IAEItemStack;
|
||||
import appeng.api.storage.data.IAEStack;
|
||||
import appeng.api.util.AEColor;
|
||||
import appeng.api.util.IConfigManager;
|
||||
import appeng.capabilities.Capabilities;
|
||||
import appeng.container.implementations.MEMonitorableContainer;
|
||||
import appeng.fluids.container.FluidTerminalContainer;
|
||||
import appeng.fluids.util.AEFluidStack;
|
||||
import appeng.helpers.IPriorityHost;
|
||||
import appeng.me.GridAccessException;
|
||||
import appeng.me.helpers.MEMonitorHandler;
|
||||
import appeng.me.helpers.MachineSource;
|
||||
import appeng.me.storage.MEInventoryHandler;
|
||||
import appeng.tile.grid.AENetworkPowerBlockEntity;
|
||||
import appeng.tile.inventory.AppEngInternalInventory;
|
||||
import appeng.util.ConfigManager;
|
||||
import appeng.util.IConfigManagerHost;
|
||||
import appeng.util.Platform;
|
||||
import appeng.util.helpers.ItemHandlerUtil;
|
||||
import appeng.util.inv.InvOperation;
|
||||
import appeng.util.inv.WrapperChainedItemHandler;
|
||||
import appeng.util.inv.filter.IAEItemFilter;
|
||||
import appeng.util.item.AEItemStack;
|
||||
|
||||
public class ChestBlockEntity extends AENetworkPowerBlockEntity
|
||||
implements IMEChest, ITerminalHost, IPriorityHost, IConfigManagerHost, IColorableTile, Tickable {
|
||||
private final AppEngInternalInventory inputInventory = new AppEngInternalInventory(this, 1);
|
||||
private final AppEngInternalInventory cellInventory = new AppEngInternalInventory(this, 1);
|
||||
private final FixedItemInv internalInventory = new WrapperChainedItemHandler(this.inputInventory,
|
||||
this.cellInventory);
|
||||
|
||||
private final IActionSource mySrc = new MachineSource(this);
|
||||
private final IConfigManager config = new ConfigManager(this);
|
||||
private long lastStateChange = 0;
|
||||
private int priority = 0;
|
||||
private int state = 0;
|
||||
private boolean wasActive = false;
|
||||
private AEColor paintedColor = AEColor.TRANSPARENT;
|
||||
private boolean isCached = false;
|
||||
private ChestMonitorHandler cellHandler;
|
||||
private Accessor accessor;
|
||||
private IFluidHandler fluidHandler;
|
||||
|
||||
public ChestBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
this.setInternalMaxPower(PowerMultiplier.CONFIG.multiply(40));
|
||||
this.getProxy().setFlags(GridFlags.REQUIRE_CHANNEL);
|
||||
this.config.registerSetting(Settings.SORT_BY, SortOrder.NAME);
|
||||
this.config.registerSetting(Settings.VIEW_MODE, ViewItems.ALL);
|
||||
this.config.registerSetting(Settings.SORT_DIRECTION, SortDir.ASCENDING);
|
||||
|
||||
this.setInternalPublicPowerStorage(true);
|
||||
this.setInternalPowerFlow(AccessRestriction.WRITE);
|
||||
|
||||
this.inputInventory.setFilter(new InputInventoryFilter());
|
||||
this.cellInventory.setFilter(new CellInventoryFilter());
|
||||
}
|
||||
|
||||
public ItemStack getCell() {
|
||||
return this.cellInventory.getInvStack(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void PowerEvent(final PowerEventType x) {
|
||||
if (x == PowerEventType.REQUEST_POWER) {
|
||||
try {
|
||||
this.getProxy().getGrid().postEvent(new MENetworkPowerStorage(this, PowerEventType.REQUEST_POWER));
|
||||
} catch (final GridAccessException e) {
|
||||
// :(
|
||||
}
|
||||
} else {
|
||||
this.recalculateDisplay();
|
||||
}
|
||||
}
|
||||
|
||||
private void recalculateDisplay() {
|
||||
final int oldState = this.state;
|
||||
|
||||
for (int x = 0; x < this.getCellCount(); x++) {
|
||||
this.state |= (this.getCellStatus(x).ordinal() << (3 * x));
|
||||
}
|
||||
|
||||
if (this.isPowered()) {
|
||||
this.state |= 0x40;
|
||||
} else {
|
||||
this.state &= ~0x40;
|
||||
}
|
||||
|
||||
final boolean currentActive = this.getProxy().isActive();
|
||||
if (this.wasActive != currentActive) {
|
||||
this.wasActive = currentActive;
|
||||
try {
|
||||
this.getProxy().getGrid().postEvent(new MENetworkCellArrayUpdate());
|
||||
} catch (final GridAccessException e) {
|
||||
// :P
|
||||
}
|
||||
}
|
||||
|
||||
if (oldState != this.state) {
|
||||
this.markForUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCellCount() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void updateHandler() {
|
||||
if (!this.isCached) {
|
||||
this.cellHandler = null;
|
||||
this.accessor = null;
|
||||
this.fluidHandler = null;
|
||||
|
||||
final ItemStack is = this.getCell();
|
||||
if (!is.isEmpty()) {
|
||||
this.isCached = true;
|
||||
ICellHandler cellHandler = AEApi.instance().registries().cell().getHandler(is);
|
||||
if (cellHandler != null) {
|
||||
double power = 1.0;
|
||||
|
||||
for (IStorageChannel channel : AEApi.instance().storage().storageChannels()) {
|
||||
final ICellInventoryHandler<IAEItemStack> newCell = cellHandler.getCellInventory(is, this,
|
||||
channel);
|
||||
if (newCell != null) {
|
||||
power += cellHandler.cellIdleDrain(is, newCell);
|
||||
this.cellHandler = this.wrap(newCell);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.getProxy().setIdlePowerUsage(power);
|
||||
this.accessor = new Accessor();
|
||||
|
||||
if (this.cellHandler != null && this.cellHandler.getChannel() == AEApi.instance().storage()
|
||||
.getStorageChannel(IFluidStorageChannel.class)) {
|
||||
this.fluidHandler = new FluidHandler();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private <T extends IAEStack<T>> ChestMonitorHandler<T> wrap(final IMEInventoryHandler<T> h) {
|
||||
if (h == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final MEInventoryHandler<T> ih = new MEInventoryHandler<T>(h, h.getChannel());
|
||||
ih.setPriority(this.priority);
|
||||
|
||||
final ChestMonitorHandler<T> g = new ChestMonitorHandler<T>(ih);
|
||||
g.addListener(new ChestNetNotifier<T>(h.getChannel()), g);
|
||||
|
||||
return g;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CellState getCellStatus(final int slot) {
|
||||
if (isClient()) {
|
||||
return CellState.values()[(this.state >> (slot * 3)) & 3];
|
||||
}
|
||||
|
||||
this.updateHandler();
|
||||
|
||||
final ItemStack cell = this.getCell();
|
||||
final ICellHandler ch = AEApi.instance().registries().cell().getHandler(cell);
|
||||
|
||||
if (this.cellHandler != null && ch != null) {
|
||||
return ch.getStatusForCell(cell, this.cellHandler.getInternalHandler());
|
||||
}
|
||||
|
||||
return CellState.ABSENT;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Item getCellItem(int slot) {
|
||||
if (slot != 0) {
|
||||
return null;
|
||||
}
|
||||
ItemStack cell = getCell();
|
||||
return cell.isEmpty() ? null : cell.getItem();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPowered() {
|
||||
if (isClient()) {
|
||||
return (this.state & 0x40) == 0x40;
|
||||
}
|
||||
|
||||
boolean gridPowered = this.getAECurrentPower() > 64;
|
||||
|
||||
if (!gridPowered) {
|
||||
try {
|
||||
gridPowered = this.getProxy().getEnergy().isNetworkPowered();
|
||||
} catch (final GridAccessException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
return super.getAECurrentPower() > 1 || gridPowered;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCellBlinking(final int slot) {
|
||||
final long now = this.world.getGameTime();
|
||||
if (now - this.lastStateChange > 8) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((this.state >> (slot * 3 + 2)) & 0x01) == 0x01;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double extractAEPower(final double amt, final Actionable mode) {
|
||||
double stash = 0.0;
|
||||
|
||||
try {
|
||||
final IEnergyGrid eg = this.getProxy().getEnergy();
|
||||
stash = eg.extractAEPower(amt, mode, PowerMultiplier.ONE);
|
||||
if (stash >= amt) {
|
||||
return stash;
|
||||
}
|
||||
} catch (final GridAccessException e) {
|
||||
// no grid :(
|
||||
}
|
||||
|
||||
// local battery!
|
||||
return super.extractAEPower(amt - stash, mode) + stash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
if (this.world.isClient) {
|
||||
return;
|
||||
}
|
||||
|
||||
final double idleUsage = this.getProxy().getIdlePowerUsage();
|
||||
|
||||
try {
|
||||
if (!this.getProxy().getEnergy().isNetworkPowered()) {
|
||||
final double powerUsed = this.extractAEPower(idleUsage, Actionable.MODULATE, PowerMultiplier.CONFIG); // drain
|
||||
if (powerUsed + 0.1 >= idleUsage != (this.state & 0x40) > 0) {
|
||||
this.recalculateDisplay();
|
||||
}
|
||||
}
|
||||
} catch (final GridAccessException e) {
|
||||
final double powerUsed = this.extractAEPower(this.getProxy().getIdlePowerUsage(), Actionable.MODULATE,
|
||||
PowerMultiplier.CONFIG); // drain
|
||||
if (powerUsed + 0.1 >= idleUsage != (this.state & 0x40) > 0) {
|
||||
this.recalculateDisplay();
|
||||
}
|
||||
}
|
||||
|
||||
if (!ItemHandlerUtil.isEmpty(this.inputInventory)) {
|
||||
this.tryToStoreContents();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeToStream(final PacketByteBuf data) throws IOException {
|
||||
super.writeToStream(data);
|
||||
|
||||
if (this.world.getGameTime() - this.lastStateChange > 8) {
|
||||
this.state = 0;
|
||||
} else {
|
||||
this.state &= 0x24924924; // just keep the blinks...
|
||||
}
|
||||
|
||||
for (int x = 0; x < this.getCellCount(); x++) {
|
||||
this.state |= (this.getCellStatus(x).ordinal() << (3 * x));
|
||||
}
|
||||
|
||||
if (this.isPowered()) {
|
||||
this.state |= 0x40;
|
||||
} else {
|
||||
this.state &= ~0x40;
|
||||
}
|
||||
|
||||
data.writeByte(this.state);
|
||||
data.writeByte(this.paintedColor.ordinal());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean readFromStream(final PacketByteBuf data) throws IOException {
|
||||
final boolean c = super.readFromStream(data);
|
||||
|
||||
final int oldState = this.state;
|
||||
|
||||
this.state = data.readByte();
|
||||
final AEColor oldPaintedColor = this.paintedColor;
|
||||
this.paintedColor = AEColor.values()[data.readByte()];
|
||||
|
||||
this.lastStateChange = this.world.getGameTime();
|
||||
|
||||
return oldPaintedColor != this.paintedColor || (this.state & 0xDB6DB6DB) != (oldState & 0xDB6DB6DB) || c;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromTag(BlockState state, final CompoundTag data) {
|
||||
super.fromTag(state, data);
|
||||
this.config.readFromNBT(data);
|
||||
this.priority = data.getInt("priority");
|
||||
if (data.contains("paintedColor")) {
|
||||
this.paintedColor = AEColor.values()[data.getByte("paintedColor")];
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag toTag(final CompoundTag data) {
|
||||
super.toTag(data);
|
||||
this.config.writeToNBT(data);
|
||||
data.putInt("priority", this.priority);
|
||||
data.putByte("paintedColor", (byte) this.paintedColor.ordinal());
|
||||
return data;
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void powerRender(final MENetworkPowerStatusChange c) {
|
||||
this.recalculateDisplay();
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void channelRender(final MENetworkChannelsChanged c) {
|
||||
this.recalculateDisplay();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T extends IAEStack<T>> IMEMonitor<T> getInventory(IStorageChannel<T> channel) {
|
||||
this.updateHandler();
|
||||
|
||||
if (this.cellHandler != null && this.cellHandler.getChannel() == channel) {
|
||||
return this.cellHandler;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FixedItemInv getInternalInventory() {
|
||||
return this.internalInventory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeInventory(final FixedItemInv inv, final int slot, final InvOperation mc,
|
||||
final ItemStack removed, final ItemStack added) {
|
||||
if (inv == this.cellInventory) {
|
||||
this.cellHandler = null;
|
||||
this.isCached = false; // recalculate the storage cell.
|
||||
|
||||
try {
|
||||
this.getProxy().getGrid().postEvent(new MENetworkCellArrayUpdate());
|
||||
final IStorageGrid gs = this.getProxy().getStorage();
|
||||
Platform.postChanges(gs, removed, added, this.mySrc);
|
||||
} catch (final GridAccessException ignored) {
|
||||
|
||||
}
|
||||
|
||||
// update the neighbors
|
||||
if (this.world != null) {
|
||||
Platform.notifyBlocksOfNeighbors(this.world, this.pos);
|
||||
this.markForUpdate();
|
||||
}
|
||||
}
|
||||
if (inv == this.inputInventory && mc == InvOperation.INSERT) {
|
||||
this.tryToStoreContents();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FixedItemInv getItemHandlerForSide(@Nonnull Direction side) {
|
||||
if (side == this.getForward()) {
|
||||
return this.cellInventory;
|
||||
} else {
|
||||
return this.inputInventory;
|
||||
}
|
||||
}
|
||||
|
||||
private void tryToStoreContents() {
|
||||
if (!ItemHandlerUtil.isEmpty(this.inputInventory)) {
|
||||
this.updateHandler();
|
||||
|
||||
if (this.cellHandler != null && this.cellHandler.getChannel() == AEApi.instance().storage()
|
||||
.getStorageChannel(IItemStorageChannel.class)) {
|
||||
final IAEItemStack returns = Platform.poweredInsert(this, this.cellHandler,
|
||||
AEItemStack.fromItemStack(this.inputInventory.getInvStack(0)), this.mySrc);
|
||||
|
||||
if (returns == null) {
|
||||
this.inputInventory.setInvStack(0, ItemStack.EMPTY);
|
||||
} else {
|
||||
this.inputInventory.setInvStack(0, returns.createItemStack());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IMEInventoryHandler> getCellArray(final IStorageChannel channel) {
|
||||
if (this.getProxy().isActive()) {
|
||||
this.updateHandler();
|
||||
|
||||
if (this.cellHandler != null && this.cellHandler.getChannel() == channel) {
|
||||
return Collections.singletonList(this.cellHandler);
|
||||
}
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return this.priority;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPriority(final int newValue) {
|
||||
this.priority = newValue;
|
||||
this.cellHandler = null;
|
||||
this.isCached = false; // recalculate the storage cell.
|
||||
|
||||
try {
|
||||
this.getProxy().getGrid().postEvent(new MENetworkCellArrayUpdate());
|
||||
} catch (final GridAccessException e) {
|
||||
// :P
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void blinkCell(final int slot) {
|
||||
final long now = this.world.getGameTime();
|
||||
if (now - this.lastStateChange > 8) {
|
||||
this.state = 0;
|
||||
}
|
||||
this.lastStateChange = now;
|
||||
|
||||
this.state |= 1 << (slot * 3 + 2);
|
||||
|
||||
this.recalculateDisplay();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IConfigManager getConfigManager() {
|
||||
return this.config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSetting(final IConfigManager manager, final Settings settingName, final Enum<?> newValue) {
|
||||
|
||||
}
|
||||
|
||||
public boolean openGui(final PlayerEntity p) {
|
||||
this.updateHandler();
|
||||
if (this.cellHandler != null) {
|
||||
final ICellHandler ch = AEApi.instance().registries().cell().getHandler(this.getCell());
|
||||
|
||||
if (ch != null) {
|
||||
final ICellGuiHandler chg = AEApi.instance().registries().cell()
|
||||
.getGuiHandler(this.cellHandler.getChannel(), this.getCell());
|
||||
if (chg != null) {
|
||||
chg.openChestGui(p, this, ch, this.cellHandler, this.getCell(), this.cellHandler.getChannel());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AEColor getColor() {
|
||||
return this.paintedColor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean recolourBlock(final Direction side, final AEColor newPaintedColor, final PlayerEntity who) {
|
||||
if (this.paintedColor == newPaintedColor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.paintedColor = newPaintedColor;
|
||||
this.saveChanges();
|
||||
this.markForUpdate();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveChanges(final ICellInventory<?> cellInventory) {
|
||||
if (cellInventory != null) {
|
||||
cellInventory.persist();
|
||||
}
|
||||
this.world.markDirty(this.pos, this);
|
||||
}
|
||||
|
||||
private class ChestNetNotifier<T extends IAEStack<T>> implements IMEMonitorHandlerReceiver<T> {
|
||||
|
||||
private final IStorageChannel<T> chan;
|
||||
|
||||
public ChestNetNotifier(final IStorageChannel<T> chan) {
|
||||
this.chan = chan;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(final Object verificationToken) {
|
||||
ChestBlockEntity.this.updateHandler();
|
||||
if (ChestBlockEntity.this.cellHandler != null
|
||||
&& this.chan == ChestBlockEntity.this.cellHandler.getChannel()) {
|
||||
return verificationToken == ChestBlockEntity.this.cellHandler;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postChange(final IBaseMonitor<T> monitor, final Iterable<T> change, final IActionSource source) {
|
||||
if (source == ChestBlockEntity.this.mySrc
|
||||
|| source.machine().map(machine -> machine == ChestBlockEntity.this).orElse(false)) {
|
||||
try {
|
||||
if (ChestBlockEntity.this.getProxy().isActive()) {
|
||||
ChestBlockEntity.this.getProxy().getStorage().postAlterationOfStoredItems(this.chan, change,
|
||||
ChestBlockEntity.this.mySrc);
|
||||
}
|
||||
} catch (final GridAccessException e) {
|
||||
// :(
|
||||
}
|
||||
}
|
||||
|
||||
ChestBlockEntity.this.blinkCell(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onListUpdate() {
|
||||
// not used here
|
||||
}
|
||||
}
|
||||
|
||||
private class ChestMonitorHandler<T extends IAEStack<T>> extends MEMonitorHandler<T> {
|
||||
|
||||
public ChestMonitorHandler(final IMEInventoryHandler<T> t) {
|
||||
super(t);
|
||||
}
|
||||
|
||||
private ICellInventoryHandler<T> getInternalHandler() {
|
||||
final IMEInventoryHandler<T> h = this.getHandler();
|
||||
if (h instanceof MEInventoryHandler) {
|
||||
return (ICellInventoryHandler<T>) ((MEInventoryHandler<T>) h).getInternal();
|
||||
}
|
||||
return (ICellInventoryHandler<T>) this.getHandler();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T injectItems(final T input, final Actionable mode, final IActionSource src) {
|
||||
if (src.player().map(player -> !this.securityCheck(player, SecurityPermissions.INJECT)).orElse(false)) {
|
||||
return input;
|
||||
}
|
||||
return super.injectItems(input, mode, src);
|
||||
}
|
||||
|
||||
private boolean securityCheck(final PlayerEntity player, final SecurityPermissions requiredPermission) {
|
||||
if (ChestBlockEntity.this.getTile() instanceof IActionHost && requiredPermission != null) {
|
||||
|
||||
final IGridNode gn = ((IActionHost) ChestBlockEntity.this.getTile()).getActionableNode();
|
||||
if (gn != null) {
|
||||
final IGrid g = gn.getGrid();
|
||||
if (g != null) {
|
||||
final boolean requirePower = false;
|
||||
if (requirePower) {
|
||||
final IEnergyGrid eg = g.getCache(IEnergyGrid.class);
|
||||
if (!eg.isNetworkPowered()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
final ISecurityGrid sg = g.getCache(ISecurityGrid.class);
|
||||
if (sg.hasPermission(player, requiredPermission)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T extractItems(final T request, final Actionable mode, final IActionSource src) {
|
||||
if (src.player().map(player -> !this.securityCheck(player, SecurityPermissions.EXTRACT)).orElse(false)) {
|
||||
return null;
|
||||
}
|
||||
return super.extractItems(request, mode, src);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> LazyOptional<T> getCapability(Capability<T> capability, @Nullable Direction facing) {
|
||||
this.updateHandler();
|
||||
if (capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY && this.fluidHandler != null
|
||||
&& facing != this.getForward()) {
|
||||
return (LazyOptional<T>) LazyOptional.of(() -> this.fluidHandler);
|
||||
}
|
||||
if (capability == Capabilities.STORAGE_MONITORABLE_ACCESSOR && this.accessor != null
|
||||
&& facing != this.getForward()) {
|
||||
return (LazyOptional<T>) LazyOptional.of(() -> this.accessor);
|
||||
}
|
||||
return super.getCapability(capability, facing);
|
||||
}
|
||||
|
||||
private class Accessor implements IStorageMonitorableAccessor {
|
||||
@Nullable
|
||||
@Override
|
||||
public IStorageMonitorable getInventory(IActionSource src) {
|
||||
if (Platform.canAccess(ChestBlockEntity.this.getProxy(), src)) {
|
||||
return ChestBlockEntity.this;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private class FluidHandler implements IFluidHandler, IFluidTank {
|
||||
|
||||
private boolean canAcceptLiquids() {
|
||||
return ChestBlockEntity.this.cellHandler != null && ChestBlockEntity.this.cellHandler.getChannel() == AEApi
|
||||
.instance().storage().getStorageChannel(IFluidStorageChannel.class);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public FluidVolume getFluid() {
|
||||
return FluidVolumeUtil.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFluidAmount() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCapacity() {
|
||||
return canAcceptLiquids() ? FluidAttributes.BUCKET_VOLUME : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFluidValid(FluidVolume stack) {
|
||||
return canAcceptLiquids();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTanks() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public FluidVolume getFluidInTank(int tank) {
|
||||
return FluidVolumeUtil.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTankCapacity(int tank) {
|
||||
return tank == 0 ? FluidAttributes.BUCKET_VOLUME : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFluidValid(int tank, @Nonnull FluidVolume stack) {
|
||||
return tank == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int fill(FluidVolume resource, FluidAction action) {
|
||||
ChestBlockEntity.this.updateHandler();
|
||||
if (canAcceptLiquids()) {
|
||||
final IAEFluidStack results = Platform.poweredInsert(ChestBlockEntity.this,
|
||||
ChestBlockEntity.this.cellHandler, AEFluidStack.fromFluidStack(resource),
|
||||
ChestBlockEntity.this.mySrc,
|
||||
action == FluidAction.EXECUTE ? Actionable.MODULATE : Actionable.SIMULATE);
|
||||
|
||||
if (results == null) {
|
||||
return resource.getAmount();
|
||||
}
|
||||
return resource.getAmount() - (int) results.getStackSize();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public FluidVolume drain(FluidVolume resource, FluidAction action) {
|
||||
return FluidVolumeUtil.EMPTY;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public FluidVolume drain(int maxDrain, FluidAction action) {
|
||||
return FluidVolumeUtil.EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
private class InputInventoryFilter implements IAEItemFilter {
|
||||
@Override
|
||||
public boolean allowExtract(FixedItemInv inv, int slot, int amount) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowInsert(FixedItemInv inv, int slot, ItemStack stack) {
|
||||
if (ChestBlockEntity.this.isPowered()) {
|
||||
ChestBlockEntity.this.updateHandler();
|
||||
return ChestBlockEntity.this.cellHandler != null && ChestBlockEntity.this.cellHandler
|
||||
.getChannel() == AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static class CellInventoryFilter implements IAEItemFilter {
|
||||
|
||||
@Override
|
||||
public boolean allowExtract(FixedItemInv inv, int slot, int amount) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowInsert(FixedItemInv inv, int slot, ItemStack stack) {
|
||||
return AEApi.instance().registries().cell().getHandler(stack) != null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemStackRepresentation() {
|
||||
return AEApi.instance().definitions().blocks().chest().maybeStack(1).orElse(ItemStack.EMPTY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScreenHandlerType<?> getContainerType() {
|
||||
this.updateHandler();
|
||||
if (this.cellHandler != null) {
|
||||
if (this.cellHandler.getChannel() == AEApi.instance().storage()
|
||||
.getStorageChannel(IItemStorageChannel.class)) {
|
||||
return MEMonitorableContainer.TYPE;
|
||||
}
|
||||
if (this.cellHandler.getChannel() == AEApi.instance().storage()
|
||||
.getStorageChannel(IFluidStorageChannel.class)) {
|
||||
return FluidTerminalContainer.TYPE;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,457 +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.tile.storage;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import alexiil.mc.lib.attributes.item.FixedItemInv;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.screen.ScreenHandlerType;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.implementations.tiles.IChestOrDrive;
|
||||
import appeng.api.networking.GridFlags;
|
||||
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.IStorageGrid;
|
||||
import appeng.api.storage.IMEInventoryHandler;
|
||||
import appeng.api.storage.IStorageChannel;
|
||||
import appeng.api.storage.cells.CellState;
|
||||
import appeng.api.storage.cells.ICellHandler;
|
||||
import appeng.api.storage.cells.ICellInventory;
|
||||
import appeng.api.storage.cells.ICellInventoryHandler;
|
||||
import appeng.api.storage.data.IAEItemStack;
|
||||
import appeng.api.storage.data.IAEStack;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
import appeng.api.util.DimensionalCoord;
|
||||
import appeng.block.storage.DriveSlotsState;
|
||||
import appeng.client.render.model.DriveModelData;
|
||||
import appeng.container.implementations.DriveContainer;
|
||||
import appeng.helpers.IPriorityHost;
|
||||
import appeng.me.GridAccessException;
|
||||
import appeng.me.helpers.MachineSource;
|
||||
import appeng.me.storage.DriveWatcher;
|
||||
import appeng.tile.grid.AENetworkInvBlockEntity;
|
||||
import appeng.tile.inventory.AppEngCellInventory;
|
||||
import appeng.util.Platform;
|
||||
import appeng.util.inv.InvOperation;
|
||||
import appeng.util.inv.filter.IAEItemFilter;
|
||||
|
||||
public class DriveBlockEntity extends AENetworkInvBlockEntity implements IChestOrDrive, IPriorityHost {
|
||||
|
||||
private static final int BIT_POWER_MASK = 0x80000000;
|
||||
private static final int BIT_BLINK_MASK = 0x24924924;
|
||||
private static final int BIT_STATE_MASK = 0xDB6DB6DB;
|
||||
|
||||
private final AppEngCellInventory inv = new AppEngCellInventory(this, 10);
|
||||
private final ICellHandler[] handlersBySlot = new ICellHandler[10];
|
||||
private final DriveWatcher<IAEItemStack>[] invBySlot = new DriveWatcher[10];
|
||||
private final IActionSource mySrc;
|
||||
private boolean isCached = false;
|
||||
private Map<IStorageChannel<? extends IAEStack<?>>, List<IMEInventoryHandler>> inventoryHandlers;
|
||||
private int priority = 0;
|
||||
private boolean wasActive = false;
|
||||
// This is only used on the client
|
||||
private final Item[] cellItems = new Item[10];
|
||||
|
||||
/**
|
||||
* The state of all cells inside a drive as bitset, using the following format.
|
||||
*
|
||||
* Bit 31: power state. 0 = off, 1 = on. Bit 30: undefined Bit 29-0: 3 bits as
|
||||
* state of each cell with the cell in slot 0 located in the 3 least significant
|
||||
* bits.
|
||||
*
|
||||
* Cell states: Bit 2: blink. 0 = off, 1 = on. Bit 1-0: cell status
|
||||
*
|
||||
*
|
||||
*/
|
||||
private int state = 0;
|
||||
|
||||
public DriveBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
this.mySrc = new MachineSource(this);
|
||||
this.getProxy().setFlags(GridFlags.REQUIRE_CHANNEL);
|
||||
this.inv.setFilter(new CellValidInventoryFilter());
|
||||
this.inventoryHandlers = new IdentityHashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOrientation(Direction inForward, Direction inUp) {
|
||||
super.setOrientation(inForward, inUp);
|
||||
this.getProxy().setValidSides(EnumSet.complementOf(EnumSet.of(inForward)));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeToStream(final PacketByteBuf data) throws IOException {
|
||||
super.writeToStream(data);
|
||||
int newState = 0;
|
||||
|
||||
if (this.getProxy().isActive()) {
|
||||
newState |= BIT_POWER_MASK;
|
||||
}
|
||||
for (int x = 0; x < this.getCellCount(); x++) {
|
||||
newState |= (this.getCellStatus(x).ordinal() << (3 * x));
|
||||
}
|
||||
data.writeInt(newState);
|
||||
|
||||
writeCellItemIds(data);
|
||||
}
|
||||
|
||||
private void writeCellItemIds(PacketByteBuf data) {
|
||||
List<Identifier> cellItemIds = new ArrayList<>(getCellCount());
|
||||
byte[] bm = new byte[getCellCount()];
|
||||
for (int x = 0; x < this.getCellCount(); x++) {
|
||||
Item item = getCellItem(x);
|
||||
if (item != null && item.getRegistryName() != null) {
|
||||
Identifier itemId = item.getRegistryName();
|
||||
int idx = cellItemIds.indexOf(itemId);
|
||||
if (idx == -1) {
|
||||
cellItemIds.add(itemId);
|
||||
bm[x] = (byte) cellItemIds.size(); // We use 1-based in bm[]
|
||||
} else {
|
||||
bm[x] = (byte) (1 + idx); // 1-based indexing!!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Write out the list of unique cell item ids
|
||||
data.writeByte(cellItemIds.size());
|
||||
for (Identifier itemId : cellItemIds) {
|
||||
data.writeResourceLocation(itemId);
|
||||
}
|
||||
// Then the lookup table for each slot
|
||||
for (int i = 0; i < getCellCount(); i++) {
|
||||
data.writeByte(bm[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean readFromStream(final PacketByteBuf data) throws IOException {
|
||||
boolean c = super.readFromStream(data);
|
||||
final int oldState = this.state;
|
||||
this.state = data.readInt();
|
||||
|
||||
c |= this.readCellItemIDs(data);
|
||||
|
||||
return (this.state & BIT_STATE_MASK) != (oldState & BIT_STATE_MASK) || c;
|
||||
}
|
||||
|
||||
private boolean readCellItemIDs(final PacketByteBuf data) {
|
||||
int uniqueStrCount = data.readByte();
|
||||
String[] uniqueStrs = new String[uniqueStrCount];
|
||||
for (int i = 0; i < uniqueStrCount; i++) {
|
||||
uniqueStrs[i] = data.readString();
|
||||
}
|
||||
|
||||
boolean changed = false;
|
||||
for (int i = 0; i < getCellCount(); i++) {
|
||||
byte idx = data.readByte();
|
||||
|
||||
// an index of 0 indicates the slot is empty
|
||||
Item item = null;
|
||||
if (idx > 0) {
|
||||
--idx;
|
||||
String itemId = uniqueStrs[idx];
|
||||
item = Registry.ITEM.get(new Identifier(itemId));
|
||||
}
|
||||
if (cellItems[i] != item) {
|
||||
changed = true;
|
||||
cellItems[i] = item;
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCellCount() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Item getCellItem(int slot) {
|
||||
// Client-side we'll need to actually use the synced state
|
||||
if (world == null || world.isClient) {
|
||||
return cellItems[slot];
|
||||
}
|
||||
|
||||
ItemStack stackInSlot = inv.getInvStack(slot);
|
||||
if (!stackInSlot.isEmpty()) {
|
||||
return stackInSlot.getItem();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CellState getCellStatus(final int slot) {
|
||||
if (Platform.isClient()) {
|
||||
return CellState.values()[(this.state >> (slot * 3)) & 3];
|
||||
}
|
||||
|
||||
final DriveWatcher handler = this.invBySlot[slot];
|
||||
if (handler == null) {
|
||||
return CellState.ABSENT;
|
||||
}
|
||||
|
||||
return handler.getStatus();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPowered() {
|
||||
if (isClient()) {
|
||||
return (this.state & BIT_POWER_MASK) == BIT_POWER_MASK;
|
||||
}
|
||||
|
||||
return this.getProxy().isActive();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCellBlinking(final int slot) {
|
||||
return ((this.state >> (slot * 3 + 2)) & 0x01) == 0x01;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromTag(BlockState state, final CompoundTag data) {
|
||||
super.fromTag(state, data);
|
||||
this.isCached = false;
|
||||
this.priority = data.getInt("priority");
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag toTag(final CompoundTag data) {
|
||||
super.toTag(data);
|
||||
data.putInt("priority", this.priority);
|
||||
return data;
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void powerRender(final MENetworkPowerStatusChange c) {
|
||||
this.recalculateDisplay();
|
||||
}
|
||||
|
||||
private void recalculateDisplay() {
|
||||
final boolean currentActive = this.getProxy().isActive();
|
||||
int newState = 0;
|
||||
|
||||
if (currentActive) {
|
||||
newState |= BIT_POWER_MASK;
|
||||
}
|
||||
|
||||
if (this.wasActive != currentActive) {
|
||||
this.wasActive = currentActive;
|
||||
try {
|
||||
this.getProxy().getGrid().postEvent(new MENetworkCellArrayUpdate());
|
||||
} catch (final GridAccessException e) {
|
||||
// :P
|
||||
}
|
||||
}
|
||||
|
||||
for (int x = 0; x < this.getCellCount(); x++) {
|
||||
newState |= (this.getCellStatus(x).ordinal() << (3 * x));
|
||||
}
|
||||
|
||||
if (newState != this.state) {
|
||||
this.state = newState;
|
||||
this.markForUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void channelRender(final MENetworkChannelsChanged c) {
|
||||
this.recalculateDisplay();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AECableType getCableConnectionType(final AEPartLocation dir) {
|
||||
return AECableType.SMART;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DimensionalCoord getLocation() {
|
||||
return new DimensionalCoord(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FixedItemInv getInternalInventory() {
|
||||
return this.inv;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeInventory(final FixedItemInv inv, final int slot, final InvOperation mc,
|
||||
final ItemStack removed, final ItemStack added) {
|
||||
if (this.isCached) {
|
||||
this.isCached = false; // recalculate the storage cell.
|
||||
this.updateState();
|
||||
}
|
||||
|
||||
try {
|
||||
this.getProxy().getGrid().postEvent(new MENetworkCellArrayUpdate());
|
||||
|
||||
final IStorageGrid gs = this.getProxy().getStorage();
|
||||
Platform.postChanges(gs, removed, added, this.mySrc);
|
||||
} catch (final GridAccessException ignored) {
|
||||
}
|
||||
|
||||
this.markForUpdate();
|
||||
}
|
||||
|
||||
private void updateState() {
|
||||
if (!this.isCached) {
|
||||
final Collection<IStorageChannel<? extends IAEStack<?>>> storageChannels = AEApi.instance().storage()
|
||||
.storageChannels();
|
||||
storageChannels.forEach(channel -> this.inventoryHandlers.put(channel, new ArrayList<>(10)));
|
||||
|
||||
double power = 2.0;
|
||||
|
||||
for (int x = 0; x < this.inv.getSlotCount(); x++) {
|
||||
final ItemStack is = this.inv.getInvStack(x);
|
||||
this.invBySlot[x] = null;
|
||||
this.handlersBySlot[x] = null;
|
||||
|
||||
if (!is.isEmpty()) {
|
||||
this.handlersBySlot[x] = AEApi.instance().registries().cell().getHandler(is);
|
||||
|
||||
if (this.handlersBySlot[x] != null) {
|
||||
for (IStorageChannel<? extends IAEStack<?>> channel : storageChannels) {
|
||||
|
||||
ICellInventoryHandler cell = this.handlersBySlot[x].getCellInventory(is, this, channel);
|
||||
|
||||
if (cell != null) {
|
||||
this.inv.setHandler(x, cell);
|
||||
power += this.handlersBySlot[x].cellIdleDrain(is, cell);
|
||||
|
||||
final DriveWatcher<IAEItemStack> ih = new DriveWatcher(cell, is, this.handlersBySlot[x],
|
||||
this);
|
||||
ih.setPriority(this.priority);
|
||||
this.invBySlot[x] = ih;
|
||||
this.inventoryHandlers.get(channel).add(ih);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.getProxy().setIdlePowerUsage(power);
|
||||
|
||||
this.isCached = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReady() {
|
||||
super.onReady();
|
||||
this.updateState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IMEInventoryHandler> getCellArray(final IStorageChannel channel) {
|
||||
if (this.getProxy().isActive()) {
|
||||
this.updateState();
|
||||
|
||||
return this.inventoryHandlers.get(channel);
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return this.priority;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPriority(final int newValue) {
|
||||
this.priority = newValue;
|
||||
this.saveChanges();
|
||||
|
||||
this.isCached = false; // recalculate the storage cell.
|
||||
this.updateState();
|
||||
|
||||
try {
|
||||
this.getProxy().getGrid().postEvent(new MENetworkCellArrayUpdate());
|
||||
} catch (final GridAccessException e) {
|
||||
// :P
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void blinkCell(final int slot) {
|
||||
this.state |= 1 << (slot * 3 + 2);
|
||||
|
||||
this.recalculateDisplay();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveChanges(final ICellInventory<?> cellInventory) {
|
||||
this.world.markDirty(this.pos, this);
|
||||
}
|
||||
|
||||
private class CellValidInventoryFilter implements IAEItemFilter {
|
||||
|
||||
@Override
|
||||
public boolean allowExtract(FixedItemInv inv, int slot, int amount) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowInsert(FixedItemInv inv, int slot, ItemStack stack) {
|
||||
return !stack.isEmpty() && AEApi.instance().registries().cell().isCellHandled(stack);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemStackRepresentation() {
|
||||
return AEApi.instance().definitions().blocks().drive().maybeStack(1).orElse(ItemStack.EMPTY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DriveModelData getRenderAttachmentData() {
|
||||
return new DriveModelData(getUp(), getForward(), DriveSlotsState.fromChestOrDrive(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScreenHandlerType<?> getContainerType() {
|
||||
return DriveContainer.TYPE;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,448 +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.tile.storage;
|
||||
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import alexiil.mc.lib.attributes.item.FixedItemInv;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.config.Actionable;
|
||||
import appeng.api.config.FullnessMode;
|
||||
import appeng.api.config.OperationMode;
|
||||
import appeng.api.config.RedstoneMode;
|
||||
import appeng.api.config.Settings;
|
||||
import appeng.api.config.Upgrades;
|
||||
import appeng.api.config.YesNo;
|
||||
import appeng.api.implementations.IUpgradeableHost;
|
||||
import appeng.api.networking.GridFlags;
|
||||
import appeng.api.networking.IGridNode;
|
||||
import appeng.api.networking.energy.IEnergySource;
|
||||
import appeng.api.networking.security.IActionSource;
|
||||
import appeng.api.networking.ticking.IGridTickable;
|
||||
import appeng.api.networking.ticking.TickRateModulation;
|
||||
import appeng.api.networking.ticking.TickingRequest;
|
||||
import appeng.api.storage.IMEInventory;
|
||||
import appeng.api.storage.IMEMonitor;
|
||||
import appeng.api.storage.IStorageChannel;
|
||||
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.DimensionalCoord;
|
||||
import appeng.api.util.IConfigManager;
|
||||
import appeng.core.settings.TickRates;
|
||||
import appeng.me.GridAccessException;
|
||||
import appeng.me.helpers.MachineSource;
|
||||
import appeng.parts.automation.BlockUpgradeInventory;
|
||||
import appeng.parts.automation.UpgradeInventory;
|
||||
import appeng.tile.grid.AENetworkInvBlockEntity;
|
||||
import appeng.tile.inventory.AppEngInternalInventory;
|
||||
import appeng.util.ConfigManager;
|
||||
import appeng.util.IConfigManagerHost;
|
||||
import appeng.util.InventoryAdaptor;
|
||||
import appeng.util.Platform;
|
||||
import appeng.util.helpers.ItemHandlerUtil;
|
||||
import appeng.util.inv.AdaptorFixedInv;
|
||||
import appeng.util.inv.InvOperation;
|
||||
import appeng.util.inv.WrapperChainedItemHandler;
|
||||
import appeng.util.inv.WrapperFilteredItemHandler;
|
||||
import appeng.util.inv.filter.AEItemFilters;
|
||||
|
||||
public class IOPortBlockEntity extends AENetworkInvBlockEntity
|
||||
implements IUpgradeableHost, IConfigManagerHost, IGridTickable {
|
||||
private static final int NUMBER_OF_CELL_SLOTS = 6;
|
||||
private static final int NUMBER_OF_UPGRADE_SLOTS = 3;
|
||||
|
||||
private final ConfigManager manager;
|
||||
|
||||
private final AppEngInternalInventory inputCells = new AppEngInternalInventory(this, NUMBER_OF_CELL_SLOTS);
|
||||
private final AppEngInternalInventory outputCells = new AppEngInternalInventory(this, NUMBER_OF_CELL_SLOTS);
|
||||
private final FixedItemInv combinedInventory = new WrapperChainedItemHandler(this.inputCells, this.outputCells);
|
||||
|
||||
private final FixedItemInv inputCellsExt = new WrapperFilteredItemHandler(this.inputCells,
|
||||
AEItemFilters.INSERT_ONLY);
|
||||
private final FixedItemInv outputCellsExt = new WrapperFilteredItemHandler(this.outputCells,
|
||||
AEItemFilters.EXTRACT_ONLY);
|
||||
|
||||
private final UpgradeInventory upgrades;
|
||||
private final IActionSource mySrc;
|
||||
private YesNo lastRedstoneState;
|
||||
private ItemStack currentCell;
|
||||
private Map<IStorageChannel<?>, IMEInventory<?>> cachedInventories;
|
||||
|
||||
public IOPortBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
this.getProxy().setFlags(GridFlags.REQUIRE_CHANNEL);
|
||||
this.manager = new ConfigManager(this);
|
||||
this.manager.registerSetting(Settings.REDSTONE_CONTROLLED, RedstoneMode.IGNORE);
|
||||
this.manager.registerSetting(Settings.FULLNESS_MODE, FullnessMode.EMPTY);
|
||||
this.manager.registerSetting(Settings.OPERATION_MODE, OperationMode.EMPTY);
|
||||
this.mySrc = new MachineSource(this);
|
||||
this.lastRedstoneState = YesNo.UNDECIDED;
|
||||
|
||||
final Block ioPortBlock = AEApi.instance().definitions().blocks().iOPort().maybeBlock().get();
|
||||
this.upgrades = new BlockUpgradeInventory(ioPortBlock, this, NUMBER_OF_UPGRADE_SLOTS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag toTag(final CompoundTag data) {
|
||||
super.toTag(data);
|
||||
this.manager.writeToNBT(data);
|
||||
this.upgrades.writeToNBT(data, "upgrades");
|
||||
data.putInt("lastRedstoneState", this.lastRedstoneState.ordinal());
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromTag(BlockState state, final CompoundTag data) {
|
||||
super.fromTag(state, data);
|
||||
this.manager.readFromNBT(data);
|
||||
this.upgrades.readFromNBT(data, "upgrades");
|
||||
if (data.contains("lastRedstoneState")) {
|
||||
this.lastRedstoneState = YesNo.values()[data.getInt("lastRedstoneState")];
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AECableType getCableConnectionType(final AEPartLocation dir) {
|
||||
return AECableType.SMART;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DimensionalCoord getLocation() {
|
||||
return new DimensionalCoord(this);
|
||||
}
|
||||
|
||||
private void updateTask() {
|
||||
try {
|
||||
if (this.hasWork()) {
|
||||
this.getProxy().getTick().wakeDevice(this.getProxy().getNode());
|
||||
} else {
|
||||
this.getProxy().getTick().sleepDevice(this.getProxy().getNode());
|
||||
}
|
||||
} catch (final GridAccessException e) {
|
||||
// :P
|
||||
}
|
||||
}
|
||||
|
||||
public void updateRedstoneState() {
|
||||
final YesNo currentState = this.world.getReceivedRedstonePower(this.pos) != 0 ? YesNo.YES : YesNo.NO;
|
||||
if (this.lastRedstoneState != currentState) {
|
||||
this.lastRedstoneState = currentState;
|
||||
this.updateTask();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean getRedstoneState() {
|
||||
if (this.lastRedstoneState == YesNo.UNDECIDED) {
|
||||
this.updateRedstoneState();
|
||||
}
|
||||
|
||||
return this.lastRedstoneState == YesNo.YES;
|
||||
}
|
||||
|
||||
private boolean isEnabled() {
|
||||
if (this.getInstalledUpgrades(Upgrades.REDSTONE) == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final RedstoneMode rs = (RedstoneMode) this.manager.getSetting(Settings.REDSTONE_CONTROLLED);
|
||||
if (rs == RedstoneMode.HIGH_SIGNAL) {
|
||||
return this.getRedstoneState();
|
||||
}
|
||||
return !this.getRedstoneState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IConfigManager getConfigManager() {
|
||||
return this.manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FixedItemInv getInventoryByName(final String name) {
|
||||
if (name.equals("upgrades")) {
|
||||
return this.upgrades;
|
||||
}
|
||||
|
||||
if (name.equals("cells")) {
|
||||
return this.combinedInventory;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSetting(final IConfigManager manager, final Settings settingName, final Enum<?> newValue) {
|
||||
this.updateTask();
|
||||
}
|
||||
|
||||
private boolean hasWork() {
|
||||
if (this.isEnabled()) {
|
||||
return !ItemHandlerUtil.isEmpty(this.inputCells);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FixedItemInv getInternalInventory() {
|
||||
return this.combinedInventory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeInventory(final FixedItemInv inv, final int slot, final InvOperation mc,
|
||||
final ItemStack removed, final ItemStack added) {
|
||||
if (this.inputCells == inv) {
|
||||
this.updateTask();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FixedItemInv getItemHandlerForSide(final Direction facing) {
|
||||
if (facing == this.getUp() || facing == this.getUp().getOpposite()) {
|
||||
return this.inputCellsExt;
|
||||
} else {
|
||||
return this.outputCellsExt;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickingRequest getTickingRequest(final IGridNode node) {
|
||||
return new TickingRequest(TickRates.IOPort.getMin(), TickRates.IOPort.getMax(), !this.hasWork(), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickRateModulation tickingRequest(final IGridNode node, final int ticksSinceLastCall) {
|
||||
if (!this.getProxy().isActive()) {
|
||||
return TickRateModulation.IDLE;
|
||||
}
|
||||
|
||||
TickRateModulation ret = TickRateModulation.SLEEP;
|
||||
long itemsToMove = 256;
|
||||
|
||||
switch (this.getInstalledUpgrades(Upgrades.SPEED)) {
|
||||
case 1:
|
||||
itemsToMove *= 2;
|
||||
break;
|
||||
case 2:
|
||||
itemsToMove *= 4;
|
||||
break;
|
||||
case 3:
|
||||
itemsToMove *= 8;
|
||||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
final IEnergySource energy = this.getProxy().getEnergy();
|
||||
for (int x = 0; x < NUMBER_OF_CELL_SLOTS; x++) {
|
||||
final ItemStack is = this.inputCells.getInvStack(x);
|
||||
if (!is.isEmpty()) {
|
||||
boolean shouldMove = true;
|
||||
|
||||
for (IStorageChannel<? extends IAEStack<?>> c : AEApi.instance().storage().storageChannels()) {
|
||||
if (itemsToMove > 0) {
|
||||
final IMEMonitor<? extends IAEStack<?>> network = this.getProxy().getStorage()
|
||||
.getInventory(c);
|
||||
final IMEInventory<?> inv = this.getInv(is, c);
|
||||
|
||||
if (inv == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (this.manager.getSetting(Settings.OPERATION_MODE) == OperationMode.EMPTY) {
|
||||
itemsToMove = this.transferContents(energy, inv, network, itemsToMove, c);
|
||||
} else {
|
||||
itemsToMove = this.transferContents(energy, network, inv, itemsToMove, c);
|
||||
}
|
||||
|
||||
shouldMove &= this.shouldMove(inv);
|
||||
|
||||
if (itemsToMove > 0) {
|
||||
ret = TickRateModulation.IDLE;
|
||||
} else {
|
||||
ret = TickRateModulation.URGENT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (itemsToMove > 0 && shouldMove && this.moveSlot(x)) {
|
||||
ret = TickRateModulation.URGENT;
|
||||
} else {
|
||||
ret = TickRateModulation.URGENT;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} catch (final GridAccessException e) {
|
||||
ret = TickRateModulation.IDLE;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInstalledUpgrades(final Upgrades u) {
|
||||
return this.upgrades.getInstalledUpgrades(u);
|
||||
}
|
||||
|
||||
private IMEInventory<?> getInv(final ItemStack is, final IStorageChannel<?> chan) {
|
||||
if (this.currentCell != is) {
|
||||
this.currentCell = is;
|
||||
this.cachedInventories = new IdentityHashMap<>();
|
||||
|
||||
for (IStorageChannel<? extends IAEStack<?>> c : AEApi.instance().storage().storageChannels()) {
|
||||
this.cachedInventories.put(c, AEApi.instance().registries().cell().getCellInventory(is, null, c));
|
||||
}
|
||||
}
|
||||
|
||||
return this.cachedInventories.get(chan);
|
||||
}
|
||||
|
||||
private long transferContents(final IEnergySource energy, final IMEInventory src, final IMEInventory destination,
|
||||
long itemsToMove, final IStorageChannel chan) {
|
||||
final IItemList<? extends IAEStack> myList;
|
||||
if (src instanceof IMEMonitor) {
|
||||
myList = ((IMEMonitor) src).getStorageList();
|
||||
} else {
|
||||
myList = src.getAvailableItems(src.getChannel().createList());
|
||||
}
|
||||
|
||||
itemsToMove *= chan.transferFactor();
|
||||
|
||||
boolean didStuff;
|
||||
|
||||
do {
|
||||
didStuff = false;
|
||||
|
||||
for (final IAEStack s : myList) {
|
||||
final long totalStackSize = s.getStackSize();
|
||||
if (totalStackSize > 0) {
|
||||
final IAEStack stack = destination.injectItems(s, Actionable.SIMULATE, this.mySrc);
|
||||
|
||||
long possible = 0;
|
||||
if (stack == null) {
|
||||
possible = totalStackSize;
|
||||
} else {
|
||||
possible = totalStackSize - stack.getStackSize();
|
||||
}
|
||||
|
||||
if (possible > 0) {
|
||||
possible = Math.min(possible, itemsToMove);
|
||||
s.setStackSize(possible);
|
||||
|
||||
final IAEStack extracted = src.extractItems(s, Actionable.MODULATE, this.mySrc);
|
||||
if (extracted != null) {
|
||||
possible = extracted.getStackSize();
|
||||
final IAEStack failed = Platform.poweredInsert(energy, destination, extracted, this.mySrc);
|
||||
|
||||
if (failed != null) {
|
||||
possible -= failed.getStackSize();
|
||||
src.injectItems(failed, Actionable.MODULATE, this.mySrc);
|
||||
}
|
||||
|
||||
if (possible > 0) {
|
||||
itemsToMove -= possible;
|
||||
didStuff = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (itemsToMove > 0 && didStuff);
|
||||
|
||||
return itemsToMove / chan.transferFactor();
|
||||
}
|
||||
|
||||
private boolean shouldMove(final IMEInventory<?> inv) {
|
||||
final FullnessMode fm = (FullnessMode) this.manager.getSetting(Settings.FULLNESS_MODE);
|
||||
|
||||
if (inv != null) {
|
||||
return this.matches(fm, inv);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean moveSlot(final int x) {
|
||||
final InventoryAdaptor ad = new AdaptorFixedInv(this.outputCells);
|
||||
if (ad.addItems(this.inputCells.getInvStack(x)).isEmpty()) {
|
||||
this.inputCells.setInvStack(x, ItemStack.EMPTY);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean matches(final FullnessMode fm, final IMEInventory src) {
|
||||
if (fm == FullnessMode.HALF) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final IItemList<? extends IAEStack> myList;
|
||||
|
||||
if (src instanceof IMEMonitor) {
|
||||
myList = ((IMEMonitor) src).getStorageList();
|
||||
} else {
|
||||
myList = src.getAvailableItems(src.getChannel().createList());
|
||||
}
|
||||
|
||||
if (fm == FullnessMode.EMPTY) {
|
||||
return myList.isEmpty();
|
||||
}
|
||||
|
||||
final IAEStack test = myList.getFirstItem();
|
||||
if (test != null) {
|
||||
test.setStackSize(1);
|
||||
return src.injectItems(test, Actionable.SIMULATE, this.mySrc) != null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the items in the upgrade slots to the drop list.
|
||||
*
|
||||
* @param w world
|
||||
* @param pos pos of block entity
|
||||
* @param drops drops of block entity
|
||||
*/
|
||||
@Override
|
||||
public void getDrops(final World w, final BlockPos pos, final List<ItemStack> drops) {
|
||||
super.getDrops(w, pos, drops);
|
||||
|
||||
for (int upgradeIndex = 0; upgradeIndex < this.upgrades.getSlotCount(); upgradeIndex++) {
|
||||
final ItemStack stackInSlot = this.upgrades.getInvStack(upgradeIndex);
|
||||
|
||||
if (!stackInSlot.isEmpty()) {
|
||||
drops.add(stackInSlot);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* 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.tile.storage;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.block.ChestAnimationProgress;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.sound.SoundEvents;
|
||||
import net.minecraft.util.Tickable;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.sound.SoundCategory;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import alexiil.mc.lib.attributes.item.FixedItemInv;
|
||||
|
||||
import appeng.block.storage.SkyChestBlock;
|
||||
import appeng.tile.AEBaseInvBlockEntity;
|
||||
import appeng.tile.inventory.AppEngInternalInventory;
|
||||
import appeng.util.inv.InvOperation;
|
||||
|
||||
public class SkyChestBlockEntity extends AEBaseInvBlockEntity implements Tickable, ChestAnimationProgress {
|
||||
|
||||
private final AppEngInternalInventory inv = new AppEngInternalInventory(this, 9 * 4);
|
||||
|
||||
// server
|
||||
private int numPlayersUsing;
|
||||
// client..
|
||||
private long lastEvent;
|
||||
private float lidAngle;
|
||||
private float prevLidAngle;
|
||||
|
||||
public SkyChestBlockEntity(BlockEntityType<? extends SkyChestBlockEntity> type) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeToStream(final PacketByteBuf data) throws IOException {
|
||||
super.writeToStream(data);
|
||||
data.writeBoolean(this.getPlayerOpen() > 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean readFromStream(final PacketByteBuf data) throws IOException {
|
||||
final boolean c = super.readFromStream(data);
|
||||
final int wasOpen = this.getPlayerOpen();
|
||||
this.setPlayerOpen(data.readBoolean() ? 1 : 0);
|
||||
|
||||
if (wasOpen != this.getPlayerOpen()) {
|
||||
this.setLastEvent(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
return c; // TESR yo!
|
||||
}
|
||||
|
||||
@Override
|
||||
public FixedItemInv getInternalInventory() {
|
||||
return this.inv;
|
||||
}
|
||||
|
||||
public void openInventory(final PlayerEntity player) {
|
||||
if (!player.isSpectator()) {
|
||||
this.setPlayerOpen(this.getPlayerOpen() + 1);
|
||||
onOpenOrClose();
|
||||
|
||||
if (this.getPlayerOpen() == 1) {
|
||||
this.getWorld().playSound(player, this.pos.getX() + 0.5D, this.pos.getY() + 0.5D,
|
||||
this.pos.getZ() + 0.5D, SoundEvents.BLOCK_CHEST_OPEN, SoundCategory.BLOCKS, 0.5F,
|
||||
this.getWorld().random.nextFloat() * 0.1F + 0.9F);
|
||||
this.markForUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void closeInventory(final PlayerEntity player) {
|
||||
if (!player.isSpectator()) {
|
||||
this.setPlayerOpen(this.getPlayerOpen() - 1);
|
||||
onOpenOrClose();
|
||||
|
||||
if (this.getPlayerOpen() < 0) {
|
||||
this.setPlayerOpen(0);
|
||||
}
|
||||
|
||||
if (this.getPlayerOpen() == 0) {
|
||||
this.getWorld().playSound(player, this.pos.getX() + 0.5D, this.pos.getY() + 0.5D,
|
||||
this.pos.getZ() + 0.5D, SoundEvents.BLOCK_CHEST_CLOSE, SoundCategory.BLOCKS, 0.5F,
|
||||
this.getWorld().random.nextFloat() * 0.1F + 0.9F);
|
||||
this.markForUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// See ChestTileEntity
|
||||
private void onOpenOrClose() {
|
||||
Block block = getCachedState().getBlock();
|
||||
if (block instanceof SkyChestBlock) {
|
||||
this.world.addSyncedBlockEvent(this.pos, block, 1, this.numPlayersUsing);
|
||||
this.world.updateNeighborsAlways(this.pos, block);
|
||||
// FIXME: Uhm, we are we doing this?
|
||||
this.world.updateNeighborsAlways(this.pos.down(), block);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
this.prevLidAngle = this.lidAngle;
|
||||
if (this.numPlayersUsing == 0 && this.lidAngle > 0.0F || this.numPlayersUsing > 0 && this.lidAngle < 1.0F) {
|
||||
if (this.numPlayersUsing > 0) {
|
||||
this.lidAngle += 0.1F;
|
||||
} else {
|
||||
this.lidAngle -= 0.1F;
|
||||
}
|
||||
|
||||
this.lidAngle = MathHelper.clamp(this.lidAngle, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeInventory(final FixedItemInv inv, final int slot, final InvOperation mc,
|
||||
final ItemStack removed, final ItemStack added) {
|
||||
|
||||
}
|
||||
|
||||
public int getPlayerOpen() {
|
||||
return this.numPlayersUsing;
|
||||
}
|
||||
|
||||
private void setPlayerOpen(final int playerOpen) {
|
||||
this.numPlayersUsing = playerOpen;
|
||||
}
|
||||
|
||||
public long getLastEvent() {
|
||||
return this.lastEvent;
|
||||
}
|
||||
|
||||
private void setLastEvent(final long lastEvent) {
|
||||
this.lastEvent = lastEvent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getAnimationProgress(float partialTicks) {
|
||||
return MathHelper.lerp(partialTicks, this.prevLidAngle, this.lidAngle);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user