mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2024-06-26 07:03:22 +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.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 @@ protected void switchNetwork()
|
|||
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 void receiveSameDimension( @Nonnull Packet packet, double distance )
|
|||
@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 String getType()
|
|||
{
|
||||
return "modem";
|
||||
}
|
||||
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String[] getMethodNames()
|
||||
{
|
||||
return new String[] {
|
||||
return new String[]{
|
||||
"open",
|
||||
"isOpen",
|
||||
"close",
|
||||
|
@ -146,7 +119,7 @@ public String[] getMethodNames()
|
|||
"isWireless",
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private static int parseChannel( Object[] arguments, int index ) throws LuaException
|
||||
{
|
||||
int channel = getInt( arguments, index );
|
||||
|
@ -156,7 +129,7 @@ private static int parseChannel( Object[] arguments, int index ) throws LuaExcep
|
|||
}
|
||||
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 Object[] callMethod( @Nonnull IComputerAccess computer, @Nonnull ILuaCont
|
|||
{
|
||||
// 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 Object[] callMethod( @Nonnull IComputerAccess computer, @Nonnull ILuaCont
|
|||
// 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 Object[] callMethod( @Nonnull IComputerAccess computer, @Nonnull ILuaCont
|
|||
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 Object[] callMethod( @Nonnull IComputerAccess computer, @Nonnull ILuaCont
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@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 @@ private static class Peripheral extends WirelessModemPeripheral
|
|||
|
||||
public Peripheral( TileModemBase entity )
|
||||
{
|
||||
super( true );
|
||||
super( new ModemState(), true );
|
||||
m_entity = entity;
|
||||
}
|
||||
|
||||
|
|
|
@ -97,7 +97,7 @@ protected void detachPeripheral( String name )
|
|||
|
||||
private boolean m_hasDirection = false;
|
||||
private boolean m_connectionsFormed = false;
|
||||
|
||||
|
||||
private WiredModemElement m_cable;
|
||||
private IWiredNode m_node;
|
||||
|
||||
|
@ -106,7 +106,7 @@ protected ModemPeripheral createPeripheral()
|
|||
{
|
||||
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 NBTTagCompound writeToNBT( NBTTagCompound nbttagcompound )
|
|||
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 boolean isSolidOnSide( int side )
|
|||
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 AxisAlignedBB getBounds()
|
|||
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 final void readDescription( @Nonnull NBTTagCompound nbttagcompound )
|
|||
@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 Vec3d getPosition()
|
|||
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 NBTTagCompound writeToNBT( NBTTagCompound tag )
|
|||
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 void update()
|
|||
{
|
||||
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 IPeripheral getPeripheral( EnumFacing side )
|
|||
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 @@ private static class Peripheral extends WirelessModemPeripheral
|
|||
|
||||
public Peripheral( TileModemBase entity )
|
||||
{
|
||||
super( false );
|
||||
super( new ModemState(), false );
|
||||
m_entity = entity;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
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 Object[] callMethod( @Nonnull IComputerAccess computer, @Nonnull ILuaCont
|
|||
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 Object[] callMethod( @Nonnull IComputerAccess computer, @Nonnull ILuaCont
|
|||
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 IWiredNode getNode()
|
|||
|
||||
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 void detachPeripheral( String name )
|
|||
{
|
||||
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.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 @@ else if( entity != null )
|
|||
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.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.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 @@ private static class Peripheral extends WirelessModemPeripheral
|
|||
|
||||
public Peripheral( ITurtleAccess turtle, boolean advanced )
|
||||
{
|
||||
super( advanced );
|
||||
super( new ModemState(), advanced );
|
||||
m_turtle = turtle;
|
||||
}
|
||||
|
||||
|
@ -221,12 +222,12 @@ public void update( @Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side )
|
|||
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