From 5a57938cb52afa3ce23b89bfec92802a0fa21f91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Tue, 15 Dec 2020 04:27:27 +0100 Subject: [PATCH] Switch from hardcoded ram to item ram and add support for lifecycle events in computer tile entity. --- .../block/entity/ComputerTileEntity.java | 162 ++++++------------ 1 file changed, 54 insertions(+), 108 deletions(-) diff --git a/src/main/java/li/cil/oc2/common/block/entity/ComputerTileEntity.java b/src/main/java/li/cil/oc2/common/block/entity/ComputerTileEntity.java index 4afdb355..cebd10c2 100644 --- a/src/main/java/li/cil/oc2/common/block/entity/ComputerTileEntity.java +++ b/src/main/java/li/cil/oc2/common/block/entity/ComputerTileEntity.java @@ -2,10 +2,10 @@ package li.cil.oc2.common.block.entity; import it.unimi.dsi.fastutil.bytes.ByteArrayFIFOQueue; import li.cil.ceres.api.Serialized; -import li.cil.oc2.Constants; import li.cil.oc2.OpenComputers; import li.cil.oc2.api.bus.DeviceBusElement; import li.cil.oc2.api.bus.device.Device; +import li.cil.oc2.api.bus.device.vm.VMLifecycleEventType; import li.cil.oc2.common.block.ComputerBlock; import li.cil.oc2.common.bus.AbstractDeviceBusController; import li.cil.oc2.common.bus.TileEntityDeviceBusElement; @@ -15,25 +15,21 @@ import li.cil.oc2.common.network.Network; import li.cil.oc2.common.network.message.ComputerBusStateMessage; import li.cil.oc2.common.network.message.ComputerRunStateMessage; import li.cil.oc2.common.network.message.TerminalBlockOutputMessage; -import li.cil.oc2.common.serialization.BlobStorage; import li.cil.oc2.common.serialization.NBTSerialization; +import li.cil.oc2.common.util.HorizontalBlockUtils; import li.cil.oc2.common.util.NBTTagIds; import li.cil.oc2.common.util.NBTUtils; import li.cil.oc2.common.util.ServerScheduler; import li.cil.oc2.common.vm.Terminal; import li.cil.oc2.common.vm.VirtualMachine; import li.cil.oc2.common.vm.VirtualMachineRunner; -import li.cil.sedna.api.Sizes; -import li.cil.sedna.api.device.PhysicalMemory; import li.cil.sedna.buildroot.Buildroot; -import li.cil.sedna.device.memory.Memory; import li.cil.sedna.device.virtio.VirtIOFileSystemDevice; import li.cil.sedna.fs.HostFileSystem; -import li.cil.sedna.memory.PhysicalMemoryInputStream; -import li.cil.sedna.memory.PhysicalMemoryOutputStream; +import li.cil.sedna.memory.MemoryMaps; import net.minecraft.block.BlockState; +import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; -import net.minecraft.nbt.ListNBT; import net.minecraft.tileentity.ITickableTileEntity; import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; @@ -42,16 +38,19 @@ import net.minecraft.world.chunk.Chunk; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.common.util.LazyOptional; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.NotNull; import javax.annotation.Nullable; -import java.io.BufferedInputStream; import java.io.InputStream; import java.nio.ByteBuffer; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Optional; +import java.util.Set; import static java.util.Objects.requireNonNull; @@ -60,7 +59,6 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic /////////////////////////////////////////////////////////////////// - private static final String DEVICES_NBT_TAG_NAME = "devices"; private static final String BUS_ELEMENT_NBT_TAG_NAME = "busElement"; private static final String BUS_STATE_NBT_TAG_NAME = "busState"; private static final String TERMINAL_NBT_TAG_NAME = "terminal"; @@ -87,7 +85,6 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic private AbstractDeviceBusController.BusState busState; private RunState runState; private int loadDevicesDelay; - @Nullable private BlobStorage.JobHandle ramJobHandle; /////////////////////////////////////////////////////////////////// @@ -97,9 +94,6 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic private final VirtIOFileSystemDevice vfs; private ConsoleRunner runner; - private PhysicalMemory ram; - private UUID ramBlobHandle; - private final DeviceItemStackHandler itemHandler = new DeviceItemStackHandler(4); /////////////////////////////////////////////////////////////////// @@ -121,6 +115,10 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic setCapabilityIfAbsent(Capabilities.DEVICE_BUS_ELEMENT_CAPABILITY, busElement); setCapabilityIfAbsent(Capabilities.DEVICE_BUS_CONTROLLER_CAPABILITY, busController); + + itemHandler.setStackInSlot(0, new ItemStack(OpenComputers.RAM_8M_ITEM.get())); + itemHandler.setStackInSlot(1, new ItemStack(OpenComputers.RAM_8M_ITEM.get())); + itemHandler.setStackInSlot(2, new ItemStack(OpenComputers.RAM_8M_ITEM.get())); } public Terminal getTerminal() { @@ -146,7 +144,7 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic return; } - stopRunnerAndUnloadDevices(); + stopRunnerAndResetVM(); } public boolean isRunning() { @@ -184,8 +182,24 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic @Override public @NotNull LazyOptional getCapability(final @NotNull Capability capability, @Nullable final Direction side) { - if (side == getBlockState().get(ComputerBlock.HORIZONTAL_FACING)) { - return LazyOptional.empty(); + if (capability == Capabilities.DEVICE_BUS_ELEMENT_CAPABILITY || + capability == Capabilities.DEVICE_BUS_CONTROLLER_CAPABILITY) { + if (side == getBlockState().get(ComputerBlock.HORIZONTAL_FACING)) { + return LazyOptional.empty(); + } else { // Do not allow item devices to override our bus element and controller. + return super.getCapability(capability, side); + } + } + + final Direction localSide = HorizontalBlockUtils.toLocal(getBlockState(), side); + + for (final Device device : busController.getDevices()) { + if (device instanceof ICapabilityProvider) { + final LazyOptional value = ((ICapabilityProvider) device).getCapability(capability, localSide); + if (value.isPresent()) { + return value; + } + } } return super.getCapability(capability, side); @@ -213,7 +227,7 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic break; } - if (!loadDevices()) { + if (!virtualMachine.vmAdapter.load()) { loadDevicesDelay = DEVICE_LOAD_RETRY_INTERVAL; break; } @@ -235,7 +249,7 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic break; case RUNNING: if (!virtualMachine.board.isRunning()) { - stopRunnerAndUnloadDevices(); + stopRunnerAndResetVM(); break; } @@ -270,10 +284,6 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic compound = super.write(compound); joinVirtualMachine(); - if (ramJobHandle != null) { - ramJobHandle.await(); - ramJobHandle = null; - } compound.put(TERMINAL_NBT_TAG_NAME, NBTSerialization.serialize(terminal)); @@ -289,10 +299,6 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic compound.put(ITEMS_NBT_TAG_NAME, itemHandler.serializeNBT()); - final ListNBT devicesNbt = new ListNBT(); - writeDevices(devicesNbt); - compound.put(DEVICES_NBT_TAG_NAME, devicesNbt); - return compound; } @@ -301,10 +307,6 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic super.read(state, compound); joinVirtualMachine(); - if (ramJobHandle != null) { - ramJobHandle.await(); - ramJobHandle = null; - } NBTSerialization.deserialize(compound.getCompound(TERMINAL_NBT_TAG_NAME), terminal); @@ -334,12 +336,11 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic } if (compound.contains(ITEMS_NBT_TAG_NAME, NBTTagIds.TAG_COMPOUND)) { + itemHandler.setStackInSlot(0, ItemStack.EMPTY); + itemHandler.setStackInSlot(1, ItemStack.EMPTY); + itemHandler.setStackInSlot(2, ItemStack.EMPTY); itemHandler.deserializeNBT(compound.getCompound(ITEMS_NBT_TAG_NAME)); } - - if (compound.contains(DEVICES_NBT_TAG_NAME, NBTTagIds.TAG_LIST)) { - readDevices(compound.getList(DEVICES_NBT_TAG_NAME, NBTTagIds.TAG_COMPOUND)); - } } /////////////////////////////////////////////////////////////////// @@ -364,67 +365,13 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic protected void disposeServer() { super.disposeServer(); - stopRunnerAndUnloadDevices(); + stopRunnerAndResetVM(); busController.dispose(); busElement.dispose(); } /////////////////////////////////////////////////////////////////// - private void writeDevices(final ListNBT list) { - // TODO Apply to devices generated from items. - - if (ram != null) { - final CompoundNBT ramNbt = new CompoundNBT(); - ramBlobHandle = BlobStorage.validateHandle(ramBlobHandle); - ramNbt.putUniqueId("ram", ramBlobHandle); - list.add(ramNbt); - - ramJobHandle = BlobStorage.JobHandle.combine(ramJobHandle, - BlobStorage.submitSave(ramBlobHandle, new PhysicalMemoryInputStream(ram))); - } else { - list.add(new CompoundNBT()); - } - } - - private void readDevices(final ListNBT list) { - // TODO Apply to devices generated from items. - - final CompoundNBT ramNbt = list.getCompound(0); - if (ramNbt.hasUniqueId("ram")) { - ramBlobHandle = ramNbt.getUniqueId("ram"); - } - } - - private boolean loadDevices() { - // TODO Load devices generated from items. - - if (ram == null) { - final int RAM_SIZE = 24 * Constants.MEGABYTE; - ram = Memory.create(RAM_SIZE); - virtualMachine.board.addDevice(0x80000000L, ram); - } - - if (ramBlobHandle != null) { - ramJobHandle = BlobStorage.JobHandle.combine(ramJobHandle, - BlobStorage.submitLoad(ramBlobHandle, new PhysicalMemoryOutputStream(ram))); - } - - return virtualMachine.vmAdapter.load(); - } - - private void unloadDevices() { - // TODO Unload devices generated from items. - - if (ram != null) { - virtualMachine.board.removeDevice(ram); - ram = null; - BlobStorage.freeHandle(ramBlobHandle); - } - - virtualMachine.vmAdapter.unload(); - } - private void setBusState(final AbstractDeviceBusController.BusState value) { if (value == busState) { return; @@ -445,7 +392,7 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic Network.sendToClientsTrackingChunk(new ComputerRunStateMessage(this), chunk); } - private void stopRunnerAndUnloadDevices() { + private void stopRunnerAndResetVM() { joinVirtualMachine(); runner = null; setRunState(RunState.STOPPED); @@ -464,15 +411,12 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic } } - private static void loadProgramFile(final PhysicalMemory memory, final InputStream stream) throws Throwable { - loadProgramFile(memory, stream, 0); + private void loadProgramFile(final InputStream stream) throws Throwable { + loadProgramFile(stream, 0); } - private static void loadProgramFile(final PhysicalMemory memory, final InputStream stream, final int offset) throws Throwable { - final BufferedInputStream bis = new BufferedInputStream(stream); - for (int address = 0, value = bis.read(); value != -1; value = bis.read(), address++) { - memory.store(offset + address, (byte) value, Sizes.SIZE_8_LOG2); - } + private void loadProgramFile(final InputStream stream, final int offset) throws Throwable { + MemoryMaps.store(virtualMachine.board.getMemoryMap(), 0x80000000L + offset, stream); } /////////////////////////////////////////////////////////////////// @@ -532,7 +476,8 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic private final ByteArrayFIFOQueue outputBuffer = new ByteArrayFIFOQueue(1024); private final ByteArrayFIFOQueue inputBuffer = new ByteArrayFIFOQueue(32); - @Serialized private boolean didInitialization; + private boolean firedResumeEvent; + @Serialized private boolean firedInitializationEvent; public ConsoleRunner(final VirtualMachine virtualMachine) { super(virtualMachine.board); @@ -540,10 +485,9 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic @Override public void tick() { - // TODO Tick devices that need it synchronously. - if (ramJobHandle != null) { - ramJobHandle.await(); - ramJobHandle = null; + if (!firedResumeEvent) { + firedResumeEvent = true; + virtualMachine.vmAdapter.fireLifecycleEvent(VMLifecycleEventType.RESUME_RUNNING); } virtualMachine.rpcAdapter.tick(); @@ -553,13 +497,15 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic @Override protected void handleBeforeRun() { - if (!didInitialization) { - didInitialization = true; + if (!firedInitializationEvent) { + firedInitializationEvent = true; + virtualMachine.vmAdapter.fireLifecycleEvent(VMLifecycleEventType.INITIALIZE); + try { // TODO Initialize devices that need it asynchronously. - loadProgramFile(ram, Buildroot.getFirmware()); - loadProgramFile(ram, Buildroot.getLinuxImage(), 0x200000); + loadProgramFile(Buildroot.getFirmware()); + loadProgramFile(Buildroot.getLinuxImage(), 0x200000); } catch (final Throwable e) { LOGGER.error(e); }