mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-01-12 10:20:28 +00:00
Allow modems to handle being attached to multiple computers
- Introduce a ModemState, which shares the open channels across all modem instances of a wired modem. - Keep a set of computers for all modem peripherals. - Keep a map of computers -> (string, peripheral) for wired modem peripherals. We shouldn't need this one, as you cannot attach one modem to another, but it's good to be consistent. One major change here is that modems will continue to be "on", even if no computers are attached. This would substantially increase implementation complexity, so I think this is an acceptable compromise for now. Should fix #74
This commit is contained in:
parent
4bd7381827
commit
62cf921cc6
@ -14,53 +14,43 @@ import dan200.computercraft.api.network.IPacketSender;
|
||||
import dan200.computercraft.api.network.Packet;
|
||||
import dan200.computercraft.api.peripheral.IComputerAccess;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import gnu.trove.set.TIntSet;
|
||||
import gnu.trove.set.hash.TIntHashSet;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static dan200.computercraft.core.apis.ArgumentHelper.getInt;
|
||||
|
||||
public abstract class ModemPeripheral
|
||||
implements IPeripheral, IPacketSender, IPacketReceiver
|
||||
public abstract class ModemPeripheral implements IPeripheral, IPacketSender, IPacketReceiver
|
||||
{
|
||||
private IPacketNetwork m_network;
|
||||
private IComputerAccess m_computer;
|
||||
private final TIntSet m_channels;
|
||||
private Set<IComputerAccess> m_computers = new HashSet<>( 1 );
|
||||
private final ModemState m_state;
|
||||
|
||||
private boolean m_open;
|
||||
private boolean m_changed;
|
||||
|
||||
public ModemPeripheral()
|
||||
protected ModemPeripheral( ModemState state )
|
||||
{
|
||||
m_network = null;
|
||||
m_computer = null;
|
||||
m_channels = new TIntHashSet();
|
||||
m_open = false;
|
||||
m_changed = true;
|
||||
this.m_state = state;
|
||||
}
|
||||
|
||||
public ModemState getModemState()
|
||||
{
|
||||
return m_state;
|
||||
}
|
||||
|
||||
private synchronized void setNetwork( IPacketNetwork network )
|
||||
{
|
||||
if( m_network != network )
|
||||
{
|
||||
// Leave old network
|
||||
if( m_network != null )
|
||||
{
|
||||
m_network.removeReceiver( this );
|
||||
}
|
||||
if( m_network == network ) return;
|
||||
|
||||
// Set new network
|
||||
m_network = network;
|
||||
// Leave old network
|
||||
if( m_network != null ) m_network.removeReceiver( this );
|
||||
|
||||
// Join new network
|
||||
if( m_network != null )
|
||||
{
|
||||
m_network.addReceiver( this );
|
||||
}
|
||||
}
|
||||
// Set new network
|
||||
m_network = network;
|
||||
|
||||
// Join new network
|
||||
if( m_network != null ) m_network.addReceiver( this );
|
||||
}
|
||||
|
||||
protected void switchNetwork()
|
||||
@ -71,36 +61,19 @@ public abstract class ModemPeripheral
|
||||
public synchronized void destroy()
|
||||
{
|
||||
setNetwork( null );
|
||||
m_channels.clear();
|
||||
m_open = false;
|
||||
}
|
||||
|
||||
public boolean pollChanged()
|
||||
{
|
||||
if( m_changed )
|
||||
{
|
||||
m_changed = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isActive()
|
||||
{
|
||||
return m_computer != null && m_open;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receiveSameDimension( @Nonnull Packet packet, double distance )
|
||||
{
|
||||
if( packet.getSender() == this ) return;
|
||||
if( packet.getSender() == this || !m_state.isOpen( packet.getChannel() ) ) return;
|
||||
|
||||
synchronized (m_channels)
|
||||
synchronized( this )
|
||||
{
|
||||
if( m_computer != null && m_channels.contains( packet.getChannel() ) )
|
||||
for( IComputerAccess computer : m_computers )
|
||||
{
|
||||
m_computer.queueEvent( "modem_message", new Object[] {
|
||||
m_computer.getAttachmentName(), packet.getChannel(), packet.getReplyChannel(), packet.getPayload(), distance
|
||||
computer.queueEvent( "modem_message", new Object[]{
|
||||
computer.getAttachmentName(), packet.getChannel(), packet.getReplyChannel(), packet.getPayload(), distance
|
||||
} );
|
||||
}
|
||||
}
|
||||
@ -109,21 +82,21 @@ public abstract class ModemPeripheral
|
||||
@Override
|
||||
public void receiveDifferentDimension( @Nonnull Packet packet )
|
||||
{
|
||||
if( packet.getSender() == this ) return;
|
||||
if( packet.getSender() == this || !m_state.isOpen( packet.getChannel() ) ) return;
|
||||
|
||||
synchronized (m_channels)
|
||||
synchronized( this )
|
||||
{
|
||||
if( m_computer != null && m_channels.contains( packet.getChannel() ) )
|
||||
for( IComputerAccess computer : m_computers )
|
||||
{
|
||||
m_computer.queueEvent( "modem_message", new Object[] {
|
||||
m_computer.getAttachmentName(), packet.getChannel(), packet.getReplyChannel(), packet.getPayload()
|
||||
computer.queueEvent( "modem_message", new Object[]{
|
||||
computer.getAttachmentName(), packet.getChannel(), packet.getReplyChannel(), packet.getPayload()
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract IPacketNetwork getNetwork();
|
||||
|
||||
|
||||
// IPeripheral implementation
|
||||
|
||||
@Nonnull
|
||||
@ -132,12 +105,12 @@ public abstract class ModemPeripheral
|
||||
{
|
||||
return "modem";
|
||||
}
|
||||
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String[] getMethodNames()
|
||||
{
|
||||
return new String[] {
|
||||
return new String[]{
|
||||
"open",
|
||||
"isOpen",
|
||||
"close",
|
||||
@ -146,7 +119,7 @@ public abstract class ModemPeripheral
|
||||
"isWireless",
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private static int parseChannel( Object[] arguments, int index ) throws LuaException
|
||||
{
|
||||
int channel = getInt( arguments, index );
|
||||
@ -156,7 +129,7 @@ public abstract class ModemPeripheral
|
||||
}
|
||||
return channel;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object[] callMethod( @Nonnull IComputerAccess computer, @Nonnull ILuaContext context, int method, @Nonnull Object[] arguments ) throws LuaException, InterruptedException
|
||||
{
|
||||
@ -166,68 +139,26 @@ public abstract class ModemPeripheral
|
||||
{
|
||||
// open
|
||||
int channel = parseChannel( arguments, 0 );
|
||||
synchronized( this )
|
||||
{
|
||||
if( !m_channels.contains( channel ) )
|
||||
{
|
||||
if( m_channels.size() >= 128 )
|
||||
{
|
||||
throw new LuaException( "Too many open channels" );
|
||||
}
|
||||
|
||||
m_channels.add( channel );
|
||||
if( !m_open )
|
||||
{
|
||||
m_open = true;
|
||||
m_changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_state.open( channel );
|
||||
return null;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
// isOpen
|
||||
int channel = parseChannel( arguments, 0 );
|
||||
synchronized( this )
|
||||
{
|
||||
boolean open = m_channels.contains( channel );
|
||||
return new Object[] { open };
|
||||
}
|
||||
return new Object[]{ m_state.isOpen( channel ) };
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
// close
|
||||
int channel = parseChannel( arguments, 0 );
|
||||
synchronized( this )
|
||||
{
|
||||
if( m_channels.remove( channel ) )
|
||||
{
|
||||
if( m_channels.size() == 0 )
|
||||
{
|
||||
m_open = false;
|
||||
m_changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_state.close( channel );
|
||||
return null;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
// closeAll
|
||||
synchronized( this )
|
||||
{
|
||||
if( m_channels.size() > 0 )
|
||||
{
|
||||
m_channels.clear();
|
||||
|
||||
if( m_open )
|
||||
{
|
||||
m_open = false;
|
||||
m_changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_state.closeAll();
|
||||
return null;
|
||||
}
|
||||
case 4:
|
||||
@ -235,12 +166,12 @@ public abstract class ModemPeripheral
|
||||
// transmit
|
||||
int channel = parseChannel( arguments, 0 );
|
||||
int replyChannel = parseChannel( arguments, 1 );
|
||||
Object payload = (arguments.length >= 3) ? arguments[2] : null;
|
||||
Object payload = arguments.length > 2 ? arguments[2] : null;
|
||||
synchronized( this )
|
||||
{
|
||||
World world = getWorld();
|
||||
Vec3d position = getPosition();
|
||||
if( world != null && position != null && m_network != null)
|
||||
if( world != null && position != null && m_network != null )
|
||||
{
|
||||
Packet packet = new Packet( channel, replyChannel, payload, this );
|
||||
if( isInterdimensional() )
|
||||
@ -258,14 +189,8 @@ public abstract class ModemPeripheral
|
||||
case 5:
|
||||
{
|
||||
// isWireless
|
||||
synchronized( this )
|
||||
{
|
||||
if( m_network != null )
|
||||
{
|
||||
return new Object[] { m_network.isWireless() };
|
||||
}
|
||||
}
|
||||
return new Object[] { false };
|
||||
IPacketNetwork network = m_network;
|
||||
return new Object[]{ network != null && network.isWireless() };
|
||||
}
|
||||
default:
|
||||
{
|
||||
@ -273,50 +198,33 @@ public abstract class ModemPeripheral
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public synchronized void attach( @Nonnull IComputerAccess computer )
|
||||
{
|
||||
m_computer = computer;
|
||||
m_computers.add( computer );
|
||||
setNetwork( getNetwork() );
|
||||
m_open = !m_channels.isEmpty();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public synchronized void detach( @Nonnull IComputerAccess computer )
|
||||
{
|
||||
if( m_network != null )
|
||||
{
|
||||
m_network.removeReceiver( this );
|
||||
m_channels.clear();
|
||||
m_network = null;
|
||||
}
|
||||
|
||||
m_computer = null;
|
||||
|
||||
if( m_open )
|
||||
{
|
||||
m_open = false;
|
||||
m_changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
public IComputerAccess getComputer()
|
||||
{
|
||||
return m_computer;
|
||||
m_computers.remove( computer );
|
||||
if( m_computers.isEmpty() ) setNetwork( null );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String getSenderID()
|
||||
public synchronized String getSenderID()
|
||||
{
|
||||
if( m_computer == null )
|
||||
if( m_computers.size() != 1 )
|
||||
{
|
||||
return "unknown";
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_computer.getID() + "_" + m_computer.getAttachmentName();
|
||||
IComputerAccess computer = m_computers.iterator().next();
|
||||
return computer.getID() + "_" + computer.getAttachmentName();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2018. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.peripheral.modem;
|
||||
|
||||
import dan200.computercraft.api.lua.LuaException;
|
||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class ModemState
|
||||
{
|
||||
private boolean open = false;
|
||||
private AtomicBoolean changed = new AtomicBoolean( true );
|
||||
|
||||
private final IntSet channels = new IntOpenHashSet();
|
||||
|
||||
private void setOpen( boolean open )
|
||||
{
|
||||
if( this.open == open ) return;
|
||||
this.open = open;
|
||||
this.changed.set( true );
|
||||
}
|
||||
|
||||
public boolean pollChanged()
|
||||
{
|
||||
return changed.getAndSet( false );
|
||||
}
|
||||
|
||||
public boolean isOpen()
|
||||
{
|
||||
return open;
|
||||
}
|
||||
|
||||
public boolean isOpen( int channel )
|
||||
{
|
||||
synchronized( channels )
|
||||
{
|
||||
return channels.contains( channel );
|
||||
}
|
||||
}
|
||||
|
||||
public void open( int channel ) throws LuaException
|
||||
{
|
||||
synchronized( channels )
|
||||
{
|
||||
if( !channels.contains( channel ) )
|
||||
{
|
||||
if( channels.size() >= 128 ) throw new LuaException( "Too many open channels" );
|
||||
channels.add( channel );
|
||||
setOpen( true );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void close( int channel )
|
||||
{
|
||||
synchronized( channels )
|
||||
{
|
||||
channels.remove( channel );
|
||||
if( channels.isEmpty() ) setOpen( false );
|
||||
}
|
||||
}
|
||||
|
||||
public void closeAll()
|
||||
{
|
||||
synchronized( channels )
|
||||
{
|
||||
channels.clear();
|
||||
setOpen( false );
|
||||
}
|
||||
}
|
||||
}
|
@ -25,7 +25,7 @@ public class TileAdvancedModem extends TileModemBase
|
||||
|
||||
public Peripheral( TileModemBase entity )
|
||||
{
|
||||
super( true );
|
||||
super( new ModemState(), true );
|
||||
m_entity = entity;
|
||||
}
|
||||
|
||||
|
@ -97,7 +97,7 @@ public class TileCable extends TileModemBase
|
||||
|
||||
private boolean m_hasDirection = false;
|
||||
private boolean m_connectionsFormed = false;
|
||||
|
||||
|
||||
private WiredModemElement m_cable;
|
||||
private IWiredNode m_node;
|
||||
|
||||
@ -106,7 +106,7 @@ public class TileCable extends TileModemBase
|
||||
{
|
||||
m_cable = new CableElement( this );
|
||||
m_node = m_cable.getNode();
|
||||
return new WiredModemPeripheral( m_cable )
|
||||
return new WiredModemPeripheral( new ModemState(), m_cable )
|
||||
{
|
||||
@Nonnull
|
||||
@Override
|
||||
@ -453,14 +453,8 @@ public class TileCable extends TileModemBase
|
||||
protected void updateAnim()
|
||||
{
|
||||
int anim = 0;
|
||||
if( m_modem.isActive() )
|
||||
{
|
||||
anim += 1;
|
||||
}
|
||||
if( m_peripheralAccessAllowed )
|
||||
{
|
||||
anim += 2;
|
||||
}
|
||||
if( m_modem.getModemState().isOpen() ) anim |= 1;
|
||||
if( m_peripheralAccessAllowed ) anim |= 2;
|
||||
setAnim( anim );
|
||||
}
|
||||
|
||||
|
@ -56,10 +56,7 @@ public abstract class TileModemBase extends TilePeripheralBase
|
||||
public void onNeighbourChange()
|
||||
{
|
||||
EnumFacing dir = getDirection();
|
||||
if( !getWorld().isSideSolid(
|
||||
getPos().offset( dir ),
|
||||
dir.getOpposite()
|
||||
) )
|
||||
if( !getWorld().isSideSolid( getPos().offset( dir ), dir.getOpposite() ) )
|
||||
{
|
||||
// Drop everything and remove block
|
||||
((BlockGeneric)getBlockType()).dropAllItems( getWorld(), getPos(), false );
|
||||
@ -79,22 +76,15 @@ public abstract class TileModemBase extends TilePeripheralBase
|
||||
public void update()
|
||||
{
|
||||
super.update();
|
||||
if( !getWorld().isRemote && m_modem.pollChanged() )
|
||||
if( !getWorld().isRemote && m_modem.getModemState().pollChanged() )
|
||||
{
|
||||
updateAnim();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void updateAnim()
|
||||
{
|
||||
if( m_modem.isActive() )
|
||||
{
|
||||
setAnim(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
setAnim(0);
|
||||
}
|
||||
setAnim( m_modem.getModemState().isOpen() ? 1 : 0 );
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -109,15 +99,6 @@ public abstract class TileModemBase extends TilePeripheralBase
|
||||
@Override
|
||||
public IPeripheral getPeripheral( EnumFacing side )
|
||||
{
|
||||
if( side == getDirection() )
|
||||
{
|
||||
return m_modem;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected boolean isAttached()
|
||||
{
|
||||
return (m_modem != null) && (m_modem.getComputer() != null);
|
||||
return side == getDirection() ? m_modem : null;
|
||||
}
|
||||
}
|
||||
|
@ -83,6 +83,7 @@ public class TileWiredModemFull extends TilePeripheralBase
|
||||
private boolean m_destroyed = false;
|
||||
private boolean m_connectionsFormed = false;
|
||||
|
||||
private final ModemState m_modemState = new ModemState();
|
||||
private final WiredModemElement m_element = new FullElement( this );
|
||||
private final IWiredNode m_node = m_element.getNode();
|
||||
|
||||
@ -236,19 +237,8 @@ public class TileWiredModemFull extends TilePeripheralBase
|
||||
protected void updateAnim()
|
||||
{
|
||||
int anim = 0;
|
||||
for( WiredModemPeripheral modem : m_modems )
|
||||
{
|
||||
if( modem != null && modem.isActive() )
|
||||
{
|
||||
anim += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( m_peripheralAccessAllowed )
|
||||
{
|
||||
anim += 2;
|
||||
}
|
||||
if( m_modemState.isOpen() ) anim |= 1;
|
||||
if( m_peripheralAccessAllowed ) anim |= 2;
|
||||
setAnim( anim );
|
||||
}
|
||||
|
||||
@ -264,12 +254,7 @@ public class TileWiredModemFull extends TilePeripheralBase
|
||||
{
|
||||
if( !getWorld().isRemote )
|
||||
{
|
||||
boolean changed = false;
|
||||
for( WiredModemPeripheral peripheral : m_modems )
|
||||
{
|
||||
if( peripheral != null && peripheral.pollChanged() ) changed = true;
|
||||
}
|
||||
if( changed ) updateAnim();
|
||||
if( m_modemState.pollChanged() ) updateAnim();
|
||||
|
||||
if( !m_connectionsFormed )
|
||||
{
|
||||
@ -402,7 +387,7 @@ public class TileWiredModemFull extends TilePeripheralBase
|
||||
if( peripheral == null )
|
||||
{
|
||||
WiredModemLocalPeripheral localPeripheral = m_peripherals[side.ordinal()];
|
||||
peripheral = m_modems[side.ordinal()] = new WiredModemPeripheral( m_element )
|
||||
peripheral = m_modems[side.ordinal()] = new WiredModemPeripheral( m_modemState, m_element )
|
||||
{
|
||||
@Nonnull
|
||||
@Override
|
||||
|
@ -29,7 +29,7 @@ public class TileWirelessModem extends TileModemBase
|
||||
|
||||
public Peripheral( TileModemBase entity )
|
||||
{
|
||||
super( false );
|
||||
super( new ModemState(), false );
|
||||
m_entity = entity;
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,8 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import static dan200.computercraft.core.apis.ArgumentHelper.getString;
|
||||
|
||||
@ -25,10 +27,11 @@ public abstract class WiredModemPeripheral extends ModemPeripheral implements IW
|
||||
{
|
||||
private final WiredModemElement modem;
|
||||
|
||||
private final Map<String, RemotePeripheralWrapper> peripheralWrappers = new HashMap<>();
|
||||
private final Map<IComputerAccess, ConcurrentMap<String, RemotePeripheralWrapper>> peripheralWrappers = new HashMap<>( 1 );
|
||||
|
||||
public WiredModemPeripheral( WiredModemElement modem )
|
||||
public WiredModemPeripheral( ModemState state, WiredModemElement modem )
|
||||
{
|
||||
super( state );
|
||||
this.modem = modem;
|
||||
}
|
||||
|
||||
@ -88,56 +91,54 @@ public abstract class WiredModemPeripheral extends ModemPeripheral implements IW
|
||||
case 0:
|
||||
{
|
||||
// getNamesRemote
|
||||
synchronized( peripheralWrappers )
|
||||
Map<String, RemotePeripheralWrapper> wrappers = getWrappers( computer );
|
||||
Map<Object, Object> table = new HashMap<>();
|
||||
if( wrappers != null )
|
||||
{
|
||||
int idx = 1;
|
||||
Map<Object, Object> table = new HashMap<>();
|
||||
for( String name : peripheralWrappers.keySet() )
|
||||
{
|
||||
table.put( idx++, name );
|
||||
}
|
||||
return new Object[]{ table };
|
||||
for( String name : wrappers.keySet() ) table.put( idx++, name );
|
||||
}
|
||||
return new Object[]{ table };
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
// isPresentRemote
|
||||
String type = getTypeRemote( getString( arguments, 0 ) );
|
||||
return new Object[]{ type != null };
|
||||
String name = getString( arguments, 0 );
|
||||
return new Object[]{ getWrapper( computer, name ) != null };
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
// getTypeRemote
|
||||
String type = getTypeRemote( getString( arguments, 0 ) );
|
||||
if( type != null )
|
||||
{
|
||||
return new Object[]{ type };
|
||||
}
|
||||
return null;
|
||||
String name = getString( arguments, 0 );
|
||||
RemotePeripheralWrapper wrapper = getWrapper( computer, name );
|
||||
return wrapper != null ? new Object[]{ wrapper.getType() } : null;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
// getMethodsRemote
|
||||
String[] methodNames = getMethodNamesRemote( getString( arguments, 0 ) );
|
||||
if( methodNames != null )
|
||||
String name = getString( arguments, 0 );
|
||||
RemotePeripheralWrapper wrapper = getWrapper( computer, name );
|
||||
if( wrapper == null ) return null;
|
||||
|
||||
String[] methodNames = wrapper.getMethodNames();
|
||||
Map<Object, Object> table = new HashMap<>();
|
||||
for( int i = 0; i < methodNames.length; ++i )
|
||||
{
|
||||
Map<Object, Object> table = new HashMap<>();
|
||||
for( int i = 0; i < methodNames.length; ++i )
|
||||
{
|
||||
table.put( i + 1, methodNames[i] );
|
||||
}
|
||||
return new Object[]{ table };
|
||||
table.put( i + 1, methodNames[i] );
|
||||
}
|
||||
return null;
|
||||
return new Object[]{ table };
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
// callRemote
|
||||
String remoteName = getString( arguments, 0 );
|
||||
String methodName = getString( arguments, 1 );
|
||||
RemotePeripheralWrapper wrapper = getWrapper( computer, remoteName );
|
||||
if( wrapper == null ) throw new LuaException( "No peripheral: " + remoteName );
|
||||
|
||||
Object[] methodArgs = new Object[arguments.length - 2];
|
||||
System.arraycopy( arguments, 2, methodArgs, 0, arguments.length - 2 );
|
||||
return callMethodRemote( remoteName, context, methodName, methodArgs );
|
||||
return wrapper.callMethod( context, methodName, methodArgs );
|
||||
}
|
||||
case 5:
|
||||
{
|
||||
@ -157,29 +158,37 @@ public abstract class WiredModemPeripheral extends ModemPeripheral implements IW
|
||||
public void attach( @Nonnull IComputerAccess computer )
|
||||
{
|
||||
super.attach( computer );
|
||||
|
||||
ConcurrentMap<String, RemotePeripheralWrapper> wrappers;
|
||||
synchronized( peripheralWrappers )
|
||||
{
|
||||
wrappers = peripheralWrappers.get( computer );
|
||||
if( wrappers == null ) peripheralWrappers.put( computer, wrappers = new ConcurrentHashMap<>() );
|
||||
}
|
||||
|
||||
synchronized( modem.getRemotePeripherals() )
|
||||
{
|
||||
synchronized( peripheralWrappers )
|
||||
for( Map.Entry<String, IPeripheral> entry : modem.getRemotePeripherals().entrySet() )
|
||||
{
|
||||
for( Map.Entry<String, IPeripheral> entry : modem.getRemotePeripherals().entrySet() )
|
||||
{
|
||||
attachPeripheralImpl( entry.getKey(), entry.getValue() );
|
||||
}
|
||||
attachPeripheralImpl( computer, wrappers, entry.getKey(), entry.getValue() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void detach( @Nonnull IComputerAccess computer )
|
||||
public void detach( @Nonnull IComputerAccess computer )
|
||||
{
|
||||
Map<String, RemotePeripheralWrapper> wrappers;
|
||||
synchronized( peripheralWrappers )
|
||||
{
|
||||
for( RemotePeripheralWrapper wrapper : peripheralWrappers.values() )
|
||||
{
|
||||
wrapper.detach();
|
||||
}
|
||||
peripheralWrappers.clear();
|
||||
wrappers = peripheralWrappers.remove( computer );
|
||||
}
|
||||
if( wrappers != null )
|
||||
{
|
||||
for( RemotePeripheralWrapper wrapper : wrappers.values() ) wrapper.detach();
|
||||
wrappers.clear();
|
||||
}
|
||||
|
||||
super.detach( computer );
|
||||
}
|
||||
|
||||
@ -204,11 +213,12 @@ public abstract class WiredModemPeripheral extends ModemPeripheral implements IW
|
||||
|
||||
public void attachPeripheral( String name, IPeripheral peripheral )
|
||||
{
|
||||
if( getComputer() == null ) return;
|
||||
|
||||
synchronized( peripheralWrappers )
|
||||
{
|
||||
attachPeripheralImpl( name, peripheral );
|
||||
for( Map.Entry<IComputerAccess, ConcurrentMap<String, RemotePeripheralWrapper>> entry : peripheralWrappers.entrySet() )
|
||||
{
|
||||
attachPeripheralImpl( entry.getKey(), entry.getValue(), name, peripheral );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -216,63 +226,35 @@ public abstract class WiredModemPeripheral extends ModemPeripheral implements IW
|
||||
{
|
||||
synchronized( peripheralWrappers )
|
||||
{
|
||||
RemotePeripheralWrapper wrapper = peripheralWrappers.get( name );
|
||||
if( wrapper != null )
|
||||
{
|
||||
peripheralWrappers.remove( name );
|
||||
wrapper.detach();
|
||||
for(ConcurrentMap<String, RemotePeripheralWrapper> wrappers : peripheralWrappers.values()) {
|
||||
RemotePeripheralWrapper wrapper = wrappers.remove( name );
|
||||
if( wrapper != null ) wrapper.detach();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void attachPeripheralImpl( String periphName, IPeripheral peripheral )
|
||||
private void attachPeripheralImpl( IComputerAccess computer, ConcurrentMap<String, RemotePeripheralWrapper> peripherals, String periphName, IPeripheral peripheral )
|
||||
{
|
||||
if( !peripheralWrappers.containsKey( periphName ) && !periphName.equals( getLocalPeripheral().getConnectedName() ) )
|
||||
if( !peripherals.containsKey( periphName ) && !periphName.equals( getLocalPeripheral().getConnectedName() ) )
|
||||
{
|
||||
RemotePeripheralWrapper wrapper = new RemotePeripheralWrapper( modem, peripheral, getComputer(), periphName );
|
||||
peripheralWrappers.put( periphName, wrapper );
|
||||
RemotePeripheralWrapper wrapper = new RemotePeripheralWrapper( modem, peripheral, computer, periphName );
|
||||
peripherals.put( periphName, wrapper );
|
||||
wrapper.attach();
|
||||
}
|
||||
}
|
||||
|
||||
private String getTypeRemote( String remoteName )
|
||||
{
|
||||
|
||||
private ConcurrentMap<String, RemotePeripheralWrapper> getWrappers( IComputerAccess computer ) {
|
||||
synchronized( peripheralWrappers )
|
||||
{
|
||||
RemotePeripheralWrapper wrapper = peripheralWrappers.get( remoteName );
|
||||
if( wrapper != null )
|
||||
{
|
||||
return wrapper.getType();
|
||||
}
|
||||
return peripheralWrappers.get( computer );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String[] getMethodNamesRemote( String remoteName )
|
||||
private RemotePeripheralWrapper getWrapper( IComputerAccess computer, String remoteName )
|
||||
{
|
||||
synchronized( peripheralWrappers )
|
||||
{
|
||||
RemotePeripheralWrapper wrapper = peripheralWrappers.get( remoteName );
|
||||
if( wrapper != null )
|
||||
{
|
||||
return wrapper.getMethodNames();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Object[] callMethodRemote( String remoteName, ILuaContext context, String method, Object[] arguments ) throws LuaException, InterruptedException
|
||||
{
|
||||
RemotePeripheralWrapper wrapper;
|
||||
synchronized( peripheralWrappers )
|
||||
{
|
||||
wrapper = peripheralWrappers.get( remoteName );
|
||||
}
|
||||
if( wrapper != null )
|
||||
{
|
||||
return wrapper.callMethod( context, method, arguments );
|
||||
}
|
||||
throw new LuaException( "No peripheral: " + remoteName );
|
||||
ConcurrentMap<String, RemotePeripheralWrapper> wrappers = getWrappers( computer );
|
||||
return wrappers == null ? null : wrappers.get( remoteName );
|
||||
}
|
||||
|
||||
private static class RemotePeripheralWrapper implements IComputerAccess, IComputerOwned
|
||||
|
@ -15,8 +15,9 @@ public abstract class WirelessModemPeripheral extends ModemPeripheral
|
||||
{
|
||||
private boolean m_advanced;
|
||||
|
||||
public WirelessModemPeripheral( boolean advanced )
|
||||
public WirelessModemPeripheral( ModemState state, boolean advanced )
|
||||
{
|
||||
super( state );
|
||||
m_advanced = advanced;
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ import dan200.computercraft.api.pocket.IPocketAccess;
|
||||
import dan200.computercraft.api.pocket.IPocketUpgrade;
|
||||
import dan200.computercraft.shared.peripheral.PeripheralType;
|
||||
import dan200.computercraft.shared.peripheral.common.PeripheralItemFactory;
|
||||
import dan200.computercraft.shared.peripheral.modem.ModemState;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.item.ItemStack;
|
||||
@ -75,7 +76,8 @@ public class PocketModem implements IPocketUpgrade
|
||||
modem.setLocation( entity.getEntityWorld(), entity.posX, entity.posY, entity.posZ );
|
||||
}
|
||||
|
||||
access.setLight( modem.isActive() ? 0xBA0000 : -1 );
|
||||
ModemState state = modem.getModemState();
|
||||
if( state.pollChanged() ) access.setLight( state.isOpen() ? 0xBA0000 : -1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
package dan200.computercraft.shared.pocket.peripherals;
|
||||
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.shared.peripheral.modem.ModemState;
|
||||
import dan200.computercraft.shared.peripheral.modem.WirelessModemPeripheral;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
@ -19,7 +20,7 @@ public class PocketModemPeripheral extends WirelessModemPeripheral
|
||||
|
||||
public PocketModemPeripheral( boolean advanced )
|
||||
{
|
||||
super( advanced );
|
||||
super( new ModemState(), advanced );
|
||||
m_world = null;
|
||||
m_position = new Vec3d( 0.0, 0.0, 0.0 );
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.api.turtle.*;
|
||||
import dan200.computercraft.shared.peripheral.PeripheralType;
|
||||
import dan200.computercraft.shared.peripheral.common.PeripheralItemFactory;
|
||||
import dan200.computercraft.shared.peripheral.modem.ModemState;
|
||||
import dan200.computercraft.shared.peripheral.modem.WirelessModemPeripheral;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.block.model.IBakedModel;
|
||||
@ -17,9 +18,9 @@ import net.minecraft.client.renderer.block.model.ModelManager;
|
||||
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
@ -37,7 +38,7 @@ public class TurtleModem implements ITurtleUpgrade
|
||||
|
||||
public Peripheral( ITurtleAccess turtle, boolean advanced )
|
||||
{
|
||||
super( advanced );
|
||||
super( new ModemState(), advanced );
|
||||
m_turtle = turtle;
|
||||
}
|
||||
|
||||
@ -221,12 +222,12 @@ public class TurtleModem implements ITurtleUpgrade
|
||||
if( !turtle.getWorld().isRemote )
|
||||
{
|
||||
IPeripheral peripheral = turtle.getPeripheral( side );
|
||||
if( peripheral != null && peripheral instanceof Peripheral )
|
||||
if( peripheral instanceof Peripheral )
|
||||
{
|
||||
Peripheral modemPeripheral = (Peripheral)peripheral;
|
||||
if( modemPeripheral.pollChanged() )
|
||||
ModemState state = ((Peripheral) peripheral).getModemState();
|
||||
if( state.pollChanged() )
|
||||
{
|
||||
turtle.getUpgradeNBTData( side ).setBoolean( "active", modemPeripheral.isActive() );
|
||||
turtle.getUpgradeNBTData( side ).setBoolean( "active", state.isOpen() );
|
||||
turtle.updateUpgradeNBTData( side );
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user