From 8ba20985d729b86226ecc0e54a53ff513d656702 Mon Sep 17 00:00:00 2001 From: Jonathan Coates Date: Mon, 27 Sep 2021 22:18:32 +0100 Subject: [PATCH] Store additional state in WiredModemPeripheral This means wired peripherals now correctly track their current mounts and attached state, rather than inheriting from the origin wired modem. Closes #890 --- .../core/apis/ComputerAccess.java | 6 ++ .../modem/wired/WiredModemPeripheral.java | 61 +++++++++++++++---- 2 files changed, 54 insertions(+), 13 deletions(-) diff --git a/src/main/java/dan200/computercraft/core/apis/ComputerAccess.java b/src/main/java/dan200/computercraft/core/apis/ComputerAccess.java index 39c4a2ff3..fdf68c141 100644 --- a/src/main/java/dan200/computercraft/core/apis/ComputerAccess.java +++ b/src/main/java/dan200/computercraft/core/apis/ComputerAccess.java @@ -5,6 +5,7 @@ */ package dan200.computercraft.core.apis; +import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.filesystem.IMount; import dan200.computercraft.api.filesystem.IWritableMount; import dan200.computercraft.api.peripheral.IComputerAccess; @@ -30,6 +31,11 @@ protected ComputerAccess( IAPIEnvironment environment ) public void unmountAll() { FileSystem fileSystem = environment.getFileSystem(); + if( !mounts.isEmpty() ) + { + ComputerCraft.log.warn( "Peripheral or API called mount but did not call unmount for {}", mounts ); + } + for( String mount : mounts ) { fileSystem.unmount( mount ); diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemPeripheral.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemPeripheral.java index 2b961924c..554a4478d 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemPeripheral.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemPeripheral.java @@ -6,6 +6,7 @@ package dan200.computercraft.shared.peripheral.modem.wired; import com.google.common.collect.ImmutableMap; +import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.filesystem.IMount; import dan200.computercraft.api.filesystem.IWritableMount; import dan200.computercraft.api.lua.*; @@ -15,6 +16,7 @@ import dan200.computercraft.api.peripheral.IComputerAccess; import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.api.peripheral.IWorkMonitor; +import dan200.computercraft.api.peripheral.NotAttachedException; import dan200.computercraft.core.apis.PeripheralAPI; import dan200.computercraft.core.asm.PeripheralMethod; import dan200.computercraft.shared.peripheral.modem.ModemPeripheral; @@ -23,10 +25,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -311,6 +310,9 @@ private static class RemotePeripheralWrapper implements IComputerAccess private final String type; private final Map methodMap; + private volatile boolean attached; + private final Set mounts = new HashSet<>(); + RemotePeripheralWrapper( WiredModemElement element, IPeripheral peripheral, IComputerAccess computer, String name ) { this.element = element; @@ -324,6 +326,7 @@ private static class RemotePeripheralWrapper implements IComputerAccess public void attach() { + attached = true; peripheral.attach( this ); computer.queueEvent( "peripheral", getAttachmentName() ); } @@ -332,6 +335,18 @@ public void detach() { peripheral.detach( this ); computer.queueEvent( "peripheral_detach", getAttachmentName() ); + attached = false; + + synchronized( this ) + { + if( !mounts.isEmpty() ) + { + ComputerCraft.log.warn( "Peripheral {} called mount but did not call unmount for {}", peripheral, mounts ); + } + + for( String mount : mounts ) computer.unmount( mount ); + mounts.clear(); + } } public String getType() @@ -354,44 +369,60 @@ public MethodResult callMethod( ILuaContext context, String methodName, IArgumen // IComputerAccess implementation @Override - public String mount( @Nonnull String desiredLocation, @Nonnull IMount mount ) + public synchronized String mount( @Nonnull String desiredLocation, @Nonnull IMount mount ) { - return computer.mount( desiredLocation, mount, name ); + if( !attached ) throw new NotAttachedException(); + String mounted = computer.mount( desiredLocation, mount, name ); + mounts.add( mounted ); + return mounted; } @Override - public String mount( @Nonnull String desiredLocation, @Nonnull IMount mount, @Nonnull String driveName ) + public synchronized String mount( @Nonnull String desiredLocation, @Nonnull IMount mount, @Nonnull String driveName ) { - return computer.mount( desiredLocation, mount, driveName ); + if( !attached ) throw new NotAttachedException(); + String mounted = computer.mount( desiredLocation, mount, driveName ); + mounts.add( mounted ); + return mounted; } @Override - public String mountWritable( @Nonnull String desiredLocation, @Nonnull IWritableMount mount ) + public synchronized String mountWritable( @Nonnull String desiredLocation, @Nonnull IWritableMount mount ) { - return computer.mountWritable( desiredLocation, mount, name ); + if( !attached ) throw new NotAttachedException(); + String mounted = computer.mountWritable( desiredLocation, mount, name ); + mounts.add( mounted ); + return mounted; } @Override - public String mountWritable( @Nonnull String desiredLocation, @Nonnull IWritableMount mount, @Nonnull String driveName ) + public synchronized String mountWritable( @Nonnull String desiredLocation, @Nonnull IWritableMount mount, @Nonnull String driveName ) { - return computer.mountWritable( desiredLocation, mount, driveName ); + if( !attached ) throw new NotAttachedException(); + String mounted = computer.mountWritable( desiredLocation, mount, driveName ); + mounts.add( mounted ); + return mounted; } @Override - public void unmount( String location ) + public synchronized void unmount( String location ) { + if( !attached ) throw new NotAttachedException(); computer.unmount( location ); + mounts.remove( location ); } @Override public int getID() { + if( !attached ) throw new NotAttachedException(); return computer.getID(); } @Override public void queueEvent( @Nonnull String event, Object... arguments ) { + if( !attached ) throw new NotAttachedException(); computer.queueEvent( event, arguments ); } @@ -399,6 +430,7 @@ public void queueEvent( @Nonnull String event, Object... arguments ) @Override public IWorkMonitor getMainThreadMonitor() { + if( !attached ) throw new NotAttachedException(); return computer.getMainThreadMonitor(); } @@ -406,6 +438,7 @@ public IWorkMonitor getMainThreadMonitor() @Override public String getAttachmentName() { + if( !attached ) throw new NotAttachedException(); return name; } @@ -413,6 +446,7 @@ public String getAttachmentName() @Override public Map getAvailablePeripherals() { + if( !attached ) throw new NotAttachedException(); synchronized( element.getRemotePeripherals() ) { return ImmutableMap.copyOf( element.getRemotePeripherals() ); @@ -423,6 +457,7 @@ public Map getAvailablePeripherals() @Override public IPeripheral getAvailablePeripheral( @Nonnull String name ) { + if( !attached ) throw new NotAttachedException(); synchronized( element.getRemotePeripherals() ) { return element.getRemotePeripherals().get( name );