diff --git a/src/api/java/appeng/api/implementations/tiles/IChestOrDrive.java b/src/api/java/appeng/api/implementations/tiles/IChestOrDrive.java index 0be1d0030..33c549a4c 100644 --- a/src/api/java/appeng/api/implementations/tiles/IChestOrDrive.java +++ b/src/api/java/appeng/api/implementations/tiles/IChestOrDrive.java @@ -40,11 +40,13 @@ public interface IChestOrDrive extends ICellContainer, IGridHost, IOrientable /** * 0 - cell is missing. * - * 1 - green, + * 1 - green, the cell is present and partially empty * - * 2 - orange, + * 2 - orange, the cell is present and full on types * - * 3 - red + * 3 - red, the cell is present and full on bytes + * + * 4 - blue, the cell is present but totally empty * * @param slot slot index * diff --git a/src/api/java/appeng/api/storage/ICellInventory.java b/src/api/java/appeng/api/storage/ICellInventory.java index fa37b4c3d..e9a9a04b6 100644 --- a/src/api/java/appeng/api/storage/ICellInventory.java +++ b/src/api/java/appeng/api/storage/ICellInventory.java @@ -123,6 +123,8 @@ public interface ICellInventory> extends IMEInventory * * 3 - red, ( usually means the cell is 100% full ) * + * 4 - blue, ( usually means the cell is available and completely empty. ) + * * @return get the status of the cell based on its contents. */ int getStatusForCell(); diff --git a/src/main/java/appeng/block/storage/DriveSlotState.java b/src/main/java/appeng/block/storage/DriveSlotState.java index 15b2dce3b..a9ff458f2 100644 --- a/src/main/java/appeng/block/storage/DriveSlotState.java +++ b/src/main/java/appeng/block/storage/DriveSlotState.java @@ -40,7 +40,10 @@ public enum DriveSlotState implements IStringSerializable { TYPES_FULL("types_full"), // Completely full - FULL("full"); + FULL("full"), + + // Online and completely empty + NO_CONTENTS("no_contents"); private final String name; @@ -64,6 +67,8 @@ public enum DriveSlotState implements IStringSerializable { return DriveSlotState.TYPES_FULL; case 3: return DriveSlotState.FULL; + case 4: + return DriveSlotState.NO_CONTENTS; } } diff --git a/src/main/java/appeng/client/render/model/DriveModel.java b/src/main/java/appeng/client/render/model/DriveModel.java index 4cd20df46..cdcfbdcf9 100644 --- a/src/main/java/appeng/client/render/model/DriveModel.java +++ b/src/main/java/appeng/client/render/model/DriveModel.java @@ -42,12 +42,14 @@ public class DriveModel implements IModel { private static final ResourceLocation MODEL_BASE = new ResourceLocation("appliedenergistics2:block/drive_base"); - private static final Map MODELS_CELLS = ImmutableMap.of( - DriveSlotState.EMPTY, new ResourceLocation("appliedenergistics2:block/drive_cell_empty"), - DriveSlotState.OFFLINE, new ResourceLocation("appliedenergistics2:block/drive_cell_off"), - DriveSlotState.ONLINE, new ResourceLocation("appliedenergistics2:block/drive_cell_on"), - DriveSlotState.TYPES_FULL, new ResourceLocation("appliedenergistics2:block/drive_cell_types_full"), - DriveSlotState.FULL, new ResourceLocation("appliedenergistics2:block/drive_cell_full")); + private static final Map MODELS_CELLS = ImmutableMap.builder() + .put(DriveSlotState.EMPTY, new ResourceLocation("appliedenergistics2:block/drive_cell_empty")) + .put(DriveSlotState.OFFLINE, new ResourceLocation("appliedenergistics2:block/drive_cell_off")) + .put(DriveSlotState.ONLINE, new ResourceLocation("appliedenergistics2:block/drive_cell_on")) + .put(DriveSlotState.TYPES_FULL, new ResourceLocation("appliedenergistics2:block/drive_cell_types_full")) + .put(DriveSlotState.FULL, new ResourceLocation("appliedenergistics2:block/drive_cell_full")) + .put(DriveSlotState.NO_CONTENTS, new ResourceLocation("appliedenergistics2:block/drive_cell_no_contents")) + .build(); @Override public Collection getDependencies() { diff --git a/src/main/java/appeng/me/storage/AbstractCellInventory.java b/src/main/java/appeng/me/storage/AbstractCellInventory.java index 6a218510f..8effd98bc 100644 --- a/src/main/java/appeng/me/storage/AbstractCellInventory.java +++ b/src/main/java/appeng/me/storage/AbstractCellInventory.java @@ -291,6 +291,9 @@ public abstract class AbstractCellInventory> implements IC @Override public int getStatusForCell() { + if (this.getUsedBytes() == 0) { + return 4; + } if (this.canHoldNewItem()) { return 1; } diff --git a/src/main/java/appeng/tile/storage/TileChest.java b/src/main/java/appeng/tile/storage/TileChest.java index 5a550325a..8ee7732ac 100644 --- a/src/main/java/appeng/tile/storage/TileChest.java +++ b/src/main/java/appeng/tile/storage/TileChest.java @@ -91,7 +91,6 @@ public class TileChest extends AENetworkPowerTile implements IMEChest, ITerminal 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; @@ -99,6 +98,13 @@ public class TileChest extends AENetworkPowerTile implements IMEChest, ITerminal private Accessor accessor; private IFluidHandler fluidHandler; + // Client-sided caches for rendering + // state value holds 3 bits per drive + private int cellState; + private boolean powered = false; + // bit index corresponds to cell index + private int blinking; + public TileChest() { this.setInternalMaxPower(PowerMultiplier.CONFIG.multiply(128)); this.getProxy().setFlags(GridFlags.REQUIRE_CHANNEL); @@ -131,17 +137,14 @@ public class TileChest extends AENetworkPowerTile implements IMEChest, ITerminal } private void recalculateDisplay() { - final int oldState = this.state; + final int oldCellState = this.cellState; + final boolean oldPowered = this.powered; for (int x = 0; x < this.getCellCount(); x++) { - this.state |= (this.getCellStatus(x) << (3 * x)); + this.cellState |= (this.getCellStatus(x) << (3 * x)); } - if (this.isPowered()) { - this.state |= 0x40; - } else { - this.state &= ~0x40; - } + this.powered = this.isPowered(); final boolean currentActive = this.getProxy().isActive(); if (this.wasActive != currentActive) { @@ -153,7 +156,7 @@ public class TileChest extends AENetworkPowerTile implements IMEChest, ITerminal } } - if (oldState != this.state) { + if (oldCellState != this.cellState || oldPowered != this.powered) { this.markForUpdate(); } } @@ -215,7 +218,7 @@ public class TileChest extends AENetworkPowerTile implements IMEChest, ITerminal @Override public int getCellStatus(final int slot) { if (Platform.isClient()) { - return (this.state >> (slot * 3)) & 3; + return (this.cellState >> (slot * 3)) & 0b111; } this.updateHandler(); @@ -233,7 +236,7 @@ public class TileChest extends AENetworkPowerTile implements IMEChest, ITerminal @Override public boolean isPowered() { if (Platform.isClient()) { - return (this.state & 0x40) == 0x40; + return this.powered; } boolean gridPowered = this.getAECurrentPower() > 64; @@ -255,7 +258,7 @@ public class TileChest extends AENetworkPowerTile implements IMEChest, ITerminal return false; } - return ((this.state >> (slot * 3 + 2)) & 0x01) == 0x01; + return (this.blinking & (1 << slot)) == 1; } @Override @@ -287,13 +290,13 @@ public class TileChest extends AENetworkPowerTile implements IMEChest, ITerminal 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) { + if (powerUsed + 0.1 >= idleUsage != this.powered) { 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) { + if (powerUsed + 0.1 >= idleUsage != this.powered) { this.recalculateDisplay(); } } @@ -308,22 +311,24 @@ public class TileChest extends AENetworkPowerTile implements IMEChest, ITerminal super.writeToStream(data); if (this.world.getTotalWorldTime() - this.lastStateChange > 8) { - this.state = 0; + this.cellState = 0; + this.powered = false; + this.blinking = 0; } else { - this.state &= 0x24924924; // just keep the blinks... + // just keep the blinks... + this.cellState = 0; + this.powered = false; } for (int x = 0; x < this.getCellCount(); x++) { - this.state |= (this.getCellStatus(x) << (3 * x)); + this.cellState |= (this.getCellStatus(x) << (3 * x)); } - if (this.isPowered()) { - this.state |= 0x40; - } else { - this.state &= ~0x40; - } + this.powered = this.isPowered(); - data.writeByte(this.state); + data.writeByte(this.cellState); + data.writeBoolean(this.powered); + data.writeByte(this.blinking); data.writeByte(this.paintedColor.ordinal()); } @@ -331,15 +336,19 @@ public class TileChest extends AENetworkPowerTile implements IMEChest, ITerminal protected boolean readFromStream(final ByteBuf data) throws IOException { final boolean c = super.readFromStream(data); - final int oldState = this.state; + final int oldState = this.cellState; + final boolean oldPowered = this.powered; + final int oldBlinking = this.blinking; - this.state = data.readByte(); + this.cellState = data.readByte(); + this.powered = data.readBoolean(); + this.blinking = data.readByte(); final AEColor oldPaintedColor = this.paintedColor; this.paintedColor = AEColor.values()[data.readByte()]; this.lastStateChange = this.world.getTotalWorldTime(); - return oldPaintedColor != this.paintedColor || (this.state & 0xDB6DB6DB) != (oldState & 0xDB6DB6DB) || c; + return oldPaintedColor != this.paintedColor || this.cellState != oldState || c || oldPowered != this.powered || oldBlinking != this.blinking; } @Override @@ -470,11 +479,13 @@ public class TileChest extends AENetworkPowerTile implements IMEChest, ITerminal public void blinkCell(final int slot) { final long now = this.world.getTotalWorldTime(); if (now - this.lastStateChange > 8) { - this.state = 0; + this.cellState = 0; + this.powered = false; + this.blinking = 0; } this.lastStateChange = now; - this.state |= 1 << (slot * 3 + 2); + this.blinking |= (1 << slot); this.recalculateDisplay(); } diff --git a/src/main/java/appeng/tile/storage/TileDrive.java b/src/main/java/appeng/tile/storage/TileDrive.java index 32628500c..d381f193c 100644 --- a/src/main/java/appeng/tile/storage/TileDrive.java +++ b/src/main/java/appeng/tile/storage/TileDrive.java @@ -55,10 +55,6 @@ import java.util.*; public class TileDrive extends AENetworkInvTile 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[] invBySlot = new DriveWatcher[10]; @@ -71,15 +67,15 @@ public class TileDrive extends AENetworkInvTile implements IChestOrDrive, IPrior /** * 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 + * Bit 2-0: cell status, representing {@link appeng.block.storage.DriveSlotState}. */ - private int state = 0; + private int cellState = 0; + private boolean powered; + // bit index corresponds to cell index + private int blinking; public TileDrive() { this.mySrc = new MachineSource(this); @@ -91,25 +87,27 @@ public class TileDrive extends AENetworkInvTile implements IChestOrDrive, IPrior @Override protected void writeToStream(final ByteBuf 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) << (3 * x)); } data.writeInt(newState); + data.writeBoolean(this.getProxy().isActive()); + data.writeInt(this.blinking); } @Override protected boolean readFromStream(final ByteBuf data) throws IOException { final boolean c = super.readFromStream(data); - final int oldState = this.state; - this.state = data.readInt(); - return (this.state & BIT_STATE_MASK) != (oldState & BIT_STATE_MASK) || c; + final int oldCellState = this.cellState; + final boolean oldPowered = this.powered; + final int oldBlinking = this.blinking; + this.cellState = data.readInt(); + this.powered = data.readBoolean(); + this.blinking = data.readInt(); + return oldCellState != this.cellState || oldPowered != this.powered || oldBlinking != this.blinking || c; } @Override @@ -120,7 +118,7 @@ public class TileDrive extends AENetworkInvTile implements IChestOrDrive, IPrior @Override public int getCellStatus(final int slot) { if (Platform.isClient()) { - return (this.state >> (slot * 3)) & 3; + return (this.cellState >> (slot * 3)) & 0b111; } final DriveWatcher handler = this.invBySlot[slot]; @@ -134,7 +132,7 @@ public class TileDrive extends AENetworkInvTile implements IChestOrDrive, IPrior @Override public boolean isPowered() { if (Platform.isClient()) { - return (this.state & BIT_POWER_MASK) == BIT_POWER_MASK; + return this.powered; } return this.getProxy().isActive(); @@ -142,7 +140,7 @@ public class TileDrive extends AENetworkInvTile implements IChestOrDrive, IPrior @Override public boolean isCellBlinking(final int slot) { - return ((this.state >> (slot * 3 + 2)) & 0x01) == 0x01; + return (this.blinking & (1 << slot)) == 1; } @Override @@ -166,11 +164,10 @@ public class TileDrive extends AENetworkInvTile implements IChestOrDrive, IPrior private void recalculateDisplay() { final boolean currentActive = this.getProxy().isActive(); - int newState = 0; + final int oldCellState = this.cellState; + final boolean oldPowered = this.powered; - if (currentActive) { - newState |= BIT_POWER_MASK; - } + this.powered = currentActive; if (this.wasActive != currentActive) { this.wasActive = currentActive; @@ -182,11 +179,10 @@ public class TileDrive extends AENetworkInvTile implements IChestOrDrive, IPrior } for (int x = 0; x < this.getCellCount(); x++) { - newState |= (this.getCellStatus(x) << (3 * x)); + cellState |= (this.getCellStatus(x) << (3 * x)); } - if (newState != this.state) { - this.state = newState; + if (oldCellState != this.cellState || oldPowered != this.powered) { this.markForUpdate(); } } @@ -306,7 +302,7 @@ public class TileDrive extends AENetworkInvTile implements IChestOrDrive, IPrior @Override public void blinkCell(final int slot) { - this.state |= 1 << (slot * 3 + 2); + this.blinking |= (1 << slot); this.recalculateDisplay(); } diff --git a/src/main/resources/assets/appliedenergistics2/blockstates/chest.json b/src/main/resources/assets/appliedenergistics2/blockstates/chest.json index 7371dc1d4..8464d67b1 100644 --- a/src/main/resources/assets/appliedenergistics2/blockstates/chest.json +++ b/src/main/resources/assets/appliedenergistics2/blockstates/chest.json @@ -54,6 +54,16 @@ "model": "appliedenergistics2:chest/cell_state_full" } } + }, + "no_contents": { + "submodel": { + "lights": { + "model": "appliedenergistics2:chest/lights_on" + }, + "state": { + "model": "appliedenergistics2:chest/cell_state_no_contents" + } + } } } } diff --git a/src/main/resources/assets/appliedenergistics2/models/block/chest/cell_state_no_contents.json b/src/main/resources/assets/appliedenergistics2/models/block/chest/cell_state_no_contents.json new file mode 100644 index 000000000..ea5a7a01c --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/models/block/chest/cell_state_no_contents.json @@ -0,0 +1,23 @@ +{ + "textures": { + "backdrop": "appliedenergistics2:blocks/chest/cell_state_backdrop", + "state": "appliedenergistics2:blocks/chest/cell_state_no_contents" + }, + "elements": [ + { + "from": [5, 4, 0], + "to": [11, 6, 1], + "faces": { + "north": { "uv": [5, 10, 11, 12], "texture": "#backdrop" }, + "up": { "uv": [5, 9, 11, 10], "texture": "#backdrop" } + } + }, + { + "from": [0, 0, 0], + "to": [16, 16, 16], + "faces": { + "north": { "uv": [0, 0, 16, 16], "texture": "#state" } + } + } + ] +} diff --git a/src/main/resources/assets/appliedenergistics2/models/block/drive_cell_no_contents.json b/src/main/resources/assets/appliedenergistics2/models/block/drive_cell_no_contents.json new file mode 100644 index 000000000..da17e72b0 --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/models/block/drive_cell_no_contents.json @@ -0,0 +1,30 @@ +{ + "credit": "Made with Blockbench", + "textures": { + "front": "appliedenergistics2:blocks/drive_cell_states", + "top_front": "appliedenergistics2:blocks/drive_cell_states_emissive" + }, + "elements": [ + { + "name": "Cell Backdrop", + "from": [9, 13, 1], + "to": [15, 15, 2], + "shade": false, + "faces": { + "north": {"uv": [0, 8, 6, 10], "texture": "#front"}, + "up": {"uv": [0, 8, 6, 9], "texture": "#front"}, + "down": {"uv": [6, 8, 0, 10], "texture": "#front"} + } + }, + { + "name": "Cell Light", + "from": [9, 13, 1], + "to": [15, 15, 2], + "shade": false, + "faces": { + "north": {"uv": [0, 0, 6, 2], "texture": "#top_front"}, + "down": {"uv": [6, 0, 0, 2], "texture": "#top_front"} + } + } + ] +} diff --git a/src/main/resources/assets/appliedenergistics2/textures/blocks/chest/cell_state_no_contents.png b/src/main/resources/assets/appliedenergistics2/textures/blocks/chest/cell_state_no_contents.png new file mode 100644 index 000000000..0c07492f7 Binary files /dev/null and b/src/main/resources/assets/appliedenergistics2/textures/blocks/chest/cell_state_no_contents.png differ diff --git a/src/main/resources/assets/appliedenergistics2/textures/blocks/drive_cell_states_emissive.png b/src/main/resources/assets/appliedenergistics2/textures/blocks/drive_cell_states_emissive.png index 7c3a4f3f5..597976962 100644 Binary files a/src/main/resources/assets/appliedenergistics2/textures/blocks/drive_cell_states_emissive.png and b/src/main/resources/assets/appliedenergistics2/textures/blocks/drive_cell_states_emissive.png differ