1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2024-09-28 15:08:47 +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:
SquidDev 2018-11-17 11:52:12 +00:00
parent 4bd7381827
commit 62cf921cc6
12 changed files with 224 additions and 292 deletions

View File

@ -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,14 +82,14 @@ 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()
} );
}
}
@ -137,7 +110,7 @@ public abstract class ModemPeripheral
@Override
public String[] getMethodNames()
{
return new String[] {
return new String[]{
"open",
"isOpen",
"close",
@ -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:
{
@ -277,46 +202,29 @@ 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();
}
}
}

View File

@ -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 );
}
}
}

View File

@ -25,7 +25,7 @@ public class TileAdvancedModem extends TileModemBase
public Peripheral( TileModemBase entity )
{
super( true );
super( new ModemState(), true );
m_entity = entity;
}

View File

@ -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 );
}

View File

@ -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,7 +76,7 @@ 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();
}
@ -87,14 +84,7 @@ public abstract class TileModemBase extends TilePeripheralBase
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;
}
}

View File

@ -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

View File

@ -29,7 +29,7 @@ public class TileWirelessModem extends TileModemBase
public Peripheral( TileModemBase entity )
{
super( false );
super( new ModemState(), false );
m_entity = entity;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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 );
}
}
}

View File

@ -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 );
}

View File

@ -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 );
}
}