Bus and item devices can (and do) contribute to energy consumption.

This commit is contained in:
Florian Nücke
2021-02-14 12:52:03 +01:00
parent 4f3ef53ba7
commit 8dfa967f77
70 changed files with 863 additions and 339 deletions

View File

@@ -10,29 +10,6 @@ import java.util.Collection;
* these devices.
*/
public interface DeviceBus {
/**
* Adds a device to this device bus.
* <p>
* Adding a device to the bus does <em>not</em> transfer ownership. In particular,
* the bus will not handle persisting devices that have been added to it. Also,
* the bus does not persist the list of devices. Instead, all devices that have
* been added to the bus must be added again after a load. It is the responsibility
* of {@link DeviceBusElement}s to detect and add devices to the bus.
*
* @param device the device to add to the bus.
*/
void addDevice(Device device);
/**
* Removes a device from this device bus.
* <p>
* If the device has not been added with {@link #addDevice(Device)} before calling
* this method, this method is a no-op.
*
* @param device the device to remove from the bus.
*/
void removeDevice(Device device);
/**
* The list of all devices currently registered with this device bus.
*

View File

@@ -30,10 +30,6 @@ public interface DeviceBusElement extends DeviceBus {
* <p>
* When {@link #scheduleScan()} is called, {@link DeviceBusController#scheduleBusScan()}
* <em>must</em> be called for each registered controller.
* <p>
* When either {@link #addDevice(Device)} or {@link #removeDevice(Device)} are called,
* {@link DeviceBusController#scanDevices()} <em>should</em> be called for each registered
* controller.
*
* @param controller the controller to add.
*/
@@ -98,4 +94,22 @@ public interface DeviceBusElement extends DeviceBus {
* @return the stable id for the specified device.
*/
Optional<UUID> getDeviceIdentifier(Device device);
/**
* Returns the energy consumption of this bus element.
* <p>
* Energy cost of a single bus element may vary depending on its configuration. For example,
* bus cables will also take into account the number of installed bus interfaces. Internal
* bus elements used to connect item devices will take into account the energy consumption of
* any connected item devices.
* <p>
* Block devices that require a running amount of energy should use regular means of having
* energy injected into them. The device bus is not intended nor communicated as something
* that transfers power.
*
* @return the complexity of this bus element.
*/
default double getEnergyConsumption() {
return 0;
}
}

View File

@@ -1,6 +1,5 @@
package li.cil.oc2.api.bus.device.provider;
import li.cil.oc2.api.bus.device.Device;
import li.cil.oc2.api.bus.device.DeviceType;
import li.cil.oc2.api.bus.device.DeviceTypes;
import li.cil.oc2.api.bus.device.ItemDevice;
@@ -43,7 +42,7 @@ public interface ItemDeviceProvider extends IForgeRegistryEntry<ItemDeviceProvid
/**
* Get a device for the specified query.
*
* @param query the query describing the object to get a {@link Device} for.
* @param query the query describing the object to get an {@link ItemDevice} for.
* @return a device for the specified query, if available.
*/
Optional<ItemDevice> getDevice(ItemDeviceQuery query);
@@ -51,4 +50,17 @@ public interface ItemDeviceProvider extends IForgeRegistryEntry<ItemDeviceProvid
default Optional<DeviceType> getDeviceType(final ItemDeviceQuery query) {
return Optional.of(DeviceTypes.CARD);
}
/**
* The amount of energy the device that would be returned by {@link #getDevice(ItemDeviceQuery)}
* will consume per tick while the VM using it is running.
* <p>
* Return <code>0</code> if no device would be provided.
*
* @param query the query describing the object to get an {@link ItemDevice} for.
* @return the amount of energy consumed by the device each tick.
*/
default int getEnergyConsumption(final ItemDeviceQuery query) {
return 0;
}
}

View File

@@ -3,6 +3,7 @@ package li.cil.oc2.client;
import li.cil.oc2.api.API;
import li.cil.oc2.api.bus.device.DeviceType;
import li.cil.oc2.client.gui.ComputerContainerScreen;
import li.cil.oc2.client.gui.ComputerTerminalScreen;
import li.cil.oc2.client.gui.RobotContainerScreen;
import li.cil.oc2.client.gui.RobotTerminalScreen;
import li.cil.oc2.client.item.CustomItemColors;
@@ -38,6 +39,7 @@ public final class ClientSetup {
CustomItemColors.initialize();
ScreenManager.registerFactory(Containers.COMPUTER_CONTAINER.get(), ComputerContainerScreen::new);
ScreenManager.registerFactory(Containers.COMPUTER_TERMINAL_CONTAINER.get(), ComputerTerminalScreen::new);
ScreenManager.registerFactory(Containers.ROBOT_CONTAINER.get(), RobotContainerScreen::new);
ScreenManager.registerFactory(Containers.ROBOT_TERMINAL_CONTAINER.get(), RobotTerminalScreen::new);

View File

@@ -15,11 +15,18 @@ import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.Widget;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.ITextProperties;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraftforge.fml.client.gui.GuiUtils;
import org.lwjgl.glfw.GLFW;
import javax.annotation.Nullable;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.List;
import static li.cil.oc2.common.util.TooltipUtils.withColor;
public abstract class AbstractTerminalWidget extends AbstractGui {
public static final ResourceLocation BACKGROUND_LOCATION = new ResourceLocation(API.MOD_ID, "textures/gui/screen/terminal.png");
@@ -27,16 +34,23 @@ public abstract class AbstractTerminalWidget extends AbstractGui {
public static final int TEXTURE_SIZE = 512;
private static final Sprite BACKGROUND = new Sprite(BACKGROUND_LOCATION, TEXTURE_SIZE, 336, 208, 0, 0);
private static final Sprite CONTROLS_BACKGROUND = new Sprite(BACKGROUND_LOCATION, TEXTURE_SIZE, 19, 34, 80, 250);
private static final Sprite TERMINAL_FOCUSED = new Sprite(TERMINAL_FOCUSED_LOCATION, TEXTURE_SIZE, 336, 208, 0, 0);
private static final Sprite CONTROLS_BACKGROUND = new Sprite(BACKGROUND_LOCATION, TEXTURE_SIZE, 19, 34, 50, 250);
private static final Sprite POWER_BASE = new Sprite(BACKGROUND_LOCATION, TEXTURE_SIZE, 12, 12, 15, 255);
private static final Sprite POWER_PRESSED = new Sprite(BACKGROUND_LOCATION, TEXTURE_SIZE, 12, 12, 29, 255);
private static final Sprite POWER_ACTIVE = new Sprite(BACKGROUND_LOCATION, TEXTURE_SIZE, 12, 12, 1, 255);
private static final Sprite CAPTURE_INPUT_BASE = new Sprite(BACKGROUND_LOCATION, TEXTURE_SIZE, 12, 12, 15, 241);
private static final Sprite CAPTURE_INPUT_PRESSED = new Sprite(BACKGROUND_LOCATION, TEXTURE_SIZE, 12, 12, 29, 241);
private static final Sprite CAPTURE_INPUT_ACTIVE = new Sprite(BACKGROUND_LOCATION, TEXTURE_SIZE, 12, 12, 1, 241);
private static final Sprite POWER_BASE = new Sprite(BACKGROUND_LOCATION, TEXTURE_SIZE, 12, 12, 15, 255);
private static final Sprite POWER_PRESSED = new Sprite(BACKGROUND_LOCATION, TEXTURE_SIZE, 12, 12, 29, 255);
private static final Sprite POWER_ACTIVE = new Sprite(BACKGROUND_LOCATION, TEXTURE_SIZE, 12, 12, 1, 255);
private static final Sprite ENERGY_BACKGROUND = new Sprite(BACKGROUND_LOCATION, TEXTURE_SIZE, 19, 34, 80, 250);
private static final Sprite ENERGY_BASE = new Sprite(BACKGROUND_LOCATION, TEXTURE_SIZE, 12, 26, 110, 250);
private static final Sprite ENERGY_BAR = new Sprite(BACKGROUND_LOCATION, TEXTURE_SIZE, 12, 26, 125, 250);
private static final Sprite TERMINAL_FOCUSED = new Sprite(TERMINAL_FOCUSED_LOCATION, TEXTURE_SIZE, 336, 208, 0, 0);
public static final int TERMINAL_WIDTH = Terminal.WIDTH * Terminal.CHAR_WIDTH / 2;
public static final int TERMINAL_HEIGHT = Terminal.HEIGHT * Terminal.CHAR_HEIGHT / 2;
@@ -49,6 +63,7 @@ public abstract class AbstractTerminalWidget extends AbstractGui {
public static final int HEIGHT = TERMINAL_HEIGHT + MARGIN_SIZE * 2;
private static final int CONTROLS_TOP = 8;
private static final int ENERGY_TOP = CONTROLS_TOP + CONTROLS_BACKGROUND.height + 4;
private static boolean isInputCaptureEnabled;
@@ -59,6 +74,8 @@ public abstract class AbstractTerminalWidget extends AbstractGui {
private int windowLeft, windowTop;
private boolean isMouseOverTerminal;
private int currentEnergy, maxEnergy, energyConsumption;
///////////////////////////////////////////////////////////////////
protected AbstractTerminalWidget(final Screen parent, final Terminal terminal) {
@@ -66,13 +83,27 @@ public abstract class AbstractTerminalWidget extends AbstractGui {
this.terminal = terminal;
}
public void setEnergyInfo(final int current, final int capacity, final int consumption) {
this.currentEnergy = current;
this.maxEnergy = capacity;
this.energyConsumption = consumption;
}
public void renderBackground(final MatrixStack matrixStack, final int mouseX, final int mouseY) {
isMouseOverTerminal = isOverTerminal(mouseX, mouseY);
isMouseOverTerminal = isMouseOverTerminal(mouseX, mouseY);
RenderSystem.color4f(1f, 1f, 1f, 1f);
getClient().getTextureManager().bindTexture(BACKGROUND_LOCATION);
CONTROLS_BACKGROUND.draw(matrixStack, windowLeft - CONTROLS_BACKGROUND.width, windowTop + CONTROLS_TOP);
if (maxEnergy > 0) {
final int x = windowLeft - ENERGY_BACKGROUND.width;
final int y = windowTop + ENERGY_TOP;
ENERGY_BACKGROUND.draw(matrixStack, x, y);
ENERGY_BASE.draw(matrixStack, x + 4, y + 4);
}
BACKGROUND.draw(matrixStack, windowLeft, windowTop);
if (shouldCaptureInput()) {
@@ -80,7 +111,7 @@ public abstract class AbstractTerminalWidget extends AbstractGui {
}
}
public void render(final MatrixStack matrixStack, @Nullable final ITextComponent error) {
public void render(final MatrixStack matrixStack, final int mouseX, final int mouseY, @Nullable final ITextComponent error) {
if (isRunning()) {
final MatrixStack stack = new MatrixStack();
stack.translate(windowLeft + TERMINAL_X, windowTop + TERMINAL_Y, getClient().getItemRenderer().zLevel);
@@ -99,6 +130,18 @@ public abstract class AbstractTerminalWidget extends AbstractGui {
0xEE3322);
}
}
if (maxEnergy > 0) {
ENERGY_BAR.drawFillY(matrixStack, windowLeft - ENERGY_BACKGROUND.width + 4, windowTop + ENERGY_TOP + 4, currentEnergy / (float) maxEnergy);
if (isMouseOver(mouseX, mouseY, -ENERGY_BACKGROUND.width + 4, ENERGY_TOP + 4, ENERGY_BAR.width, ENERGY_BAR.height)) {
final List<? extends ITextProperties> tooltip = Arrays.asList(
new TranslationTextComponent(Constants.TOOLTIP_ENERGY, withColor(currentEnergy + "/" + maxEnergy, TextFormatting.GREEN)),
new TranslationTextComponent(Constants.TOOLTIP_ENERGY_CONSUMPTION, withColor(String.valueOf(energyConsumption), TextFormatting.GREEN))
);
GuiUtils.drawHoveringText(matrixStack, tooltip, mouseX, mouseY, parent.width, parent.height, 200, getClient().fontRenderer);
}
}
}
public void tick() {
@@ -209,12 +252,18 @@ public abstract class AbstractTerminalWidget extends AbstractGui {
return isMouseOverTerminal && isInputCaptureEnabled && isRunning();
}
private boolean isOverTerminal(final int mouseX, final int mouseY) {
private boolean isMouseOverTerminal(final int mouseX, final int mouseY) {
return isMouseOver(mouseX, mouseY,
AbstractTerminalWidget.TERMINAL_X, AbstractTerminalWidget.TERMINAL_Y,
AbstractTerminalWidget.TERMINAL_WIDTH, AbstractTerminalWidget.TERMINAL_HEIGHT);
}
private boolean isMouseOver(final int mouseX, final int mouseY, final int x, final int y, final int width, final int height) {
final int localMouseX = mouseX - windowLeft;
final int localMouseY = mouseY - windowTop;
return localMouseX >= AbstractTerminalWidget.TERMINAL_X &&
localMouseX < AbstractTerminalWidget.TERMINAL_X + AbstractTerminalWidget.TERMINAL_WIDTH &&
localMouseY >= AbstractTerminalWidget.TERMINAL_Y &&
localMouseY < AbstractTerminalWidget.TERMINAL_Y + AbstractTerminalWidget.TERMINAL_HEIGHT;
return localMouseX >= x &&
localMouseX < x + width &&
localMouseY >= y &&
localMouseY < y + height;
}
}

View File

@@ -1,42 +1,50 @@
package li.cil.oc2.client.gui;
import com.mojang.blaze3d.matrix.MatrixStack;
import li.cil.oc2.common.container.ComputerTerminalContainer;
import li.cil.oc2.common.network.Network;
import li.cil.oc2.common.network.message.ComputerPowerMessage;
import li.cil.oc2.common.network.message.ComputerTerminalInputMessage;
import li.cil.oc2.common.tileentity.ComputerTileEntity;
import li.cil.oc2.common.vm.Terminal;
import net.minecraft.client.entity.player.ClientPlayerEntity;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.inventory.ContainerScreen;
import net.minecraft.client.gui.widget.Widget;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.client.util.InputMappings;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.util.text.ITextComponent;
import java.nio.ByteBuffer;
public final class ComputerTerminalScreen extends Screen {
private final ComputerTileEntity computer;
public final class ComputerTerminalScreen extends ContainerScreen<ComputerTerminalContainer> {
private final ComputerTerminalWidget terminalWidget;
///////////////////////////////////////////////////////////////////
public ComputerTerminalScreen(final ComputerTileEntity computer, final ITextComponent title) {
super(title);
this.computer = computer;
this.terminalWidget = new ComputerTerminalWidget(computer.getTerminal());
public ComputerTerminalScreen(final ComputerTerminalContainer container, final PlayerInventory playerInventory, final ITextComponent title) {
super(container, playerInventory, title);
this.terminalWidget = new ComputerTerminalWidget(container.getComputer().getTerminal());
xSize = AbstractTerminalWidget.WIDTH;
ySize = AbstractTerminalWidget.HEIGHT;
}
///////////////////////////////////////////////////////////////////
@Override
public void render(final MatrixStack matrixStack, final int mouseX, final int mouseY, final float partialTicks) {
renderBackground(matrixStack);
protected void drawGuiContainerBackgroundLayer(final MatrixStack matrixStack, final float partialTicks, final int mouseX, final int mouseY) {
terminalWidget.renderBackground(matrixStack, mouseX, mouseY);
}
@Override
protected void drawGuiContainerForegroundLayer(final MatrixStack matrixStack, final int mouseX, final int mouseY) {
}
@Override
public void render(final MatrixStack matrixStack, final int mouseX, final int mouseY, final float partialTicks) {
terminalWidget.setEnergyInfo(container.getEnergy(), container.getEnergyCapacity(), container.getEnergyConsumption());
renderBackground(matrixStack);
super.render(matrixStack, mouseX, mouseY, partialTicks);
terminalWidget.render(matrixStack, computer.getVirtualMachine().getBootError());
terminalWidget.render(matrixStack, mouseX, mouseY, container.getComputer().getVirtualMachine().getBootError());
}
@Override
@@ -44,16 +52,6 @@ public final class ComputerTerminalScreen extends Screen {
super.tick();
terminalWidget.tick();
final ClientPlayerEntity player = getMinecraft().player;
if (!player.isAlive() || !canInteractWith(player)) {
closeScreen();
}
}
@Override
public boolean isPauseScreen() {
return false;
}
@Override
@@ -64,8 +62,18 @@ public final class ComputerTerminalScreen extends Screen {
@Override
public boolean keyPressed(final int keyCode, final int scanCode, final int modifiers) {
return terminalWidget.keyPressed(keyCode, scanCode, modifiers) ||
super.keyPressed(keyCode, scanCode, modifiers);
if (terminalWidget.keyPressed(keyCode, scanCode, modifiers)) {
return true;
}
// Don't close with inventory binding since we usually want to use that as terminal input
// even without input capture enabled.
final InputMappings.Input input = InputMappings.getInputByCode(keyCode, scanCode);
if (this.minecraft.gameSettings.keyBindInventory.isActiveAndMatches(input)) {
return true;
}
return super.keyPressed(keyCode, scanCode, modifiers);
}
@Override
@@ -82,12 +90,6 @@ public final class ComputerTerminalScreen extends Screen {
///////////////////////////////////////////////////////////////////
private boolean canInteractWith(final PlayerEntity player) {
return Vector3d.copyCentered(computer.getPos()).isWithinDistanceOf(player.getPositionVec(), 8);
}
///////////////////////////////////////////////////////////////////
private final class ComputerTerminalWidget extends AbstractTerminalWidget {
public ComputerTerminalWidget(final Terminal terminal) {
super(ComputerTerminalScreen.this, terminal);
@@ -95,7 +97,7 @@ public final class ComputerTerminalScreen extends Screen {
@Override
protected boolean isRunning() {
return computer.getVirtualMachine().isRunning();
return container.getComputer().getVirtualMachine().isRunning();
}
@Override
@@ -105,12 +107,12 @@ public final class ComputerTerminalScreen extends Screen {
@Override
protected void sendPowerStateToServer(final boolean value) {
Network.INSTANCE.sendToServer(new ComputerPowerMessage(computer, value));
Network.INSTANCE.sendToServer(new ComputerPowerMessage(container.getComputer(), value));
}
@Override
protected void sendTerminalInputToServer(final ByteBuffer input) {
Network.INSTANCE.sendToServer(new ComputerTerminalInputMessage(computer, input));
Network.INSTANCE.sendToServer(new ComputerTerminalInputMessage(container.getComputer(), input));
}
}
}

View File

@@ -3,7 +3,6 @@ package li.cil.oc2.client.gui;
import com.mojang.blaze3d.matrix.MatrixStack;
import li.cil.oc2.client.gui.widget.Sprite;
import li.cil.oc2.common.container.RobotTerminalContainer;
import li.cil.oc2.common.entity.RobotEntity;
import li.cil.oc2.common.network.Network;
import li.cil.oc2.common.network.message.RobotPowerMessage;
import li.cil.oc2.common.network.message.RobotTerminalInputMessage;
@@ -40,15 +39,17 @@ public final class RobotTerminalScreen extends ContainerScreen<RobotTerminalCont
}
@Override
protected void drawGuiContainerForegroundLayer(final MatrixStack matrixStack, final int x, final int y) {
protected void drawGuiContainerForegroundLayer(final MatrixStack matrixStack, final int mouseX, final int mouseY) {
}
@Override
public void render(final MatrixStack matrixStack, final int mouseX, final int mouseY, final float partialTicks) {
terminalWidget.setEnergyInfo(container.getEnergy(), container.getEnergyCapacity(), container.getEnergyConsumption());
renderBackground(matrixStack);
super.render(matrixStack, mouseX, mouseY, partialTicks);
terminalWidget.render(matrixStack, getRobot().getVirtualMachine().getBootError());
RobotContainerScreen.renderSelection(matrixStack, getRobot().getSelectedSlot(), guiLeft + SLOTS_X + 4, guiTop + SLOTS_Y + 4, 12);
terminalWidget.render(matrixStack, mouseX, mouseY, container.getRobot().getVirtualMachine().getBootError());
RobotContainerScreen.renderSelection(matrixStack, container.getRobot().getSelectedSlot(), guiLeft + SLOTS_X + 4, guiTop + SLOTS_Y + 4, 12);
renderHoveredTooltip(matrixStack, mouseX, mouseY);
}
@@ -95,12 +96,6 @@ public final class RobotTerminalScreen extends ContainerScreen<RobotTerminalCont
///////////////////////////////////////////////////////////////////
private RobotEntity getRobot() {
return container.getRobot();
}
///////////////////////////////////////////////////////////////////
private final class RobotTerminalWidget extends AbstractTerminalWidget {
public RobotTerminalWidget(final Terminal terminal) {
super(RobotTerminalScreen.this, terminal);
@@ -108,7 +103,7 @@ public final class RobotTerminalScreen extends ContainerScreen<RobotTerminalCont
@Override
protected boolean isRunning() {
return getRobot().getVirtualMachine().isRunning();
return container.getRobot().getVirtualMachine().isRunning();
}
@Override
@@ -118,12 +113,12 @@ public final class RobotTerminalScreen extends ContainerScreen<RobotTerminalCont
@Override
protected void sendPowerStateToServer(final boolean value) {
Network.INSTANCE.sendToServer(new RobotPowerMessage(getRobot(), value));
Network.INSTANCE.sendToServer(new RobotPowerMessage(container.getRobot(), value));
}
@Override
protected void sendTerminalInputToServer(final ByteBuffer input) {
Network.INSTANCE.sendToServer(new RobotTerminalInputMessage(getRobot(), input));
Network.INSTANCE.sendToServer(new RobotTerminalInputMessage(container.getRobot(), input));
}
}
}

View File

@@ -24,4 +24,10 @@ public final class Sprite extends AbstractGui {
Minecraft.getInstance().getTextureManager().bindTexture(image);
blit(stack, x, y, u0, v0, width, height, textureSize, textureSize);
}
public void drawFillY(final MatrixStack stack, final int x, final int y, final float value) {
Minecraft.getInstance().getTextureManager().bindTexture(image);
final int h = (int) (this.height * value);
blit(stack, x, y + (height - h), u0, v0 + (height - h), width, h, textureSize, textureSize);
}
}

View File

@@ -26,12 +26,21 @@ public final class Config {
public static int maxFlashMemorySize = 4 * Constants.KILOBYTE;
public static int maxFloppySize = 512 * Constants.KILOBYTE;
public static int computerEnergyPerTick = 20;
public static int computerEnergyStorage = 4000;
public static int robotEnergyPerTick = 10;
public static int robotEnergyStorage = 600000;
public static double busCableEnergyPerTick = 0.1;
public static double busInterfaceEnergyPerTick = 0.5;
public static int computerEnergyPerTick = 10;
public static int computerEnergyStorage = 2000;
public static int robotEnergyPerTick = 5;
public static int robotEnergyStorage = 750000;
public static int chargerEnergyPerTick = 2500;
public static int chargerEnergyStorage = 50000;
public static int chargerEnergyStorage = 10000;
public static double memoryEnergyPerMegabytePerTick = 0.5;
public static double hardDriveEnergyPerMegabytePerTick = 1;
public static int networkInterfaceEnergyPerTick = 1;
public static int redstoneInterfaceCardEnergyPerTick = 1;
public static int blockOperationsModuleEnergyPerTick = 2;
public static int inventoryOperationsModuleEnergyPerTick = 1;
public static int blockOperationsModuleToolLevel = Items.DIAMOND_PICKAXE.getHarvestLevel(new ItemStack(Items.DIAMOND_PICKAXE), ToolType.PICKAXE, null, null);
@@ -73,6 +82,9 @@ public final class Config {
maxHardDriveSize = COMMON_INSTANCE.maxHardDriveSize.get();
maxFlashMemorySize = COMMON_INSTANCE.maxFlashMemorySize.get();
busCableEnergyPerTick = COMMON_INSTANCE.busCableEnergyPerTick.get();
busInterfaceEnergyPerTick = COMMON_INSTANCE.busInterfaceEnergyPerTick.get();
computerEnergyPerTick = COMMON_INSTANCE.computerEnergyPerTick.get();
computerEnergyStorage = COMMON_INSTANCE.computerEnergyStorage.get();
robotEnergyPerTick = COMMON_INSTANCE.robotEnergyPerTick.get();
@@ -94,6 +106,8 @@ public final class Config {
public final ForgeConfigSpec.IntValue maxHardDriveSize;
public final ForgeConfigSpec.IntValue maxFlashMemorySize;
public final ForgeConfigSpec.DoubleValue busCableEnergyPerTick;
public final ForgeConfigSpec.DoubleValue busInterfaceEnergyPerTick;
public final ForgeConfigSpec.IntValue computerEnergyPerTick;
public final ForgeConfigSpec.IntValue computerEnergyStorage;
public final ForgeConfigSpec.IntValue robotEnergyPerTick;
@@ -132,9 +146,19 @@ public final class Config {
builder.push("energy");
busCableEnergyPerTick = builder
.translation(Constants.CONFIG_BUS_CABLE_COMPLEXITY)
.comment("The amount of energy (Forge Energy/RF) a single bus cable consumes per tick.")
.defineInRange("busCableEnergyPerTick", Config.busCableEnergyPerTick, 0, Double.MAX_VALUE);
busInterfaceEnergyPerTick = builder
.translation(Constants.CONFIG_BUS_INTERFACE_COMPLEXITY)
.comment("The amount of energy (Forge Energy/RF) a single bus interface consumes per tick.")
.defineInRange("busInterfaceEnergyPerTick", Config.busInterfaceEnergyPerTick, 0, Double.MAX_VALUE);
computerEnergyPerTick = builder
.translation(Constants.CONFIG_COMPUTER_ENERGY_PER_TICK)
.comment("The amount of energy (Forge Energy/RF) a computer draws per tick. Set to zero to disable.")
.comment("The amount of energy (Forge Energy/RF) a computer consumes per tick. Set to zero to disable.")
.defineInRange("computerEnergyPerTick", Config.computerEnergyPerTick, 0, Integer.MAX_VALUE);
computerEnergyStorage = builder
@@ -144,7 +168,7 @@ public final class Config {
robotEnergyPerTick = builder
.translation(Constants.CONFIG_ROBOT_ENERGY_PER_TICK)
.comment("The amount of energy (Forge Energy/RF) a robot draws per tick. Set to zero to disable.")
.comment("The amount of energy (Forge Energy/RF) a robot consumes per tick. Set to zero to disable.")
.defineInRange("robotEnergyPerTick", Config.robotEnergyPerTick, 0, Integer.MAX_VALUE);
robotEnergyStorage = builder

View File

@@ -32,6 +32,7 @@ public final class Constants {
public static final String DISK_DRIVE_BLOCK_NAME = "disk_drive";
public static final String REDSTONE_INTERFACE_BLOCK_NAME = "redstone_interface";
public static final String CHARGER_BLOCK_NAME = "charger";
public static final String CREATIVE_ENERGY_BLOCK_NAME = "creative_energy";
///////////////////////////////////////////////////////////////////
@@ -62,6 +63,7 @@ public final class Constants {
public static final String TOOLTIP_MEMORY_MISSING = "tooltip.oc2.memory_missing";
public static final String TOOLTIP_HARD_DRIVE_MISSING = "tooltip.oc2.hard_drive_missing";
public static final String TOOLTIP_ENERGY = "tooltip.oc2.energy";
public static final String TOOLTIP_ENERGY_CONSUMPTION = "tooltip.oc2.energyConsumption";
///////////////////////////////////////////////////////////////////
@@ -71,6 +73,9 @@ public final class Constants {
public static final String CONFIG_MAX_FLASH_MEMORY_SIZE = "config.oc2.vm.maxFlashMemorySize";
public static final String CONFIG_BLOCK_OPERATIONS_MODULE_TOOL_LEVEL = "config.oc2.modules.block_operations.toolLevel";
public static final String CONFIG_FAKE_PLAYER_UUID = "config.oc2.admin.fakePlayerUUID";
public static final String CONFIG_BUS_CABLE_COMPLEXITY = "config.oc2.busCableComplexity";
public static final String CONFIG_BUS_INTERFACE_COMPLEXITY = "config.oc2.busInterfaceComplexity";
public static final String CONFIG_BUS_COMPLEXITY_ENERGY_PER_TICK = "config.oc2.complexityEnergyPerTick";
public static final String CONFIG_COMPUTER_ENERGY_PER_TICK = "config.oc2.computerEnergyPerTick";
public static final String CONFIG_COMPUTER_ENERGY_STORAGE = "config.oc2.computerEnergyStorage";
public static final String CONFIG_ROBOT_ENERGY_PER_TICK = "config.oc2.robotEnergyPerTick";

View File

@@ -20,6 +20,7 @@ public final class Blocks {
public static final RegistryObject<RedstoneInterfaceBlock> REDSTONE_INTERFACE = BLOCKS.register(Constants.REDSTONE_INTERFACE_BLOCK_NAME, RedstoneInterfaceBlock::new);
public static final RegistryObject<DiskDriveBlock> DISK_DRIVE = BLOCKS.register(Constants.DISK_DRIVE_BLOCK_NAME, DiskDriveBlock::new);
public static final RegistryObject<ChargerBlock> CHARGER = BLOCKS.register(Constants.CHARGER_BLOCK_NAME, ChargerBlock::new);
public static final RegistryObject<CreativeEnergyBlock> CREATIVE_ENERGY = BLOCKS.register(Constants.CREATIVE_ENERGY_BLOCK_NAME, CreativeEnergyBlock::new);
///////////////////////////////////////////////////////////////////

View File

@@ -89,6 +89,16 @@ public final class BusCableBlock extends Block {
}
}
public static int getInterfaceCount(final BlockState state) {
int partCount = 0;
for (final EnumProperty<ConnectionType> connectionType : FACING_TO_CONNECTION_MAP.values()) {
if (state.get(connectionType) == ConnectionType.INTERFACE) {
partCount++;
}
}
return partCount;
}
///////////////////////////////////////////////////////////////////
private final VoxelShape[] shapes;
@@ -143,7 +153,6 @@ public final class BusCableBlock extends Block {
return true;
}
@Nullable
@Override
public TileEntity createTileEntity(final BlockState state, final IBlockReader world) {
return TileEntities.BUS_CABLE_TILE_ENTITY.get().create();
@@ -257,10 +266,9 @@ public final class BusCableBlock extends Block {
}
private static int getPartCount(final BlockState state) {
int partCount = 0;
if (state.get(HAS_CABLE)) partCount++;
for (final EnumProperty<ConnectionType> connectionType : FACING_TO_CONNECTION_MAP.values()) {
if (state.get(connectionType) == ConnectionType.INTERFACE) partCount++;
int partCount = getInterfaceCount(state);
if (state.get(HAS_CABLE)) {
partCount++;
}
return partCount;
}

View File

@@ -2,12 +2,11 @@ package li.cil.oc2.common.block;
import li.cil.oc2.api.bus.device.DeviceTypes;
import li.cil.oc2.api.capabilities.RedstoneEmitter;
import li.cil.oc2.client.gui.ComputerTerminalScreen;
import li.cil.oc2.common.Config;
import li.cil.oc2.common.Constants;
import li.cil.oc2.common.bus.device.data.BlockDeviceDataRegistration;
import li.cil.oc2.common.bus.device.data.Firmwares;
import li.cil.oc2.common.capabilities.Capabilities;
import li.cil.oc2.common.container.ComputerContainer;
import li.cil.oc2.common.integration.Wrenches;
import li.cil.oc2.common.item.Items;
import li.cil.oc2.common.tileentity.ComputerTileEntity;
@@ -20,13 +19,9 @@ import net.minecraft.block.BlockState;
import net.minecraft.block.HorizontalBlock;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.client.Minecraft;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.inventory.container.Container;
import net.minecraft.inventory.container.INamedContainerProvider;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
@@ -43,13 +38,11 @@ import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.util.math.shapes.VoxelShapes;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorldReader;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.network.NetworkHooks;
import javax.annotation.Nullable;
import java.util.List;
@@ -95,6 +88,7 @@ public final class ComputerBlock extends HorizontalBlock {
@Override
public void addInformation(final ItemStack stack, @Nullable final IBlockReader world, final List<ITextComponent> tooltip, final ITooltipFlag advanced) {
super.addInformation(stack, world, tooltip, advanced);
TooltipUtils.addEnergyConsumption(Config.computerEnergyPerTick, tooltip);
TooltipUtils.addTileEntityInventoryInformation(stack, tooltip);
}
@@ -103,7 +97,6 @@ public final class ComputerBlock extends HorizontalBlock {
return true;
}
@Nullable
@Override
public TileEntity createTileEntity(final BlockState state, final IBlockReader world) {
return TileEntities.COMPUTER_TILE_ENTITY.get().create();
@@ -177,15 +170,17 @@ public final class ComputerBlock extends HorizontalBlock {
final ComputerTileEntity computer = (ComputerTileEntity) tileEntity;
final ItemStack heldItem = player.getHeldItem(hand);
if (Wrenches.isWrench(heldItem)) {
if (!world.isRemote() && player instanceof ServerPlayerEntity) {
openContainerScreen(computer, player);
}
} else {
if (player.isSneaking()) {
computer.start();
} else if (world.isRemote()) {
openTerminalScreen(computer);
if (!world.isRemote()) {
if (Wrenches.isWrench(heldItem)) {
if (player instanceof ServerPlayerEntity) {
computer.openContainerScreen((ServerPlayerEntity) player);
}
} else {
if (player.isSneaking()) {
computer.start();
} else if (player instanceof ServerPlayerEntity) {
computer.openTerminalScreen((ServerPlayerEntity) player);
}
}
}
@@ -226,25 +221,6 @@ public final class ComputerBlock extends HorizontalBlock {
///////////////////////////////////////////////////////////////////
@OnlyIn(Dist.CLIENT)
private void openTerminalScreen(final ComputerTileEntity computer) {
Minecraft.getInstance().displayGuiScreen(new ComputerTerminalScreen(computer, getTranslatedName()));
}
private void openContainerScreen(final ComputerTileEntity tileEntity, final PlayerEntity player) {
NetworkHooks.openGui((ServerPlayerEntity) player, new INamedContainerProvider() {
@Override
public ITextComponent getDisplayName() {
return new TranslationTextComponent(getTranslationKey());
}
@Override
public Container createMenu(final int id, final PlayerInventory inventory, final PlayerEntity player) {
return new ComputerContainer(id, tileEntity, inventory);
}
}, tileEntity.getPos());
}
private ItemStack getPreconfiguredComputer() {
final ItemStack computer = new ItemStack(Items.COMPUTER.get());

View File

@@ -0,0 +1,31 @@
package li.cil.oc2.common.block;
import li.cil.oc2.common.tileentity.TileEntities;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.IBlockReader;
public final class CreativeEnergyBlock extends Block {
public CreativeEnergyBlock() {
super(Properties
.create(Material.IRON)
.sound(SoundType.METAL)
.hardnessAndResistance(-1, 3600000)
.noDrops());
}
///////////////////////////////////////////////////////////////////
@Override
public boolean hasTileEntity(final BlockState state) {
return true;
}
@Override
public TileEntity createTileEntity(final BlockState state, final IBlockReader world) {
return TileEntities.CREATIVE_ENERGY_TILE_ENTITY.get().create();
}
}

View File

@@ -21,8 +21,6 @@ import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.World;
import javax.annotation.Nullable;
public final class DiskDriveBlock extends HorizontalBlock {
public DiskDriveBlock() {
super(Properties
@@ -44,7 +42,6 @@ public final class DiskDriveBlock extends HorizontalBlock {
return true;
}
@Nullable
@Override
public TileEntity createTileEntity(final BlockState state, final IBlockReader world) {
return TileEntities.DISK_DRIVE_TILE_ENTITY.get().create();

View File

@@ -17,7 +17,6 @@ import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.World;
import javax.annotation.Nullable;
import java.util.Objects;
public final class NetworkConnectorBlock extends HorizontalFaceBlock {
@@ -51,7 +50,6 @@ public final class NetworkConnectorBlock extends HorizontalFaceBlock {
return true;
}
@Nullable
@Override
public TileEntity createTileEntity(final BlockState state, final IBlockReader world) {
return TileEntities.NETWORK_CONNECTOR_TILE_ENTITY.get().create();

View File

@@ -15,8 +15,6 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.World;
import javax.annotation.Nullable;
public final class NetworkHubBlock extends HorizontalBlock {
public NetworkHubBlock() {
super(Properties
@@ -38,7 +36,6 @@ public final class NetworkHubBlock extends HorizontalBlock {
return true;
}
@Nullable
@Override
public TileEntity createTileEntity(final BlockState state, final IBlockReader world) {
return TileEntities.NETWORK_HUB_TILE_ENTITY.get().create();

View File

@@ -15,8 +15,6 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorldReader;
import javax.annotation.Nullable;
public final class RedstoneInterfaceBlock extends HorizontalBlock {
public RedstoneInterfaceBlock() {
super(Properties
@@ -38,7 +36,6 @@ public final class RedstoneInterfaceBlock extends HorizontalBlock {
return true;
}
@Nullable
@Override
public TileEntity createTileEntity(final BlockState state, final IBlockReader world) {
return TileEntities.REDSTONE_INTERFACE_TILE_ENTITY.get().create();

View File

@@ -1,5 +1,7 @@
package li.cil.oc2.common.bus;
import it.unimi.dsi.fastutil.objects.Object2IntArrayMap;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import li.cil.oc2.api.bus.DeviceBusController;
import li.cil.oc2.api.bus.DeviceBusElement;
import li.cil.oc2.api.bus.device.Device;
@@ -9,11 +11,17 @@ import java.util.*;
import java.util.stream.Collectors;
public abstract class AbstractDeviceBusElement implements DeviceBusElement {
protected final HashSet<Device> devices = new HashSet<>();
protected final Object2IntArrayMap<Device> devices = new Object2IntArrayMap<>();
protected final HashSet<DeviceBusController> controllers = new HashSet<>();
///////////////////////////////////////////////////////////////////
public void addDevice(final Device device) {
devices.put(device, 0);
scanDevices();
}
@Override
public void addController(final DeviceBusController controller) {
controllers.add(controller);
}
@@ -35,7 +43,7 @@ public abstract class AbstractDeviceBusElement implements DeviceBusElement {
@Override
public Collection<Device> getLocalDevices() {
return devices;
return devices.keySet();
}
@Override
@@ -44,15 +52,12 @@ public abstract class AbstractDeviceBusElement implements DeviceBusElement {
}
@Override
public void addDevice(final Device device) {
devices.add(device);
scanDevices();
}
@Override
public void removeDevice(final Device device) {
devices.remove(device);
scanDevices();
public double getEnergyConsumption() {
long accumulator = 0;
for (final Object2IntMap.Entry<Device> entry : devices.object2IntEntrySet()) {
accumulator += entry.getIntValue();
}
return accumulator;
}
@Override

View File

@@ -10,7 +10,6 @@ import net.minecraftforge.common.util.INBTSerializable;
import net.minecraftforge.registries.IForgeRegistryEntry;
import java.util.*;
import java.util.stream.Collectors;
public abstract class AbstractGroupingDeviceBusElement<TProvider extends IForgeRegistryEntry<TProvider>, TDeviceInfo extends AbstractDeviceInfo<TProvider, ?>> extends AbstractDeviceBusElement implements INBTSerializable<ListNBT> {
private static final String GROUP_ID_TAG_NAME = "groupId";
@@ -101,11 +100,15 @@ public abstract class AbstractGroupingDeviceBusElement<TProvider extends IForgeR
final HashSet<TDeviceInfo> removedDevices = new HashSet<>(oldDevices);
removedDevices.removeAll(newDevices);
devices.removeAll(removedDevices.stream().map(info -> info.device).collect(Collectors.toList()));
for (final TDeviceInfo info : removedDevices) {
devices.removeInt(info.device);
}
final HashSet<TDeviceInfo> addedDevices = new HashSet<>(newDevices);
addedDevices.removeAll(oldDevices);
devices.addAll(addedDevices.stream().map(info -> info.device).collect(Collectors.toList()));
for (final TDeviceInfo info : addedDevices) {
devices.put(info.device, info.getEnergyConsumption());
}
oldDevices.removeAll(removedDevices);
oldDevices.addAll(newDevices);

View File

@@ -36,6 +36,7 @@ public class CommonDeviceBusController implements DeviceBusController {
public final ParameterizedEvent<DevicesChangedEvent> onDevicesRemoved = new ParameterizedEvent<>();
private final DeviceBusElement root;
private final int baseEnergyConsumption;
private final Set<DeviceBusElement> elements = new HashSet<>();
private final HashSet<Device> devices = new HashSet<>();
@@ -44,10 +45,13 @@ public class CommonDeviceBusController implements DeviceBusController {
private BusState state = BusState.SCAN_PENDING;
private int scanDelay;
private int energyConsumption;
///////////////////////////////////////////////////////////////////
public CommonDeviceBusController(final DeviceBusElement root) {
public CommonDeviceBusController(final DeviceBusElement root, final int baseEnergyConsumption) {
this.root = root;
this.baseEnergyConsumption = baseEnergyConsumption;
}
///////////////////////////////////////////////////////////////////
@@ -67,6 +71,10 @@ public class CommonDeviceBusController implements DeviceBusController {
return state;
}
public int getEnergyConsumption() {
return energyConsumption;
}
@Override
public void scheduleBusScan() {
scanDelay = 0; // scan as soon as possible
@@ -206,6 +214,8 @@ public class CommonDeviceBusController implements DeviceBusController {
scanDevices();
updateEnergyConsumption();
state = BusState.READY;
}
@@ -245,6 +255,19 @@ public class CommonDeviceBusController implements DeviceBusController {
elements.clear();
}
private void updateEnergyConsumption() {
double accumulator = baseEnergyConsumption;
for (final DeviceBusElement element : elements) {
accumulator += Math.max(0, element.getEnergyConsumption());
}
if (accumulator > Integer.MAX_VALUE) {
energyConsumption = Integer.MAX_VALUE;
} else {
energyConsumption = (int) accumulator;
}
}
///////////////////////////////////////////////////////////////////
public static final class AfterDeviceScanEvent {

View File

@@ -1,7 +1,9 @@
package li.cil.oc2.common.bus;
import li.cil.oc2.api.bus.device.provider.ItemDeviceQuery;
import li.cil.oc2.api.bus.device.rpc.RPCDevice;
import li.cil.oc2.common.bus.device.rpc.TypeNameRPCDevice;
import li.cil.oc2.common.bus.device.util.Devices;
import li.cil.oc2.common.bus.device.util.ItemDeviceInfo;
import li.cil.oc2.common.util.ItemDeviceUtils;
import li.cil.oc2.common.util.NBTTagIds;
@@ -11,22 +13,22 @@ import net.minecraft.util.ResourceLocation;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.function.Function;
public class ItemHandlerDeviceBusElement extends AbstractGroupingItemDeviceBusElement {
private final Function<ItemStack, List<ItemDeviceInfo>> deviceLookup;
private final Function<ItemStack, ItemDeviceQuery> queryFactory;
public ItemHandlerDeviceBusElement(final int slotCount, final Function<ItemStack, List<ItemDeviceInfo>> deviceLookup) {
public ItemHandlerDeviceBusElement(final int slotCount, final Function<ItemStack, ItemDeviceQuery> queryFactory) {
super(slotCount);
this.deviceLookup = deviceLookup;
this.queryFactory = queryFactory;
}
///////////////////////////////////////////////////////////////////
public void updateDevices(final int slot, final ItemStack stack) {
if (!stack.isEmpty()) {
final HashSet<ItemDeviceInfo> newDevices = new HashSet<>(deviceLookup.apply(stack));
final ItemDeviceQuery query = queryFactory.apply(stack);
final HashSet<ItemDeviceInfo> newDevices = new HashSet<>(Devices.getDevices(query));
insertItemNameDevice(stack, newDevices);
importDeviceDataFromItemStack(stack, newDevices);
setDevicesForGroup(slot, newDevices);
@@ -75,7 +77,7 @@ public class ItemHandlerDeviceBusElement extends AbstractGroupingItemDeviceBusEl
if (devices.stream().anyMatch(info -> info.device instanceof RPCDevice)) {
final ResourceLocation registryName = stack.getItem().getRegistryName();
if (registryName != null) {
devices.add(new ItemDeviceInfo(null, new TypeNameRPCDevice(registryName.toString())));
devices.add(new ItemDeviceInfo(null, new TypeNameRPCDevice(registryName.toString()), 0));
}
}
}

View File

@@ -19,8 +19,8 @@ public class TileEntityDeviceBusController extends CommonDeviceBusController {
///////////////////////////////////////////////////////////////////
public TileEntityDeviceBusController(final DeviceBusElement root, final TileEntity tileEntity) {
super(root);
public TileEntityDeviceBusController(final DeviceBusElement root, final int baseEnergyConsumption, final TileEntity tileEntity) {
super(root, baseEnergyConsumption);
this.tileEntity = tileEntity;
}

View File

@@ -3,6 +3,7 @@ package li.cil.oc2.common.bus;
import li.cil.oc2.api.bus.BlockDeviceBusElement;
import li.cil.oc2.api.bus.DeviceBus;
import li.cil.oc2.api.bus.DeviceBusElement;
import li.cil.oc2.api.bus.device.provider.BlockDeviceQuery;
import li.cil.oc2.api.bus.device.rpc.RPCDevice;
import li.cil.oc2.common.Constants;
import li.cil.oc2.common.bus.device.rpc.TypeNameRPCDevice;
@@ -93,7 +94,8 @@ public class TileEntityDeviceBusElement extends AbstractGroupingBlockDeviceBusEl
final HashSet<BlockDeviceInfo> newDevices = new HashSet<>();
if (canDetectDevicesTowards(direction)) {
for (final LazyOptional<BlockDeviceInfo> deviceInfo : Devices.getDevices(world, pos, direction)) {
final BlockDeviceQuery query = Devices.makeQuery(world, pos, direction);
for (final LazyOptional<BlockDeviceInfo> deviceInfo : Devices.getDevices(query)) {
deviceInfo.ifPresent(newDevices::add);
deviceInfo.addListener(unused -> handleNeighborChanged(pos));
}

View File

@@ -4,6 +4,7 @@ import li.cil.oc2.api.bus.device.DeviceType;
import li.cil.oc2.api.bus.device.DeviceTypes;
import li.cil.oc2.api.bus.device.ItemDevice;
import li.cil.oc2.api.bus.device.provider.ItemDeviceQuery;
import li.cil.oc2.common.Config;
import li.cil.oc2.common.bus.device.item.BlockOperationsModuleDevice;
import li.cil.oc2.common.bus.device.provider.util.AbstractItemDeviceProvider;
import li.cil.oc2.common.capabilities.Capabilities;
@@ -29,4 +30,9 @@ public final class BlockOperationsModuleDeviceProvider extends AbstractItemDevic
entity.getCapability(Capabilities.ROBOT).map(robot ->
new BlockOperationsModuleDevice(query.getItemStack(), entity, robot)));
}
@Override
protected int getItemDeviceEnergyConsumption(final ItemDeviceQuery query) {
return Config.blockOperationsModuleEnergyPerTick;
}
}

View File

@@ -6,10 +6,12 @@ import li.cil.oc2.api.bus.device.ItemDevice;
import li.cil.oc2.api.bus.device.data.BlockDeviceData;
import li.cil.oc2.api.bus.device.provider.ItemDeviceQuery;
import li.cil.oc2.common.Config;
import li.cil.oc2.common.Constants;
import li.cil.oc2.common.bus.device.item.HardDriveVMDevice;
import li.cil.oc2.common.bus.device.item.SparseHardDriveVMDevice;
import li.cil.oc2.common.bus.device.provider.util.AbstractItemDeviceProvider;
import li.cil.oc2.common.item.AbstractBlockDeviceItem;
import li.cil.oc2.common.item.HardDriveItem;
import li.cil.oc2.common.item.Items;
import li.cil.oc2.common.util.LocationSupplierUtils;
import li.cil.sedna.api.device.BlockDevice;
@@ -44,4 +46,16 @@ public final class HardDriveItemDeviceProvider extends AbstractItemDeviceProvide
protected Optional<DeviceType> getItemDeviceType(final ItemDeviceQuery query) {
return Optional.of(DeviceTypes.HARD_DRIVE);
}
@Override
protected int getItemDeviceEnergyConsumption(final ItemDeviceQuery query) {
final BlockDeviceData data = HardDriveItem.getData(query.getItemStack());
final long capacity;
if (data != null) {
capacity = data.getBlockDevice().getCapacity();
} else {
capacity = HardDriveItem.getCapacity(query.getItemStack());
}
return Math.max(1, (int) Math.round(capacity * Config.hardDriveEnergyPerMegabytePerTick / Constants.MEGABYTE));
}
}

View File

@@ -4,6 +4,7 @@ import li.cil.oc2.api.bus.device.DeviceType;
import li.cil.oc2.api.bus.device.DeviceTypes;
import li.cil.oc2.api.bus.device.ItemDevice;
import li.cil.oc2.api.bus.device.provider.ItemDeviceQuery;
import li.cil.oc2.common.Config;
import li.cil.oc2.common.bus.device.item.InventoryOperationsModuleDevice;
import li.cil.oc2.common.bus.device.provider.util.AbstractItemDeviceProvider;
import li.cil.oc2.common.capabilities.Capabilities;
@@ -29,4 +30,9 @@ public final class InventoryOperationsModuleDeviceProvider extends AbstractItemD
entity.getCapability(Capabilities.ROBOT).map(robot ->
new InventoryOperationsModuleDevice(query.getItemStack(), entity, robot)));
}
@Override
protected int getItemDeviceEnergyConsumption(final ItemDeviceQuery query) {
return Config.inventoryOperationsModuleEnergyPerTick;
}
}

View File

@@ -4,9 +4,12 @@ import li.cil.oc2.api.bus.device.DeviceType;
import li.cil.oc2.api.bus.device.DeviceTypes;
import li.cil.oc2.api.bus.device.ItemDevice;
import li.cil.oc2.api.bus.device.provider.ItemDeviceQuery;
import li.cil.oc2.common.Config;
import li.cil.oc2.common.Constants;
import li.cil.oc2.common.bus.device.item.MemoryDevice;
import li.cil.oc2.common.bus.device.provider.util.AbstractItemDeviceProvider;
import li.cil.oc2.common.item.Items;
import li.cil.oc2.common.item.MemoryItem;
import java.util.Optional;
@@ -26,4 +29,10 @@ public final class MemoryItemDeviceProvider extends AbstractItemDeviceProvider {
protected Optional<DeviceType> getItemDeviceType(final ItemDeviceQuery query) {
return Optional.of(DeviceTypes.MEMORY);
}
@Override
protected int getItemDeviceEnergyConsumption(final ItemDeviceQuery query) {
final int capacity = MemoryItem.getCapacity(query.getItemStack());
return Math.max(1, (int) Math.round(capacity * Config.memoryEnergyPerMegabytePerTick / Constants.MEGABYTE));
}
}

View File

@@ -2,6 +2,7 @@ package li.cil.oc2.common.bus.device.provider.item;
import li.cil.oc2.api.bus.device.ItemDevice;
import li.cil.oc2.api.bus.device.provider.ItemDeviceQuery;
import li.cil.oc2.common.Config;
import li.cil.oc2.common.bus.device.item.NetworkInterfaceCardItemDevice;
import li.cil.oc2.common.bus.device.provider.util.AbstractItemDeviceProvider;
import li.cil.oc2.common.item.Items;
@@ -20,4 +21,9 @@ public final class NetworkInterfaceCardItemDeviceProvider extends AbstractItemDe
return query.getContainerTileEntity().map(tileEntity ->
new NetworkInterfaceCardItemDevice(query.getItemStack()));
}
@Override
protected int getItemDeviceEnergyConsumption(final ItemDeviceQuery query) {
return Config.networkInterfaceEnergyPerTick;
}
}

View File

@@ -2,6 +2,7 @@ package li.cil.oc2.common.bus.device.provider.item;
import li.cil.oc2.api.bus.device.ItemDevice;
import li.cil.oc2.api.bus.device.provider.ItemDeviceQuery;
import li.cil.oc2.common.Config;
import li.cil.oc2.common.bus.device.item.RedstoneInterfaceCardItemDevice;
import li.cil.oc2.common.bus.device.provider.util.AbstractItemDeviceProvider;
import li.cil.oc2.common.item.Items;
@@ -20,4 +21,9 @@ public final class RedstoneInterfaceCardItemDeviceProvider extends AbstractItemD
return query.getContainerTileEntity().map(tileEntity ->
new RedstoneInterfaceCardItemDevice(query.getItemStack(), tileEntity));
}
@Override
protected int getItemDeviceEnergyConsumption(final ItemDeviceQuery query) {
return Config.redstoneInterfaceCardEnergyPerTick;
}
}

View File

@@ -37,6 +37,11 @@ public abstract class AbstractItemDeviceProvider extends ForgeRegistryEntry<Item
return matches(query) ? getItemDeviceType(query) : Optional.empty();
}
@Override
public final int getEnergyConsumption(final ItemDeviceQuery query) {
return matches(query) ? getItemDeviceEnergyConsumption(query) : 0;
}
///////////////////////////////////////////////////////////////////
protected abstract Optional<ItemDevice> getItemDevice(final ItemDeviceQuery query);
@@ -45,6 +50,10 @@ public abstract class AbstractItemDeviceProvider extends ForgeRegistryEntry<Item
return Optional.of(DeviceTypes.CARD);
}
protected int getItemDeviceEnergyConsumption(final ItemDeviceQuery query) {
return 0;
}
///////////////////////////////////////////////////////////////////
private boolean matches(final ItemDeviceQuery query) {

View File

@@ -19,6 +19,10 @@ public abstract class AbstractDeviceInfo<TProvider extends IForgeRegistryEntry<T
///////////////////////////////////////////////////////////////////
public int getEnergyConsumption() {
return 0;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;

View File

@@ -20,39 +20,32 @@ import net.minecraftforge.registries.IForgeRegistry;
import javax.annotation.Nullable;
import java.util.*;
import static java.util.Objects.requireNonNull;
public final class Devices {
public static List<LazyOptional<BlockDeviceInfo>> getDevices(final TileEntity tileEntity, @Nullable final Direction side) {
final World world = tileEntity.getWorld();
public static BlockDeviceQuery makeQuery(final TileEntity tileEntity, @Nullable final Direction side) {
final World world = requireNonNull(tileEntity.getWorld());
final BlockPos pos = tileEntity.getPos();
if (world == null) throw new IllegalArgumentException();
return getDevices(world, pos, side);
return new BlockQuery(world, pos, side);
}
public static List<LazyOptional<BlockDeviceInfo>> getDevices(final World world, final BlockPos pos, @Nullable final Direction side) {
return getDevices(new BlockQuery(world, pos, side));
public static BlockDeviceQuery makeQuery(final World world, final BlockPos pos, @Nullable final Direction side) {
return new BlockQuery(world, pos, side);
}
public static List<ItemDeviceInfo> getDevices(final ItemStack stack) {
return getDevices(new ItemQuery(stack));
public static ItemDeviceQuery makeQuery(final ItemStack stack) {
return new ItemQuery(stack);
}
public static List<ItemDeviceInfo> getDevices(final TileEntity tileEntity, final ItemStack stack) {
return getDevices(new ItemQuery(tileEntity, stack));
public static ItemDeviceQuery makeQuery(final TileEntity tileEntity, final ItemStack stack) {
return new ItemQuery(tileEntity, stack);
}
public static List<ItemDeviceInfo> getDevices(final Entity entity, final ItemStack stack) {
return getDevices(new ItemQuery(entity, stack));
public static ItemDeviceQuery makeQuery(final Entity entity, final ItemStack stack) {
return new ItemQuery(entity, stack);
}
public static Collection<DeviceType> getDeviceTypes(final ItemStack stack) {
return getDeviceTypes(new ItemQuery(stack));
}
///////////////////////////////////////////////////////////////////
private static List<LazyOptional<BlockDeviceInfo>> getDevices(final BlockQuery query) {
public static List<LazyOptional<BlockDeviceInfo>> getDevices(final BlockDeviceQuery query) {
final IForgeRegistry<BlockDeviceProvider> registry = Providers.BLOCK_DEVICE_PROVIDER_REGISTRY.get();
final ArrayList<LazyOptional<BlockDeviceInfo>> devices = new ArrayList<>();
for (final BlockDeviceProvider provider : registry.getValues()) {
@@ -66,17 +59,17 @@ public final class Devices {
return devices;
}
private static List<ItemDeviceInfo> getDevices(final ItemQuery query) {
public static List<ItemDeviceInfo> getDevices(final ItemDeviceQuery query) {
final IForgeRegistry<ItemDeviceProvider> registry = Providers.ITEM_DEVICE_PROVIDER_REGISTRY.get();
final ArrayList<ItemDeviceInfo> devices = new ArrayList<>();
for (final ItemDeviceProvider provider : registry.getValues()) {
final Optional<ItemDevice> device = provider.getDevice(query);
device.ifPresent(d -> devices.add(new ItemDeviceInfo(provider, d)));
device.ifPresent(d -> devices.add(new ItemDeviceInfo(provider, d, provider.getEnergyConsumption(query))));
}
return devices;
}
private static Collection<DeviceType> getDeviceTypes(final ItemQuery query) {
public static Collection<DeviceType> getDeviceTypes(final ItemDeviceQuery query) {
final IForgeRegistry<ItemDeviceProvider> registry = Providers.ITEM_DEVICE_PROVIDER_REGISTRY.get();
final HashSet<DeviceType> deviceTypes = new HashSet<>();
for (final ItemDeviceProvider provider : registry.getValues()) {
@@ -86,6 +79,19 @@ public final class Devices {
return deviceTypes;
}
public static int getEnergyConsumption(final ItemDeviceQuery query) {
final IForgeRegistry<ItemDeviceProvider> registry = Providers.ITEM_DEVICE_PROVIDER_REGISTRY.get();
long accumulator = 0;
for (final ItemDeviceProvider provider : registry.getValues()) {
accumulator += Math.max(0, provider.getEnergyConsumption(query));
}
if (accumulator > Integer.MAX_VALUE) {
return Integer.MAX_VALUE;
} else {
return (int) accumulator;
}
}
///////////////////////////////////////////////////////////////////
private static class BlockQuery implements BlockDeviceQuery {

View File

@@ -6,7 +6,19 @@ import li.cil.oc2.api.bus.device.provider.ItemDeviceProvider;
import javax.annotation.Nullable;
public class ItemDeviceInfo extends AbstractDeviceInfo<ItemDeviceProvider, ItemDevice> {
public ItemDeviceInfo(@Nullable final ItemDeviceProvider itemDeviceProvider, final ItemDevice device) {
public final int energyConsumption;
///////////////////////////////////////////////////////////////////
public ItemDeviceInfo(@Nullable final ItemDeviceProvider itemDeviceProvider, final ItemDevice device, final int energyConsumption) {
super(itemDeviceProvider, device);
this.energyConsumption = energyConsumption;
}
///////////////////////////////////////////////////////////////////
@Override
public int getEnergyConsumption() {
return energyConsumption;
}
}

View File

@@ -0,0 +1,69 @@
package li.cil.oc2.common.container;
import li.cil.oc2.common.block.Blocks;
import li.cil.oc2.common.tileentity.ComputerTileEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.network.PacketBuffer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.IIntArray;
import net.minecraft.util.IWorldPosCallable;
import net.minecraft.util.IntArray;
import net.minecraft.util.math.BlockPos;
import javax.annotation.Nullable;
public final class ComputerTerminalContainer extends AbstractContainer {
private static final int ENERGY_INFO_SIZE = 3;
///////////////////////////////////////////////////////////////////
@Nullable
public static ComputerTerminalContainer create(final int id, final PlayerInventory playerInventory, final PacketBuffer data) {
final BlockPos pos = data.readBlockPos();
final TileEntity tileEntity = playerInventory.player.getEntityWorld().getTileEntity(pos);
if (!(tileEntity instanceof ComputerTileEntity)) {
return null;
}
return new ComputerTerminalContainer(id, (ComputerTileEntity) tileEntity, new IntArray(3));
}
///////////////////////////////////////////////////////////////////
private final ComputerTileEntity computer;
private final IIntArray energyInfo;
///////////////////////////////////////////////////////////////////
public ComputerTerminalContainer(final int id, final ComputerTileEntity computer, final IIntArray energyInfo) {
super(Containers.COMPUTER_TERMINAL_CONTAINER.get(), id);
this.computer = computer;
this.energyInfo = energyInfo;
assertIntArraySize(energyInfo, ENERGY_INFO_SIZE);
trackIntArray(energyInfo);
}
///////////////////////////////////////////////////////////////////
public ComputerTileEntity getComputer() {
return computer;
}
public int getEnergy() {
return energyInfo.get(0);
}
public int getEnergyCapacity() {
return energyInfo.get(1);
}
public int getEnergyConsumption() {
return energyInfo.get(2);
}
@Override
public boolean canInteractWith(final PlayerEntity player) {
return isWithinUsableDistance(IWorldPosCallable.of(computer.getWorld(), computer.getPos()), player, Blocks.COMPUTER.get());
}
}

View File

@@ -15,6 +15,7 @@ public final class Containers {
///////////////////////////////////////////////////////////////////
public static final RegistryObject<ContainerType<ComputerContainer>> COMPUTER_CONTAINER = CONTAINERS.register(Constants.COMPUTER_BLOCK_NAME, () -> IForgeContainerType.create(ComputerContainer::create));
public static final RegistryObject<ContainerType<ComputerTerminalContainer>> COMPUTER_TERMINAL_CONTAINER = CONTAINERS.register(Constants.COMPUTER_BLOCK_NAME + "_terminal", () -> IForgeContainerType.create(ComputerTerminalContainer::create));
public static final RegistryObject<ContainerType<RobotContainer>> ROBOT_CONTAINER = CONTAINERS.register(Constants.ROBOT_ENTITY_NAME, () -> IForgeContainerType.create(RobotContainer::create));
public static final RegistryObject<ContainerType<RobotTerminalContainer>> ROBOT_TERMINAL_CONTAINER = CONTAINERS.register(Constants.ROBOT_ENTITY_NAME + "_terminal", () -> IForgeContainerType.create(RobotTerminalContainer::create));

View File

@@ -1,13 +1,12 @@
package li.cil.oc2.common.container;
import li.cil.oc2.api.bus.device.provider.ItemDeviceQuery;
import li.cil.oc2.common.bus.ItemHandlerDeviceBusElement;
import li.cil.oc2.common.bus.device.util.ItemDeviceInfo;
import li.cil.oc2.common.util.NBTTagIds;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.NonNullList;
import java.util.List;
import java.util.function.Function;
public class DeviceItemStackHandler extends FixedSizeItemStackHandler {
@@ -19,13 +18,13 @@ public class DeviceItemStackHandler extends FixedSizeItemStackHandler {
///////////////////////////////////////////////////////////////////
public DeviceItemStackHandler(final int size, final Function<ItemStack, List<ItemDeviceInfo>> deviceLookup) {
this(NonNullList.withSize(size, ItemStack.EMPTY), deviceLookup);
public DeviceItemStackHandler(final int size, final Function<ItemStack, ItemDeviceQuery> queryFactory) {
this(NonNullList.withSize(size, ItemStack.EMPTY), queryFactory);
}
public DeviceItemStackHandler(final NonNullList<ItemStack> stacks, final Function<ItemStack, List<ItemDeviceInfo>> deviceLookup) {
public DeviceItemStackHandler(final NonNullList<ItemStack> stacks, final Function<ItemStack, ItemDeviceQuery> queryFactory) {
super(stacks);
this.busElement = new ItemHandlerDeviceBusElement(getSlots(), deviceLookup);
this.busElement = new ItemHandlerDeviceBusElement(getSlots(), queryFactory);
}
///////////////////////////////////////////////////////////////////

View File

@@ -6,12 +6,18 @@ import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.IIntArray;
import net.minecraft.util.IntArray;
import net.minecraftforge.items.ItemStackHandler;
import net.minecraftforge.items.SlotItemHandler;
import javax.annotation.Nullable;
public final class RobotTerminalContainer extends AbstractContainer {
private static final int ENERGY_INFO_SIZE = 3;
///////////////////////////////////////////////////////////////////
@Nullable
public static RobotTerminalContainer create(final int id, final PlayerInventory inventory, final PacketBuffer data) {
final int entityId = data.readVarInt();
@@ -19,18 +25,23 @@ public final class RobotTerminalContainer extends AbstractContainer {
if (!(entity instanceof RobotEntity)) {
return null;
}
return new RobotTerminalContainer(id, (RobotEntity) entity);
return new RobotTerminalContainer(id, (RobotEntity) entity, new IntArray(3));
}
///////////////////////////////////////////////////////////////////
private final RobotEntity robot;
private final IIntArray energyInfo;
///////////////////////////////////////////////////////////////////
public RobotTerminalContainer(final int id, final RobotEntity robot) {
public RobotTerminalContainer(final int id, final RobotEntity robot, final IIntArray energyInfo) {
super(Containers.ROBOT_TERMINAL_CONTAINER.get(), id);
this.robot = robot;
this.energyInfo = energyInfo;
assertIntArraySize(energyInfo, ENERGY_INFO_SIZE);
trackIntArray(energyInfo);
final ItemStackHandler inventory = robot.getInventory();
for (int slot = 0; slot < inventory.getSlots(); slot++) {
@@ -45,6 +56,18 @@ public final class RobotTerminalContainer extends AbstractContainer {
return robot;
}
public int getEnergy() {
return energyInfo.get(0);
}
public int getEnergyCapacity() {
return energyInfo.get(1);
}
public int getEnergyConsumption() {
return energyInfo.get(2);
}
@Override
public boolean canInteractWith(final PlayerEntity player) {
return robot.isEntityInRange(player, 8);

View File

@@ -1,11 +1,10 @@
package li.cil.oc2.common.container;
import li.cil.oc2.api.bus.device.DeviceType;
import li.cil.oc2.api.bus.device.provider.ItemDeviceQuery;
import li.cil.oc2.common.bus.device.util.Devices;
import li.cil.oc2.common.bus.device.util.ItemDeviceInfo;
import net.minecraft.item.ItemStack;
import java.util.List;
import java.util.function.Function;
public class TypedDeviceItemStackHandler extends DeviceItemStackHandler {
@@ -13,8 +12,8 @@ public class TypedDeviceItemStackHandler extends DeviceItemStackHandler {
///////////////////////////////////////////////////////////////////
public TypedDeviceItemStackHandler(final int size, final Function<ItemStack, List<ItemDeviceInfo>> deviceLookup, final DeviceType deviceType) {
super(size, deviceLookup);
public TypedDeviceItemStackHandler(final int size, final Function<ItemStack, ItemDeviceQuery> queryFactory, final DeviceType deviceType) {
super(size, queryFactory);
this.deviceType = deviceType;
}
@@ -22,6 +21,6 @@ public class TypedDeviceItemStackHandler extends DeviceItemStackHandler {
@Override
public boolean isItemValid(final int slot, final ItemStack stack) {
return super.isItemValid(slot, stack) && Devices.getDeviceTypes(stack).contains(deviceType);
return super.isItemValid(slot, stack) && Devices.getDeviceTypes(Devices.makeQuery(stack)).contains(deviceType);
}
}

View File

@@ -3,7 +3,6 @@ package li.cil.oc2.common.container;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.tags.ITag;
import org.jetbrains.annotations.NotNull;
public class TypedItemStackHandler extends FixedSizeItemStackHandler {
private final ITag<Item> deviceType;
@@ -18,7 +17,7 @@ public class TypedItemStackHandler extends FixedSizeItemStackHandler {
///////////////////////////////////////////////////////////////////
@Override
public boolean isItemValid(final int slot, @NotNull final ItemStack stack) {
public boolean isItemValid(final int slot, final ItemStack stack) {
return super.isItemValid(slot, stack) && !stack.isEmpty() && deviceType.contains(stack.getItem());
}
}

View File

@@ -8,8 +8,8 @@ import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.energy.IEnergyStorage;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.annotation.Nullable;
public final class EnergyStorageItemStack implements IEnergyStorage, ICapabilityProvider {
private final LazyOptional<IEnergyStorage> optional = LazyOptional.of(() -> this);
@@ -61,9 +61,12 @@ public final class EnergyStorageItemStack implements IEnergyStorage, ICapability
return true;
}
@NotNull
@Override
public <T> LazyOptional<T> getCapability(@NotNull final Capability<T> capability, @Nullable final Direction side) {
return Capabilities.ENERGY_STORAGE.orEmpty(capability, optional);
public <T> LazyOptional<T> getCapability(final Capability<T> capability, @Nullable final Direction side) {
if (Capabilities.ENERGY_STORAGE != null && capability != null) {
return Capabilities.ENERGY_STORAGE.orEmpty(capability, optional);
} else {
return LazyOptional.empty();
}
}
}

View File

@@ -6,13 +6,13 @@ import li.cil.oc2.api.bus.device.DeviceTypes;
import li.cil.oc2.api.bus.device.object.Callback;
import li.cil.oc2.api.bus.device.object.ObjectDevice;
import li.cil.oc2.api.bus.device.object.Parameter;
import li.cil.oc2.api.bus.device.provider.ItemDeviceQuery;
import li.cil.oc2.api.capabilities.Robot;
import li.cil.oc2.common.Config;
import li.cil.oc2.common.Constants;
import li.cil.oc2.common.bus.AbstractDeviceBusElement;
import li.cil.oc2.common.bus.CommonDeviceBusController;
import li.cil.oc2.common.bus.device.util.Devices;
import li.cil.oc2.common.bus.device.util.ItemDeviceInfo;
import li.cil.oc2.common.capabilities.Capabilities;
import li.cil.oc2.common.container.FixedSizeItemStackHandler;
import li.cil.oc2.common.container.RobotContainer;
@@ -50,16 +50,13 @@ import net.minecraft.network.datasync.DataParameter;
import net.minecraft.network.datasync.DataSerializers;
import net.minecraft.network.datasync.EntityDataManager;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.*;
import net.minecraft.util.math.*;
import net.minecraft.util.math.shapes.IBooleanFunction;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.util.math.shapes.VoxelShapes;
import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraft.world.World;
import net.minecraft.world.server.ServerWorld;
import net.minecraftforge.api.distmarker.Dist;
@@ -72,7 +69,6 @@ import net.minecraftforge.event.world.ChunkEvent;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.fml.network.NetworkHooks;
import net.minecraftforge.items.ItemStackHandler;
import org.jetbrains.annotations.NotNull;
import javax.annotation.Nullable;
import java.nio.ByteBuffer;
@@ -125,7 +121,7 @@ public final class RobotEntity extends Entity implements Robot {
this.preventEntitySpawning = true;
setNoGravity(true);
final CommonDeviceBusController busController = new CommonDeviceBusController(busElement);
final CommonDeviceBusController busController = new CommonDeviceBusController(busElement, Config.robotEnergyPerTick);
virtualMachine = new RobotVirtualMachine(busController);
virtualMachine.state.builtinDevices.rtcMinecraft.setWorld(world);
@@ -166,9 +162,8 @@ public final class RobotEntity extends Entity implements Robot {
getDataManager().set(SELECTED_SLOT, (byte) MathHelper.clamp(value, 0, INVENTORY_SIZE - 1));
}
@NotNull
@Override
public <T> LazyOptional<T> getCapability(@NotNull final Capability<T> capability, @org.jetbrains.annotations.Nullable final Direction side) {
public <T> LazyOptional<T> getCapability(final Capability<T> capability, @Nullable final Direction side) {
if (capability == Capabilities.ITEM_HANDLER) {
return LazyOptional.of(() -> inventory).cast();
}
@@ -471,7 +466,30 @@ public final class RobotEntity extends Entity implements Robot {
@Override
public Container createMenu(final int id, final PlayerInventory inventory, final PlayerEntity player) {
return new RobotTerminalContainer(id, RobotEntity.this);
return new RobotTerminalContainer(id, RobotEntity.this, new IIntArray() {
@Override
public int get(final int index) {
switch (index) {
case 0:
return energy.getEnergyStored();
case 1:
return energy.getMaxEnergyStored();
case 2:
return virtualMachine.busController.getEnergyConsumption();
default:
return 0;
}
}
@Override
public void set(final int index, final int value) {
}
@Override
public int size() {
return 3;
}
});
}
}, b -> b.writeVarInt(getEntityId()));
}
@@ -733,8 +751,8 @@ public final class RobotEntity extends Entity implements Robot {
}
@Override
protected List<ItemDeviceInfo> getDevices(final ItemStack stack) {
return Devices.getDevices(RobotEntity.this, stack);
protected ItemDeviceQuery getDeviceQuery(final ItemStack stack) {
return Devices.makeQuery(RobotEntity.this, stack);
}
}
@@ -793,30 +811,17 @@ public final class RobotEntity extends Entity implements Robot {
}
@Override
protected void load() {
if (Config.robotsUseEnergy()) {
// Don't even start running if we couldn't keep running.
if (energy.getEnergyStored() < Config.robotEnergyPerTick) {
error(new TranslationTextComponent(Constants.COMPUTER_ERROR_NOT_ENOUGH_ENERGY));
return;
}
protected boolean consumeEnergy(final int amount, final boolean simulate) {
if (!Config.robotsUseEnergy()) {
return true;
}
super.load();
}
@Override
protected void run() {
if (Config.robotsUseEnergy()) {
if (energy.getEnergyStored() >= Config.robotEnergyPerTick) {
energy.extractEnergy(Config.robotEnergyPerTick, false);
} else {
error(new TranslationTextComponent(Constants.COMPUTER_ERROR_NOT_ENOUGH_ENERGY));
return;
}
if (amount > energy.getEnergyStored()) {
return false;
}
super.run();
energy.extractEnergy(amount, simulate);
return true;
}
@Override

View File

@@ -1,12 +1,15 @@
package li.cil.oc2.common.item;
import li.cil.oc2.common.Config;
import li.cil.oc2.common.block.Blocks;
import li.cil.oc2.common.block.BusCableBlock;
import li.cil.oc2.common.util.TooltipUtils;
import li.cil.oc2.common.util.WorldUtils;
import net.minecraft.advancements.CriteriaTriggers;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.SoundType;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.item.BlockItemUseContext;
@@ -14,7 +17,13 @@ import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUseContext;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import javax.annotation.Nullable;
import java.util.List;
public final class BusCableItem extends ModBlockItem {
public BusCableItem(final Block block) {
@@ -23,6 +32,13 @@ public final class BusCableItem extends ModBlockItem {
///////////////////////////////////////////////////////////////////
@OnlyIn(Dist.CLIENT)
@Override
public void addInformation(final ItemStack stack, final @Nullable World world, final List<ITextComponent> tooltip, final ITooltipFlag flag) {
super.addInformation(stack, world, tooltip, flag);
TooltipUtils.addEnergyConsumption(Config.busCableEnergyPerTick, tooltip);
}
@Override
public ActionResultType onItemUse(final ItemUseContext context) {
final ActionResultType result = tryAddToBlock(context);

View File

@@ -1,25 +1,34 @@
package li.cil.oc2.common.item;
import li.cil.oc2.common.Config;
import li.cil.oc2.common.block.Blocks;
import li.cil.oc2.common.block.BusCableBlock;
import li.cil.oc2.common.block.BusCableBlock.ConnectionType;
import li.cil.oc2.common.util.TooltipUtils;
import li.cil.oc2.common.util.WorldUtils;
import net.minecraft.advancements.CriteriaTriggers;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.SoundType;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUseContext;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.*;
import net.minecraft.state.EnumProperty;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction;
import net.minecraft.util.NonNullList;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Map;
public final class BusInterfaceItem extends ModBlockItem {
public BusInterfaceItem(final Block block) {
@@ -28,6 +37,13 @@ public final class BusInterfaceItem extends ModBlockItem {
///////////////////////////////////////////////////////////////////
@OnlyIn(Dist.CLIENT)
@Override
public void addInformation(final ItemStack stack, final @Nullable World world, final List<ITextComponent> tooltip, final ITooltipFlag flag) {
super.addInformation(stack, world, tooltip, flag);
TooltipUtils.addEnergyConsumption(Config.busInterfaceEnergyPerTick, tooltip);
}
@Override
public ActionResultType onItemUse(final ItemUseContext context) {
final Vector3d localHitPos = context.getHitVec().subtract(Vector3d.copyCentered(context.getPos()));
@@ -42,6 +58,26 @@ public final class BusInterfaceItem extends ModBlockItem {
return result.isSuccessOrConsume() ? result : super.tryPlace(context);
}
@Override
public String getTranslationKey() {
return getDefaultTranslationKey();
}
@Override
public void fillItemGroup(final ItemGroup group, final NonNullList<ItemStack> items) {
if (isInGroup(group)) {
items.add(new ItemStack(this));
}
}
@Override
public void addToBlockToItemMap(final Map<Block, Item> map, final Item item) {
}
@Override
public void removeFromBlockToItemMap(final Map<Block, Item> map, final Item item) {
}
///////////////////////////////////////////////////////////////////
@Nullable

View File

@@ -26,6 +26,7 @@ public final class Items {
public static final RegistryObject<Item> REDSTONE_INTERFACE = register(Constants.REDSTONE_INTERFACE_BLOCK_NAME, Blocks.REDSTONE_INTERFACE);
public static final RegistryObject<Item> DISK_DRIVE = register(Constants.DISK_DRIVE_BLOCK_NAME, Blocks.DISK_DRIVE);
public static final RegistryObject<Item> CHARGER = register(Constants.CHARGER_BLOCK_NAME, Blocks.CHARGER, ChargerItem::new);
public static final RegistryObject<Item> CREATIVE_ENERGY = register(Constants.CREATIVE_ENERGY_BLOCK_NAME, Blocks.CREATIVE_ENERGY);
///////////////////////////////////////////////////////////////////

View File

@@ -7,8 +7,10 @@ import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemStack;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import javax.annotation.Nullable;
import java.util.List;
public class ModBlockItem extends BlockItem {
@@ -22,10 +24,11 @@ public class ModBlockItem extends BlockItem {
///////////////////////////////////////////////////////////////////
@OnlyIn(Dist.CLIENT)
@Override
public void addInformation(final ItemStack stack, @Nullable final World world, final List<ITextComponent> tooltip, final ITooltipFlag flag) {
TooltipUtils.tryAddDescription(stack, tooltip);
this.getBlock().addInformation(stack, world, tooltip, flag);
super.addInformation(stack, world, tooltip, flag);
}
///////////////////////////////////////////////////////////////////

View File

@@ -6,8 +6,10 @@ import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import javax.annotation.Nullable;
import java.util.List;
public class ModItem extends Item {
@@ -21,6 +23,7 @@ public class ModItem extends Item {
///////////////////////////////////////////////////////////////////
@OnlyIn(Dist.CLIENT)
@Override
public void addInformation(final ItemStack stack, @Nullable final World world, final List<ITextComponent> tooltip, final ITooltipFlag flag) {
super.addInformation(stack, world, tooltip, flag);

View File

@@ -22,8 +22,8 @@ import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.World;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import org.jetbrains.annotations.Nullable;
import javax.annotation.Nullable;
import java.util.List;
import static li.cil.oc2.common.Constants.ENERGY_TAG_NAME;
@@ -39,8 +39,9 @@ public final class RobotItem extends ModItem {
@Override
public void addInformation(final ItemStack stack, @Nullable final World world, final List<ITextComponent> tooltip, final ITooltipFlag flag) {
super.addInformation(stack, world, tooltip, flag);
TooltipUtils.addEnergyConsumption(Config.robotEnergyPerTick, tooltip);
TooltipUtils.addEntityEnergyInformation(stack, tooltip);
TooltipUtils.addEntityInventoryInformation(stack, tooltip);
TooltipUtils.addEntityEnergyInformation(stack, tooltip, Config.robotEnergyStorage);
}
@Nullable

View File

@@ -5,7 +5,8 @@ import li.cil.ceres.api.SerializationException;
import li.cil.ceres.api.SerializationVisitor;
import li.cil.ceres.api.Serializer;
import li.cil.sedna.api.memory.MemoryRange;
import org.jetbrains.annotations.Nullable;
import javax.annotation.Nullable;
public final class MemoryRangeSerializer implements Serializer<MemoryRange> {
@Override

View File

@@ -1,6 +1,7 @@
package li.cil.oc2.common.tileentity;
import li.cil.oc2.client.model.BusCableBakedModel;
import li.cil.oc2.common.Config;
import li.cil.oc2.common.block.BusCableBlock;
import li.cil.oc2.common.bus.TileEntityDeviceBusElement;
import li.cil.oc2.common.capabilities.Capabilities;
@@ -118,5 +119,12 @@ public final class BusCableTileEntity extends AbstractTileEntity {
final BusCableBlock.ConnectionType connectionType = BusCableBlock.getConnectionType(getBlockState(), direction);
return connectionType == BusCableBlock.ConnectionType.INTERFACE;
}
@Override
public double getEnergyConsumption() {
return super.getEnergyConsumption()
+ Config.busCableEnergyPerTick
+ BusCableBlock.getInterfaceCount(getBlockState()) * Config.busInterfaceEnergyPerTick;
}
}
}

View File

@@ -16,9 +16,10 @@ import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.energy.IEnergyStorage;
import net.minecraftforge.items.IItemHandler;
import javax.annotation.Nullable;
import java.util.List;
public final class ChargerTileEntity extends TileEntity implements ITickableTileEntity {
public final class ChargerTileEntity extends AbstractTileEntity implements ITickableTileEntity {
private final FixedEnergyStorage energy = new FixedEnergyStorage(Config.chargerEnergyStorage);
///////////////////////////////////////////////////////////////////
@@ -53,6 +54,13 @@ public final class ChargerTileEntity extends TileEntity implements ITickableTile
///////////////////////////////////////////////////////////////////
@Override
protected void collectCapabilities(final CapabilityCollector collector, @Nullable final Direction direction) {
collector.offer(Capabilities.ENERGY_STORAGE, energy);
}
///////////////////////////////////////////////////////////////////
private void chargeBlock() {
if (energy.getEnergyStored() == 0) {
return;

View File

@@ -3,6 +3,8 @@ package li.cil.oc2.common.tileentity;
import li.cil.oc2.api.bus.DeviceBusElement;
import li.cil.oc2.api.bus.device.Device;
import li.cil.oc2.api.bus.device.DeviceTypes;
import li.cil.oc2.api.bus.device.provider.BlockDeviceQuery;
import li.cil.oc2.api.bus.device.provider.ItemDeviceQuery;
import li.cil.oc2.client.audio.LoopingSoundManager;
import li.cil.oc2.common.Config;
import li.cil.oc2.common.Constants;
@@ -12,8 +14,9 @@ import li.cil.oc2.common.bus.TileEntityDeviceBusController;
import li.cil.oc2.common.bus.TileEntityDeviceBusElement;
import li.cil.oc2.common.bus.device.util.BlockDeviceInfo;
import li.cil.oc2.common.bus.device.util.Devices;
import li.cil.oc2.common.bus.device.util.ItemDeviceInfo;
import li.cil.oc2.common.capabilities.Capabilities;
import li.cil.oc2.common.container.ComputerContainer;
import li.cil.oc2.common.container.ComputerTerminalContainer;
import li.cil.oc2.common.container.DeviceItemStackHandler;
import li.cil.oc2.common.energy.FixedEnergyStorage;
import li.cil.oc2.common.network.Network;
@@ -25,10 +28,16 @@ import li.cil.oc2.common.serialization.NBTSerialization;
import li.cil.oc2.common.util.*;
import li.cil.oc2.common.vm.*;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.inventory.container.Container;
import net.minecraft.inventory.container.INamedContainerProvider;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.ITickableTileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.IIntArray;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraft.world.World;
@@ -36,12 +45,12 @@ import net.minecraft.world.chunk.Chunk;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fml.network.NetworkHooks;
import javax.annotation.Nullable;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import static li.cil.oc2.common.Constants.BLOCK_ENTITY_TAG_NAME_IN_ITEM;
@@ -70,7 +79,7 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic
private final TileEntityDeviceBusElement busElement = new ComputerBusElement();
private final ComputerItemStackHandlers deviceItems = new ComputerItemStackHandlers();
private final FixedEnergyStorage energy = new FixedEnergyStorage(Config.computerEnergyStorage);
private final ComputerVirtualMachine virtualMachine = new ComputerVirtualMachine(new TileEntityDeviceBusController(busElement, this), deviceItems::getDeviceAddressBase);
private final ComputerVirtualMachine virtualMachine = new ComputerVirtualMachine(new TileEntityDeviceBusController(busElement, Config.computerEnergyPerTick, this), deviceItems::getDeviceAddressBase);
///////////////////////////////////////////////////////////////////
@@ -111,6 +120,57 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic
virtualMachine.stop();
}
public void openTerminalScreen(final ServerPlayerEntity player) {
NetworkHooks.openGui(player, new INamedContainerProvider() {
@Override
public ITextComponent getDisplayName() {
return new TranslationTextComponent(getBlockState().getBlock().getTranslationKey());
}
@Override
public Container createMenu(final int id, final PlayerInventory inventory, final PlayerEntity player) {
return new ComputerTerminalContainer(id, ComputerTileEntity.this, new IIntArray() {
@Override
public int get(final int index) {
switch (index) {
case 0:
return energy.getEnergyStored();
case 1:
return energy.getMaxEnergyStored();
case 2:
return virtualMachine.busController.getEnergyConsumption();
default:
return 0;
}
}
@Override
public void set(final int index, final int value) {
}
@Override
public int size() {
return 3;
}
});
}
}, getPos());
}
public void openContainerScreen(final ServerPlayerEntity player) {
NetworkHooks.openGui(player, new INamedContainerProvider() {
@Override
public ITextComponent getDisplayName() {
return new TranslationTextComponent(getBlockState().getBlock().getTranslationKey());
}
@Override
public Container createMenu(final int id, final PlayerInventory inventory, final PlayerEntity player) {
return new ComputerContainer(id, ComputerTileEntity.this, inventory);
}
}, getPos());
}
public void handleNeighborChanged() {
virtualMachine.busController.scheduleBusScan();
}
@@ -150,7 +210,8 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic
// adjacent cable. Because that would just be weird.
if (!hasAddedOwnDevices) {
hasAddedOwnDevices = true;
for (final LazyOptional<BlockDeviceInfo> optional : Devices.getDevices(this, (Direction) null)) {
final BlockDeviceQuery query = Devices.makeQuery(this, (Direction) null);
for (final LazyOptional<BlockDeviceInfo> optional : Devices.getDevices(query)) {
optional.ifPresent(info -> busElement.addDevice(info.device));
}
}
@@ -279,8 +340,8 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic
}
@Override
protected List<ItemDeviceInfo> getDevices(final ItemStack stack) {
return Devices.getDevices(ComputerTileEntity.this, stack);
protected ItemDeviceQuery getDeviceQuery(final ItemStack stack) {
return Devices.makeQuery(ComputerTileEntity.this, stack);
}
@Override
@@ -357,30 +418,17 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic
}
@Override
protected void load() {
if (Config.computersUseEnergy()) {
// Don't even start running if we couldn't keep running.
if (energy.getEnergyStored() < Config.computerEnergyPerTick) {
error(new TranslationTextComponent(Constants.COMPUTER_ERROR_NOT_ENOUGH_ENERGY));
return;
}
protected boolean consumeEnergy(final int amount, final boolean simulate) {
if (!Config.computersUseEnergy()) {
return true;
}
super.load();
}
@Override
protected void run() {
if (Config.computersUseEnergy()) {
if (energy.getEnergyStored() >= Config.computerEnergyPerTick) {
energy.extractEnergy(Config.computerEnergyPerTick, false);
} else {
error(new TranslationTextComponent(Constants.COMPUTER_ERROR_NOT_ENOUGH_ENERGY));
return;
}
if (amount > energy.getEnergyStored()) {
return false;
}
super.run();
energy.extractEnergy(amount, simulate);
return true;
}
@Override

View File

@@ -0,0 +1,36 @@
package li.cil.oc2.common.tileentity;
import li.cil.oc2.common.capabilities.Capabilities;
import net.minecraft.tileentity.ITickableTileEntity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
public final class CreativeEnergyTileEntity extends TileEntity implements ITickableTileEntity {
private final Direction[] SIDES = Direction.values();
///////////////////////////////////////////////////////////////////
public CreativeEnergyTileEntity() {
super(TileEntities.CREATIVE_ENERGY_TILE_ENTITY.get());
}
///////////////////////////////////////////////////////////////////
@Override
public void tick() {
for (final Direction side : SIDES) {
final BlockPos neighborPos = getPos().offset(side);
final ChunkPos neighborChunkPos = new ChunkPos(neighborPos);
if (getWorld().chunkExists(neighborChunkPos.x, neighborChunkPos.z)) {
final TileEntity tileEntity = getWorld().getTileEntity(neighborPos);
if (tileEntity != null) {
tileEntity.getCapability(Capabilities.ENERGY_STORAGE, side.getOpposite()).ifPresent(energy -> {
energy.receiveEnergy(Integer.MAX_VALUE, false);
});
}
}
}
}
}

View File

@@ -1,9 +1,9 @@
package li.cil.oc2.common.tileentity;
import li.cil.oc2.api.bus.device.data.BlockDeviceData;
import li.cil.oc2.api.bus.device.vm.VMContext;
import li.cil.oc2.api.bus.device.vm.VMDevice;
import li.cil.oc2.api.bus.device.vm.VMDeviceLoadResult;
import li.cil.oc2.api.bus.device.vm.context.VMContext;
import li.cil.oc2.common.Config;
import li.cil.oc2.common.Constants;
import li.cil.oc2.common.block.DiskDriveBlock;
@@ -30,8 +30,8 @@ import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.Nullable;
import javax.annotation.Nullable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

View File

@@ -25,6 +25,7 @@ public final class TileEntities {
public static final RegistryObject<TileEntityType<NetworkHubTileEntity>> NETWORK_HUB_TILE_ENTITY = register(Constants.NETWORK_HUB_BLOCK_NAME, Blocks.NETWORK_HUB, NetworkHubTileEntity::new);
public static final RegistryObject<TileEntityType<DiskDriveTileEntity>> DISK_DRIVE_TILE_ENTITY = register(Constants.DISK_DRIVE_BLOCK_NAME, Blocks.DISK_DRIVE, DiskDriveTileEntity::new);
public static final RegistryObject<TileEntityType<ChargerTileEntity>> CHARGER_TILE_ENTITY = register(Constants.CHARGER_BLOCK_NAME, Blocks.CHARGER, ChargerTileEntity::new);
public static final RegistryObject<TileEntityType<CreativeEnergyTileEntity>> CREATIVE_ENERGY_TILE_ENTITY = register(Constants.CREATIVE_ENERGY_BLOCK_NAME, Blocks.CREATIVE_ENERGY, CreativeEnergyTileEntity::new);
///////////////////////////////////////////////////////////////////

View File

@@ -14,7 +14,8 @@ import net.minecraft.network.play.ServerPlayNetHandler;
import net.minecraft.world.server.ServerWorld;
import net.minecraftforge.common.util.FakePlayer;
import net.minecraftforge.common.util.FakePlayerFactory;
import org.jetbrains.annotations.Nullable;
import javax.annotation.Nullable;
public final class FakePlayerUtils {
private static final String FAKE_PLAYER_NAME = "[" + API.MOD_ID + "]";

View File

@@ -3,8 +3,10 @@ package li.cil.oc2.common.util;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
import li.cil.oc2.api.bus.device.DeviceType;
import li.cil.oc2.api.bus.device.provider.ItemDeviceQuery;
import li.cil.oc2.common.Constants;
import li.cil.oc2.common.energy.FixedEnergyStorage;
import li.cil.oc2.common.bus.device.util.Devices;
import li.cil.oc2.common.capabilities.Capabilities;
import li.cil.oc2.common.tags.ItemTags;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
@@ -15,12 +17,17 @@ import net.minecraft.util.text.*;
import net.minecraftforge.registries.ForgeRegistry;
import net.minecraftforge.registries.RegistryManager;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import static li.cil.oc2.common.Constants.*;
public final class TooltipUtils {
private static final IFormattableTextComponent DEVICE_NEEDS_REBOOT =
new TranslationTextComponent(Constants.TOOLTIP_DEVICE_NEEDS_REBOOT)
.modifyStyle(s -> s.setColor(Color.fromTextFormatting(TextFormatting.YELLOW)));
private static final ThreadLocal<List<ItemStack>> ITEM_STACKS = ThreadLocal.withInitial(ArrayList::new);
private static final ThreadLocal<IntList> ITEM_STACKS_SIZES = ThreadLocal.withInitial(IntArrayList::new);
@@ -35,7 +42,7 @@ public final class TooltipUtils {
final LanguageMap languagemap = LanguageMap.getInstance();
if (languagemap.func_230506_b_(translationKey)) {
final TranslationTextComponent description = new TranslationTextComponent(translationKey);
tooltip.add(new StringTextComponent("").modifyStyle(s -> s.setColor(Color.fromTextFormatting(TextFormatting.GRAY))).append(description));
tooltip.add(withColor(description, TextFormatting.GRAY));
}
// Tooltips get queried very early in Minecraft initialization, meaning tags may not
@@ -43,8 +50,14 @@ public final class TooltipUtils {
// in that case, so we do the detour through the collection instead.
final ITag<Item> tag = net.minecraft.tags.ItemTags.getCollection().get(ItemTags.DEVICE_NEEDS_REBOOT.getName());
if (tag != null && tag.contains(stack.getItem())) {
tooltip.add(new StringTextComponent("").modifyStyle(s -> s.setColor(Color.fromTextFormatting(TextFormatting.YELLOW)))
.append(new TranslationTextComponent(Constants.TOOLTIP_DEVICE_NEEDS_REBOOT)));
tooltip.add(DEVICE_NEEDS_REBOOT);
}
final ItemDeviceQuery query = Devices.makeQuery(stack);
final int energyConsumption = Devices.getEnergyConsumption(query);
if (energyConsumption > 0) {
final IFormattableTextComponent energy = withColor(String.valueOf(energyConsumption), TextFormatting.GREEN);
tooltip.add(withColor(new TranslationTextComponent(Constants.TOOLTIP_ENERGY_CONSUMPTION, energy), TextFormatting.GRAY));
}
}
@@ -86,28 +99,29 @@ public final class TooltipUtils {
}
}
public static void addEntityEnergyInformation(final ItemStack stack, final List<ITextComponent> tooltip, final int defaultCapacity) {
addEnergyInformation(NBTUtils.getChildTag(stack.getTag(), MOD_TAG_NAME, ENERGY_TAG_NAME), tooltip, defaultCapacity);
public static void addEntityEnergyInformation(final ItemStack stack, final List<ITextComponent> tooltip) {
stack.getCapability(Capabilities.ENERGY_STORAGE).ifPresent(energy -> {
if (energy.getEnergyStored() == 0) {
return;
}
final IFormattableTextComponent value = withColor(energy.getEnergyStored() + "/" + energy.getMaxEnergyStored(), TextFormatting.GREEN);
tooltip.add(withColor(new TranslationTextComponent(Constants.TOOLTIP_ENERGY, value), TextFormatting.GRAY));
});
}
public static void addEnergyInformation(final CompoundNBT energyTag, final List<ITextComponent> tooltip, final int defaultCapacity) {
final int stored = energyTag.getInt(FixedEnergyStorage.STORED_TAG_NAME);
if (stored == 0) {
return;
public static void addEnergyConsumption(final double value, final List<ITextComponent> tooltip) {
if (value > 0) {
tooltip.add(withColor(new TranslationTextComponent(Constants.TOOLTIP_ENERGY_CONSUMPTION, withColor(new DecimalFormat("#.##").format(value), TextFormatting.GREEN)), TextFormatting.GRAY));
}
}
final int capacity;
if (energyTag.contains(FixedEnergyStorage.CAPACITY_TAG_NAME, NBTTagIds.TAG_INT)) {
capacity = energyTag.getInt(FixedEnergyStorage.CAPACITY_TAG_NAME);
} else {
capacity = defaultCapacity;
}
public static IFormattableTextComponent withColor(final String value, final TextFormatting formatting) {
return withColor(new StringTextComponent(value), formatting);
}
if (capacity > 0) {
tooltip.add(new TranslationTextComponent(Constants.TOOLTIP_ENERGY, stored + "/" + capacity));
} else {
tooltip.add(new TranslationTextComponent(Constants.TOOLTIP_ENERGY, stored));
}
public static IFormattableTextComponent withColor(final IFormattableTextComponent text, final TextFormatting formatting) {
return text.modifyStyle(s -> s.setColor(Color.fromTextFormatting(formatting)));
}
///////////////////////////////////////////////////////////////////

View File

@@ -3,6 +3,7 @@ package li.cil.oc2.common.vm;
import li.cil.oc2.api.bus.DeviceBusElement;
import li.cil.oc2.api.bus.device.DeviceType;
import li.cil.oc2.api.bus.device.DeviceTypes;
import li.cil.oc2.api.bus.device.provider.ItemDeviceQuery;
import li.cil.oc2.api.bus.device.vm.VMDevice;
import li.cil.oc2.common.bus.AbstractDeviceBusElement;
import li.cil.oc2.common.bus.device.util.ItemDeviceInfo;
@@ -42,7 +43,7 @@ public abstract class AbstractVMItemStackHandlers implements VMItemStackHandlers
///////////////////////////////////////////////////////////////////
public final DeviceBusElement busElement = new BusElement();
public final AbstractDeviceBusElement busElement = new BusElement();
// NB: linked hash map such that order of parameters in constructor is retained.
// This is relevant when assigning default addresses for devices.
@@ -54,7 +55,7 @@ public abstract class AbstractVMItemStackHandlers implements VMItemStackHandlers
public AbstractVMItemStackHandlers(final GroupDefinition... groups) {
for (final GroupDefinition group : groups) {
itemHandlers.put(group.deviceType, new ItemHandler(group.count, this::getDevices, group.deviceType));
itemHandlers.put(group.deviceType, new ItemHandler(group.count, this::getDeviceQuery, group.deviceType));
}
combinedItemHandlers = new CombinedInvWrapper(itemHandlers.values().toArray(new IItemHandlerModifiable[0]));
@@ -131,7 +132,7 @@ public abstract class AbstractVMItemStackHandlers implements VMItemStackHandlers
///////////////////////////////////////////////////////////////////
protected abstract List<ItemDeviceInfo> getDevices(final ItemStack stack);
protected abstract ItemDeviceQuery getDeviceQuery(final ItemStack stack);
protected void onContentsChanged(final DeviceItemStackHandler itemHandler, final int slot) {
}
@@ -139,8 +140,8 @@ public abstract class AbstractVMItemStackHandlers implements VMItemStackHandlers
///////////////////////////////////////////////////////////////////
private final class ItemHandler extends TypedDeviceItemStackHandler {
public ItemHandler(final int size, final Function<ItemStack, List<ItemDeviceInfo>> deviceLookup, final DeviceType deviceType) {
super(size, deviceLookup, deviceType);
public ItemHandler(final int size, final Function<ItemStack, ItemDeviceQuery> queryFactory, final DeviceType deviceType) {
super(size, queryFactory, deviceType);
}
@Override

View File

@@ -265,6 +265,8 @@ public abstract class AbstractVirtualMachine implements VirtualMachine {
protected abstract AbstractTerminalVMRunner createRunner();
protected abstract boolean consumeEnergy(final int amount, final boolean simulate);
protected void handleBusStateChanged(final CommonDeviceBusController.BusState value) {
}
@@ -274,12 +276,31 @@ public abstract class AbstractVirtualMachine implements VirtualMachine {
protected void handleBootErrorChanged(@Nullable final ITextComponent value) {
}
protected void load() {
protected void error(@Nullable final ITextComponent message) {
error(message, true);
}
protected void error(@Nullable final ITextComponent message, final boolean reset) {
if (reset) {
stopRunnerAndReset();
}
setBootError(message);
}
///////////////////////////////////////////////////////////////////
private void load() {
if (loadDevicesDelay > 0) {
loadDevicesDelay--;
return;
}
if (!consumeEnergy(busController.getEnergyConsumption(), true)) {
// Don't even start running if we couldn't keep running.
error(new TranslationTextComponent(Constants.COMPUTER_ERROR_NOT_ENOUGH_ENERGY));
return;
}
final VMDeviceLoadResult loadResult = state.vmAdapter.load();
if (!loadResult.wasSuccessful()) {
if (loadResult.getErrorMessage() != null) {
@@ -325,7 +346,7 @@ public abstract class AbstractVirtualMachine implements VirtualMachine {
// initialization. This is used by devices to restore data from disk, for example.
}
protected void run() {
private void run() {
final ITextComponent runtimeError = runner.getRuntimeError();
if (runtimeError != null) {
error(runtimeError);
@@ -337,22 +358,14 @@ public abstract class AbstractVirtualMachine implements VirtualMachine {
return;
}
if (!consumeEnergy(busController.getEnergyConsumption(), false)) {
error(new TranslationTextComponent(Constants.COMPUTER_ERROR_NOT_ENOUGH_ENERGY));
return;
}
runner.tick();
}
protected void error(@Nullable final ITextComponent message) {
error(message, true);
}
protected void error(@Nullable final ITextComponent message, final boolean reset) {
if (reset) {
stopRunnerAndReset();
}
setBootError(message);
}
///////////////////////////////////////////////////////////////////
private void setBusState(final CommonDeviceBusController.BusState value) {
if (value == busState) {
return;

View File

@@ -3,6 +3,7 @@ package li.cil.oc2.data;
import li.cil.oc2.api.API;
import li.cil.oc2.common.block.Blocks;
import li.cil.oc2.common.block.BusCableBlock;
import li.cil.oc2.common.block.CreativeEnergyBlock;
import li.cil.oc2.common.item.Items;
import net.minecraft.block.Block;
import net.minecraft.data.DataGenerator;
@@ -37,6 +38,7 @@ public class ModBlockStateProvider extends BlockStateProvider {
horizontalBlock(Blocks.NETWORK_HUB, Items.NETWORK_HUB);
horizontalBlock(Blocks.DISK_DRIVE, Items.DISK_DRIVE);
horizontalBlock(Blocks.CHARGER, Items.CHARGER);
simpleBlock(Blocks.CREATIVE_ENERGY, Items.CREATIVE_ENERGY);
registerCableStates();
}
@@ -157,4 +159,9 @@ public class ModBlockStateProvider extends BlockStateProvider {
horizontalFaceBlock(block.get(), models().getBuilder(block.getId().getPath()));
return itemModels().getBuilder(item.getId().getPath()).parent(models().getExistingFile(block.getId()));
}
private void simpleBlock(final RegistryObject<CreativeEnergyBlock> block, final RegistryObject<Item> item) {
simpleBlock(block.get());
itemModels().getBuilder(item.getId().getPath()).parent(models().getExistingFile(block.getId()));
}
}

View File

@@ -4,7 +4,8 @@ import li.cil.oc2.api.API;
import net.minecraft.data.BlockTagsProvider;
import net.minecraft.data.DataGenerator;
import net.minecraftforge.common.data.ExistingFileHelper;
import org.jetbrains.annotations.Nullable;
import javax.annotation.Nullable;
import static li.cil.oc2.common.block.Blocks.*;
import static li.cil.oc2.common.tags.BlockTags.*;

View File

@@ -9,7 +9,8 @@ import net.minecraft.data.ItemTagsProvider;
import net.minecraft.tags.ItemTags;
import net.minecraftforge.common.Tags;
import net.minecraftforge.common.data.ExistingFileHelper;
import org.jetbrains.annotations.Nullable;
import javax.annotation.Nullable;
import static li.cil.oc2.common.tags.ItemTags.*;

View File

@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "oc2:block/creative_energy"
}
}
}

View File

@@ -12,6 +12,8 @@
"block.oc2.disk_drive.desc": "Used to access Floppy Disks.",
"block.oc2.charger": "Charger",
"block.oc2.charger.desc": "Charges entities and items in containers on top of it.",
"block.oc2.creative_energy": "Infinite Energy Cube",
"block.oc2.creative_energy.desc": "Provides unlimited energy to adjacent blocks. Intended for testing.",
"item.oc2.wrench": "Scrench",
"item.oc2.wrench.desc": "Used to configure devices and to dismantle them (while sneaking).",
@@ -39,12 +41,15 @@
"config.oc2.vm.maxFlashMemorySize:": "Maximum flash memory device size",
"config.oc2.modules.block_operations.toolLevel": "Block operations module tool level",
"config.oc2.admin.fakePlayerUUID": "Fake Player UUID",
"config.oc2.computerEnergyPerTick": "Energy/tick used by computers",
"config.oc2.busCableComplexity": "Bus Cable complexity",
"config.oc2.busInterfaceComplexity": "Bus Interface complexity",
"config.oc2.complexityEnergyPerTick": "Complexity energy/tick",
"config.oc2.computerEnergyPerTick": "Computer energy/tick",
"config.oc2.computerEnergyStorage": "Computer energy storage",
"config.oc2.robotEnergyPerTick": "Energy/tick used by robots",
"config.oc2.robotEnergyPerTick": "Robot energy/tick",
"config.oc2.robotEnergyStorage": "Robot energy storage",
"config.oc2.chargerEnergyPerTick": "Energy/tick transferred by chargers",
"config.oc2.chargerEnergyStorage": "Charge energy storage",
"config.oc2.chargerEnergyPerTick": "Charger energy/tick",
"config.oc2.chargerEnergyStorage": "Charger energy storage",
"gui.oc2.computer.error.unknown": "Unknown Error",
"gui.oc2.computer.error.missing_firmware": "Missing Firmware",
@@ -73,6 +78,7 @@
"tooltip.oc2.memory_missing": "Some memory is required to load the flash memory for execution to boot.",
"tooltip.oc2.hard_drive_missing": "Most systems will require a root file system to boot.",
"tooltip.oc2.energy": "Energy: %s",
"tooltip.oc2.energyConsumption": "Energy Consumption: %s",
"subtitles.oc2.computer": "Computer fans running",
"subtitles.oc2.floppy": "Floppy access",

View File

@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "oc2:block/creative_energy"
}
}

View File

@@ -0,0 +1,3 @@
{
"parent": "oc2:block/creative_energy"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

@@ -43,7 +43,7 @@ public class DeviceBusTests {
when(busControllerBusElement.getLocalDevices()).thenReturn(emptyList());
when(busControllerBusElement.getNeighbors()).thenReturn(Optional.empty());
busController = new CommonDeviceBusController(busControllerBusElement);
busController = new CommonDeviceBusController(busControllerBusElement, 0);
}
@Test

View File

@@ -1,6 +1,6 @@
package li.cil.oc2.common.bus;
import li.cil.oc2.api.bus.device.vm.VMContext;
import li.cil.oc2.api.bus.device.vm.context.VMContext;
import li.cil.oc2.api.bus.device.vm.VMDevice;
import li.cil.oc2.api.bus.device.vm.VMDeviceLoadResult;
import li.cil.oc2.common.vm.VMDeviceBusAdapter;