diff --git a/src/main/java/li/cil/oc2/common/network/Network.java b/src/main/java/li/cil/oc2/common/network/Network.java index 9dbc57bc..7d76e4e7 100644 --- a/src/main/java/li/cil/oc2/common/network/Network.java +++ b/src/main/java/li/cil/oc2/common/network/Network.java @@ -6,8 +6,10 @@ import li.cil.oc2.common.network.message.ComputerRunStateMessage; import li.cil.oc2.common.network.message.TerminalBlockInputMessage; import li.cil.oc2.common.network.message.TerminalBlockOutputMessage; import net.minecraft.util.ResourceLocation; +import net.minecraft.world.chunk.Chunk; import net.minecraftforge.fml.network.NetworkDirection; import net.minecraftforge.fml.network.NetworkRegistry; +import net.minecraftforge.fml.network.PacketDistributor; import net.minecraftforge.fml.network.simple.SimpleChannel; public final class Network { @@ -33,6 +35,22 @@ public final class Network { .decoder(TerminalBlockInputMessage::new) .consumer(TerminalBlockInputMessage::handleMessage) .add(); + + INSTANCE.messageBuilder(ComputerRunStateMessage.class, getNextPacketId(), NetworkDirection.PLAY_TO_CLIENT) + .encoder(ComputerRunStateMessage::toBytes) + .decoder(ComputerRunStateMessage::new) + .consumer(ComputerRunStateMessage::handleMessage) + .add(); + + INSTANCE.messageBuilder(ComputerBusStateMessage.class, getNextPacketId(), NetworkDirection.PLAY_TO_CLIENT) + .encoder(ComputerBusStateMessage::toBytes) + .decoder(ComputerBusStateMessage::new) + .consumer(ComputerBusStateMessage::handleMessage) + .add(); + } + + public static void sendToClientsTrackingChunk(final T message, final Chunk chunk) { + Network.INSTANCE.send(PacketDistributor.TRACKING_CHUNK.with(() -> chunk), message); } private static int getNextPacketId() { diff --git a/src/main/java/li/cil/oc2/common/network/message/ComputerBusStateMessage.java b/src/main/java/li/cil/oc2/common/network/message/ComputerBusStateMessage.java new file mode 100644 index 00000000..142278f2 --- /dev/null +++ b/src/main/java/li/cil/oc2/common/network/message/ComputerBusStateMessage.java @@ -0,0 +1,40 @@ +package li.cil.oc2.common.network.message; + +import li.cil.oc2.common.bus.TileEntityDeviceBusController; +import li.cil.oc2.common.network.MessageUtils; +import li.cil.oc2.common.tile.ComputerTileEntity; +import net.minecraft.network.PacketBuffer; +import net.minecraft.util.math.BlockPos; +import net.minecraftforge.fml.network.NetworkEvent; + +import java.util.function.Supplier; + +public class ComputerBusStateMessage { + private BlockPos pos; + private TileEntityDeviceBusController.State busState; + + public ComputerBusStateMessage(final ComputerTileEntity tileEntity) { + this.pos = tileEntity.getPos(); + this.busState = tileEntity.getBusState(); + } + + public ComputerBusStateMessage(final PacketBuffer buffer) { + fromBytes(buffer); + } + + public static boolean handleMessage(final ComputerBusStateMessage message, final Supplier context) { + context.get().enqueueWork(() -> MessageUtils.withClientTileEntityAt(message.pos, ComputerTileEntity.class, + (tileEntity) -> tileEntity.setBusStateClient(message.busState))); + return true; + } + + public void fromBytes(final PacketBuffer buffer) { + pos = buffer.readBlockPos(); + busState = buffer.readEnumValue(TileEntityDeviceBusController.State.class); + } + + public static void toBytes(final ComputerBusStateMessage message, final PacketBuffer buffer) { + buffer.writeBlockPos(message.pos); + buffer.writeEnumValue(message.busState); + } +} diff --git a/src/main/java/li/cil/oc2/common/network/message/ComputerRunStateMessage.java b/src/main/java/li/cil/oc2/common/network/message/ComputerRunStateMessage.java new file mode 100644 index 00000000..45353378 --- /dev/null +++ b/src/main/java/li/cil/oc2/common/network/message/ComputerRunStateMessage.java @@ -0,0 +1,39 @@ +package li.cil.oc2.common.network.message; + +import li.cil.oc2.common.network.MessageUtils; +import li.cil.oc2.common.tile.ComputerTileEntity; +import net.minecraft.network.PacketBuffer; +import net.minecraft.util.math.BlockPos; +import net.minecraftforge.fml.network.NetworkEvent; + +import java.util.function.Supplier; + +public class ComputerRunStateMessage { + private BlockPos pos; + private ComputerTileEntity.RunState runState; + + public ComputerRunStateMessage(final ComputerTileEntity tileEntity) { + this.pos = tileEntity.getPos(); + this.runState = tileEntity.getRunState(); + } + + public ComputerRunStateMessage(final PacketBuffer buffer) { + fromBytes(buffer); + } + + public static boolean handleMessage(final ComputerRunStateMessage message, final Supplier context) { + context.get().enqueueWork(() -> MessageUtils.withClientTileEntityAt(message.pos, ComputerTileEntity.class, + (tileEntity) -> tileEntity.setRunStateClient(message.runState))); + return true; + } + + public void fromBytes(final PacketBuffer buffer) { + pos = buffer.readBlockPos(); + runState = buffer.readEnumValue(ComputerTileEntity.RunState.class); + } + + public static void toBytes(final ComputerRunStateMessage message, final PacketBuffer buffer) { + buffer.writeBlockPos(message.pos); + buffer.writeEnumValue(message.runState); + } +} diff --git a/src/main/java/li/cil/oc2/common/tile/ComputerTileEntity.java b/src/main/java/li/cil/oc2/common/tile/ComputerTileEntity.java index e1c3529c..bb32977a 100644 --- a/src/main/java/li/cil/oc2/common/tile/ComputerTileEntity.java +++ b/src/main/java/li/cil/oc2/common/tile/ComputerTileEntity.java @@ -30,9 +30,11 @@ import net.minecraft.block.BlockState; import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.ListNBT; import net.minecraft.tileentity.ITickableTileEntity; +import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; -import net.minecraftforge.fml.network.PacketDistributor; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -58,7 +60,7 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic private static final int DEVICE_LOAD_RETRY_INTERVAL = 10 * 20; // In ticks. - private enum RunState { + public enum RunState { STOPPED, LOADING_DEVICES, RUNNING, @@ -110,7 +112,7 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic return; } - runState = RunState.LOADING_DEVICES; + setRunState(RunState.LOADING_DEVICES); loadDevicesDelay = 0; } @@ -120,15 +122,39 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic } if (runState == RunState.LOADING_DEVICES) { - runState = RunState.STOPPED; + setRunState(RunState.STOPPED); return; } stopRunnerAndUnloadDevices(); } - public boolean isRunning() { - return runner != null; + public TileEntityDeviceBusController.State getBusState() { + return busState; + } + + public RunState getRunState() { + return runState; + } + + public void handleNeighborChanged(final BlockPos pos) { + busElement.handleNeighborChanged(pos); + } + + @OnlyIn(Dist.CLIENT) + public void setRunStateClient(final RunState value) { + final World world = getWorld(); + if (world != null && world.isRemote()) { + runState = value; + } + } + + @OnlyIn(Dist.CLIENT) + public void setBusStateClient(final TileEntityDeviceBusController.State value) { + final World world = getWorld(); + if (world != null && world.isRemote()) { + busState = value; + } } @Override @@ -168,7 +194,7 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic runner = new ConsoleRunner(virtualMachine); } - runState = RunState.RUNNING; + setRunState(RunState.RUNNING); // Only start running next tick. This gives loaded devices one tick to do async // initialization. This is used by RAM to restore data from disk, for example. @@ -188,6 +214,7 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic @Override protected void initializeClient() { super.initializeClient(); + terminal.setDisplayOnly(true); } @@ -195,6 +222,7 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic protected void initializeServer() { super.initializeServer(); + busElement.initialize(); ServerScheduler.schedule(() -> chunk = requireNonNull(getWorld()).getChunkAt(getPos())); } @@ -212,6 +240,7 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic result.put(TERMINAL_NBT_TAG_NAME, NBTSerialization.serialize(terminal)); result.putInt(BUS_STATE_NBT_TAG_NAME, busState.ordinal()); + result.putInt(RUN_STATE_NBT_TAG_NAME, runState.ordinal()); return result; } @@ -222,6 +251,7 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic NBTSerialization.deserialize(tag.getCompound(TERMINAL_NBT_TAG_NAME), terminal); busState = TileEntityDeviceBusController.State.values()[tag.getInt(BUS_STATE_NBT_TAG_NAME)]; + runState = RunState.values()[tag.getInt(RUN_STATE_NBT_TAG_NAME)]; } @Override @@ -283,7 +313,9 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic runState = RunState.LOADING_DEVICES; } else { runState = NBTUtils.getEnum(compound, RUN_STATE_NBT_TAG_NAME, RunState.class); - if (runState == RunState.RUNNING) { + if (runState == null) { + runState = RunState.STOPPED; + } else if (runState == RunState.RUNNING) { runState = RunState.LOADING_DEVICES; } } @@ -349,10 +381,30 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic virtualMachine.vmAdapter.unload(); } + private void setBusState(final TileEntityDeviceBusController.State value) { + if (value == busState) { + return; + } + + busState = value; + + Network.sendToClientsTrackingChunk(new ComputerBusStateMessage(this), chunk); + } + + private void setRunState(final RunState value) { + if (value == runState) { + return; + } + + runState = value; + + Network.sendToClientsTrackingChunk(new ComputerRunStateMessage(this), chunk); + } + private void stopRunnerAndUnloadDevices() { joinVirtualMachine(); runner = null; - runState = RunState.STOPPED; + setRunState(RunState.STOPPED); unloadDevices(); virtualMachine.reset(); @@ -467,8 +519,8 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic terminal.putOutput(output); output.flip(); - final TerminalBlockOutputMessage message = new TerminalBlockOutputMessage(ComputerTileEntity.this, output); - Network.INSTANCE.send(PacketDistributor.TRACKING_CHUNK.with(() -> chunk), message); + Network.sendToClientsTrackingChunk( + new TerminalBlockOutputMessage(ComputerTileEntity.this, output), chunk); } } }