1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2024-06-25 22:53:22 +00:00

Various improvements to peripheral invalidation

- Abstract peripheral ID and type checking into separate class
 - Update peripherals directly rather than marking as invalid then
   fetching from the network.
 - Update peripherals when adjacent tiles change

This does result in a slightly more ugly interface, but reduces the
amount of work needed to perform partial updates of peripherals, such as
those done by neighbouring tile updates.
This commit is contained in:
SquidDev 2018-04-16 18:22:28 +01:00
parent 04f162ef25
commit 6cf32f1f74
8 changed files with 289 additions and 201 deletions

View File

@ -1,11 +1,8 @@
package dan200.computercraft.api.network.wired;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.peripheral.IPeripheral;
import javax.annotation.Nonnull;
import java.util.Collections;
import java.util.Map;
/**
* An object which may be part of a wired network.
@ -19,21 +16,6 @@
*/
public interface IWiredElement extends IWiredSender
{
/**
* Fetch the peripherals this network element provides.
*
* This is only called when initially attaching to a network and after a call to {@link IWiredNode#invalidate()}}, so
* one does not <em>need</em> to cache the return value.
*
* @return The peripherals this node provides.
* @see IWiredNode#invalidate()
*/
@Nonnull
default Map<String, IPeripheral> getPeripherals()
{
return Collections.emptyMap();
}
/**
* Called when objects on the network change. This may occur when network nodes are added or removed, or when
* peripherals change.

View File

@ -1,6 +1,9 @@
package dan200.computercraft.api.network.wired;
import dan200.computercraft.api.peripheral.IPeripheral;
import javax.annotation.Nonnull;
import java.util.Map;
/**
* A wired network is composed of one of more {@link IWiredNode}s, a set of connections between them, and a series
@ -51,7 +54,8 @@ public interface IWiredNetwork
/**
* Sever all connections this node has, removing it from this network.
*
* This should only be used on the server thread.
* This should only be used on the server thread. You should only call this on nodes
* that your network element owns.
*
* @param node The node to remove
* @return Whether this node was removed from the network. One cannot remove a node from a network where it is the
@ -62,13 +66,15 @@ public interface IWiredNetwork
boolean remove( @Nonnull IWiredNode node );
/**
* Mark this node's peripherals as having changed.
* Update the peripherals a node provides.
*
* This should only be used on the server thread.
* This should only be used on the server thread. You should only call this on nodes
* that your network element owns.
*
* @param node The node to mark as invalid.
* @param node The node to attach peripherals for.
* @param peripherals The new peripherals for this node.
* @throws IllegalArgumentException If the node is not in the network.
* @see IWiredElement#getPeripherals()
* @see IWiredNode#updatePeripherals(Map)
*/
void invalidate( @Nonnull IWiredNode node );
void updatePeripherals( @Nonnull IWiredNode node, @Nonnull Map<String, IPeripheral> peripherals );
}

View File

@ -1,8 +1,10 @@
package dan200.computercraft.api.network.wired;
import dan200.computercraft.api.network.IPacketNetwork;
import dan200.computercraft.api.peripheral.IPeripheral;
import javax.annotation.Nonnull;
import java.util.Map;
/**
* Wired nodes act as a layer between {@link IWiredElement}s and {@link IWiredNetwork}s.
@ -72,7 +74,8 @@ default boolean disconnectFrom( @Nonnull IWiredNode node )
/**
* Sever all connections this node has, removing it from this network.
*
* This should only be used on the server thread.
* This should only be used on the server thread. You should only call this on nodes
* that your network element owns.
*
* @return Whether this node was removed from the network. One cannot remove a node from a network where it is the
* only element.
@ -87,12 +90,14 @@ default boolean remove()
/**
* Mark this node's peripherals as having changed.
*
* This should only be used on the server thread.
* This should only be used on the server thread. You should only call this on nodes
* that your network element owns.
*
* @see IWiredElement#getPeripherals()
* @param peripherals The new peripherals for this node.
* @see IWiredNetwork#updatePeripherals(IWiredNode, Map)
*/
default void invalidate()
default void updatePeripherals( @Nonnull Map<String, IPeripheral> peripherals )
{
getNetwork().invalidate( this );
getNetwork().updatePeripherals( this, peripherals );
}
}

View File

@ -16,10 +16,7 @@
import dan200.computercraft.shared.peripheral.common.BlockCable;
import dan200.computercraft.shared.peripheral.common.BlockCableModemVariant;
import dan200.computercraft.shared.peripheral.common.PeripheralItemFactory;
import dan200.computercraft.shared.util.IDAssigner;
import dan200.computercraft.shared.util.PeripheralUtil;
import dan200.computercraft.shared.wired.CapabilityWiredElement;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
@ -35,7 +32,6 @@
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.File;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@ -79,16 +75,6 @@ public Vec3d getPosition()
return new Vec3d( pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5 );
}
@Nonnull
@Override
public Map<String, IPeripheral> getPeripherals()
{
IPeripheral peripheral = m_entity.getConnectedPeripheral();
return peripheral != null
? Collections.singletonMap( m_entity.getConnectedPeripheralName(), peripheral )
: Collections.emptyMap();
}
@Override
protected void attachPeripheral( String name, IPeripheral peripheral )
{
@ -105,9 +91,9 @@ protected void detachPeripheral( String name )
// Members
private boolean m_peripheralAccessAllowed;
private int m_attachedPeripheralID;
private WiredModemLocalPeripheral m_peripheral = new WiredModemLocalPeripheral();
private boolean m_destroyed;
private boolean m_destroyed = false;
private boolean m_hasDirection = false;
private boolean m_connectionsFormed = false;
@ -115,14 +101,6 @@ protected void detachPeripheral( String name )
private WiredModemElement m_cable;
private IWiredNode m_node;
public TileCable()
{
m_peripheralAccessAllowed = false;
m_attachedPeripheralID = -1;
m_destroyed = false;
}
@Override
protected ModemPeripheral createPeripheral()
{
@ -133,7 +111,7 @@ protected ModemPeripheral createPeripheral()
@Override
protected boolean canSeePeripheral( @Nonnull String peripheralName )
{
return !peripheralName.equals( getConnectedPeripheralName() );
return !peripheralName.equals( m_peripheral.getConnectedName() );
}
@Nonnull
@ -294,10 +272,29 @@ public void onNeighbourChange()
modemChanged();
connectionsChanged();
break;
return;
}
}
}
if( !world.isRemote && m_peripheralAccessAllowed )
{
if( m_peripheral.attach( world, getPos(), dir ) ) updateConnectedPeripherals();
}
}
@Override
public void onNeighbourTileEntityChange( @Nonnull BlockPos neighbour )
{
super.onNeighbourTileEntityChange( neighbour );
if( !world.isRemote && m_peripheralAccessAllowed )
{
EnumFacing facing = getDirection();
if( getPos().offset( facing ).equals( neighbour ) )
{
if( m_peripheral.attach( world, getPos(), facing ) ) updateConnectedPeripherals();
}
}
}
public AxisAlignedBB getModemBounds()
@ -400,9 +397,9 @@ public boolean onActivate( EntityPlayer player, EnumFacing side, float hitX, flo
if( !getWorld().isRemote )
{
// On server, we interacted if a peripheral was found
String oldPeriphName = getConnectedPeripheralName();
String oldPeriphName = m_peripheral.getConnectedName();
togglePeripheralAccess();
String periphName = getConnectedPeripheralName();
String periphName = m_peripheral.getConnectedName();
if( !Objects.equal( periphName, oldPeriphName ) )
{
@ -437,7 +434,7 @@ public void readFromNBT( NBTTagCompound nbttagcompound )
// Read properties
super.readFromNBT( nbttagcompound );
m_peripheralAccessAllowed = nbttagcompound.getBoolean( "peripheralAccess" );
m_attachedPeripheralID = nbttagcompound.getInteger( "peripheralID" );
m_peripheral.readNBT( nbttagcompound, "" );
}
@Nonnull
@ -447,7 +444,7 @@ public NBTTagCompound writeToNBT( NBTTagCompound nbttagcompound )
// Write properties
nbttagcompound = super.writeToNBT( nbttagcompound );
nbttagcompound.setBoolean( "peripheralAccess", m_peripheralAccessAllowed );
nbttagcompound.setInteger( "peripheralID", m_attachedPeripheralID );
m_peripheral.writeNBT( nbttagcompound, "" );
return nbttagcompound;
}
@ -476,8 +473,13 @@ public void update()
if( !m_connectionsFormed )
{
m_connectionsFormed = true;
connectionsChanged();
if( m_peripheralAccessAllowed ) m_node.invalidate();
if( m_peripheralAccessAllowed )
{
m_peripheral.attach( world, pos, m_dir );
updateConnectedPeripherals();
}
}
}
}
@ -515,15 +517,11 @@ public void modemChanged()
if( getWorld().isRemote ) return;
PeripheralType type = getPeripheralType();
if( type == PeripheralType.Cable )
{
m_attachedPeripheralID = -1;
}
if( type != PeripheralType.WiredModemWithCable && m_peripheralAccessAllowed )
{
m_peripheralAccessAllowed = false;
m_node.invalidate();
m_peripheral.detach();
m_node.updatePeripherals( Collections.emptyMap() );
markDirty();
updateAnim();
}
@ -534,61 +532,34 @@ private void togglePeripheralAccess()
{
if( !m_peripheralAccessAllowed )
{
m_peripheral.attach( world, getPos(), getDirection() );
if( !m_peripheral.hasPeripheral() ) return;
m_peripheralAccessAllowed = true;
if( getConnectedPeripheral() == null )
{
m_peripheralAccessAllowed = false;
return;
}
m_node.updatePeripherals( m_peripheral.toMap() );
}
else
{
m_peripheral.detach();
m_peripheralAccessAllowed = false;
m_node.updatePeripherals( Collections.emptyMap() );
}
updateAnim();
m_node.invalidate();
}
private String getConnectedPeripheralName()
private void updateConnectedPeripherals()
{
IPeripheral periph = getConnectedPeripheral();
if( periph != null )
Map<String, IPeripheral> peripherals = m_peripheral.toMap();
if( peripherals.isEmpty() )
{
String type = periph.getType();
if( m_attachedPeripheralID < 0 )
{
m_attachedPeripheralID = IDAssigner.getNextIDFromFile( new File(
ComputerCraft.getWorldDir( getWorld() ),
"computer/lastid_" + type + ".txt"
) );
}
return type + "_" + m_attachedPeripheralID;
// If there are no peripherals then disable access and update the display state.
m_peripheralAccessAllowed = false;
updateAnim();
}
return null;
}
private IPeripheral getConnectedPeripheral()
{
if( m_peripheralAccessAllowed )
{
if( getPeripheralType() == PeripheralType.WiredModemWithCable )
{
EnumFacing facing = getDirection();
BlockPos neighbour = getPos().offset( facing );
IPeripheral peripheral = getPeripheral( getWorld(), neighbour, facing.getOpposite() );
return peripheral == null || peripheral instanceof WiredModemPeripheral ? null : peripheral;
}
}
return null;
}
public static IPeripheral getPeripheral( World world, BlockPos pos, EnumFacing facing )
{
Block block = world.getBlockState( pos ).getBlock();
if( block == ComputerCraft.Blocks.wiredModemFull || block == ComputerCraft.Blocks.cable ) return null;
return PeripheralUtil.getPeripheral( world, pos, facing );
m_node.updatePeripherals( peripherals );
}
@Override

View File

@ -13,7 +13,6 @@
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.shared.peripheral.common.BlockCable;
import dan200.computercraft.shared.peripheral.common.TilePeripheralBase;
import dan200.computercraft.shared.util.IDAssigner;
import dan200.computercraft.shared.wired.CapabilityWiredElement;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.nbt.NBTTagCompound;
@ -24,11 +23,9 @@
import net.minecraft.util.text.TextComponentTranslation;
import net.minecraft.world.World;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.Constants;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.File;
import java.util.*;
public class TileWiredModemFull extends TilePeripheralBase
@ -76,20 +73,12 @@ public Vec3d getPosition()
BlockPos pos = m_entity.getPos();
return new Vec3d( pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5 );
}
@Nonnull
@Override
public Map<String, IPeripheral> getPeripherals()
{
return m_entity.getPeripherals();
}
}
private WiredModemPeripheral[] m_modems = new WiredModemPeripheral[6];
private boolean m_peripheralAccessAllowed = false;
private int[] m_attachedPeripheralIDs = new int[6];
private String[] m_attachedPeripheralTypes = new String[6];
private WiredModemLocalPeripheral[] m_peripherals = new WiredModemLocalPeripheral[6];
private boolean m_destroyed = false;
private boolean m_connectionsFormed = false;
@ -99,7 +88,7 @@ public Map<String, IPeripheral> getPeripherals()
public TileWiredModemFull()
{
Arrays.fill( m_attachedPeripheralIDs, -1 );
for( int i = 0; i < m_peripherals.length; i++ ) m_peripherals[i] = new WiredModemLocalPeripheral();
}
private void remove()
@ -152,18 +141,29 @@ public void onNeighbourChange()
{
if( !world.isRemote && m_peripheralAccessAllowed )
{
Map<String, IPeripheral> updated = getPeripherals();
if( updated.isEmpty() )
boolean hasChanged = false;
for( EnumFacing facing : EnumFacing.VALUES )
{
// If there are no peripherals then disable access and update the display state.
m_peripheralAccessAllowed = false;
updateAnim();
hasChanged |= m_peripherals[facing.ordinal()].attach( world, getPos(), facing );
}
// Always invalidate the node: it's more accurate than checking if the peripherals
// have changed
m_node.invalidate();
if( hasChanged ) updateConnectedPeripherals();
}
}
@Override
public void onNeighbourTileEntityChange( @Nonnull BlockPos neighbour )
{
if( !world.isRemote && m_peripheralAccessAllowed )
{
for( EnumFacing facing : EnumFacing.VALUES )
{
if( getPos().offset( facing ).equals( neighbour ) )
{
WiredModemLocalPeripheral peripheral = m_peripherals[facing.ordinal()];
if( peripheral.attach( world, getPos(), facing ) ) updateConnectedPeripherals();
}
}
}
}
@ -180,9 +180,9 @@ public boolean onActivate( EntityPlayer player, EnumFacing side, float hitX, flo
if( !getWorld().isRemote )
{
// On server, we interacted if a peripheral was found
Set<String> oldPeriphName = getPeripherals().keySet();
Set<String> oldPeriphName = getConnectedPeripheralNames();
togglePeripheralAccess();
Set<String> periphName = getPeripherals().keySet();
Set<String> periphName = getConnectedPeripheralNames();
if( !Objects.equal( periphName, oldPeriphName ) )
{
@ -220,17 +220,7 @@ public void readFromNBT( NBTTagCompound tag )
{
super.readFromNBT( tag );
m_peripheralAccessAllowed = tag.getBoolean( "peripheralAccess" );
for( int i = 0; i < m_attachedPeripheralIDs.length; i++ )
{
if( tag.hasKey( "peripheralID_" + i, Constants.NBT.TAG_ANY_NUMERIC ) )
{
m_attachedPeripheralIDs[i] = tag.getInteger( "peripheralID_" + i );
}
if( tag.hasKey( "peripheralType_" + i, Constants.NBT.TAG_STRING ) )
{
m_attachedPeripheralTypes[i] = tag.getString( "peripheralType_" + i );
}
}
for( int i = 0; i < m_peripherals.length; i++ ) m_peripherals[i].readNBT( tag, "_" + i );
}
@Nonnull
@ -239,17 +229,7 @@ public NBTTagCompound writeToNBT( NBTTagCompound tag )
{
tag = super.writeToNBT( tag );
tag.setBoolean( "peripheralAccess", m_peripheralAccessAllowed );
for( int i = 0; i < m_attachedPeripheralIDs.length; i++ )
{
if( m_attachedPeripheralIDs[i] >= 0 )
{
tag.setInteger( "peripheralID_" + i, m_attachedPeripheralIDs[i] );
}
if( m_attachedPeripheralTypes[i] != null )
{
tag.setString( "peripheralType_" + i, m_attachedPeripheralTypes[i] );
}
}
for( int i = 0; i < m_peripherals.length; i++ ) m_peripherals[i].writeNBT( tag, "_" + i );
return tag;
}
@ -294,8 +274,16 @@ public void update()
if( !m_connectionsFormed )
{
m_connectionsFormed = true;
connectionsChanged();
if( m_peripheralAccessAllowed ) m_node.invalidate();
if( m_peripheralAccessAllowed )
{
for( EnumFacing facing : EnumFacing.VALUES )
{
m_peripherals[facing.ordinal()].attach( world, getPos(), facing );
}
updateConnectedPeripherals();
}
}
}
@ -326,60 +314,63 @@ private void togglePeripheralAccess()
{
if( !m_peripheralAccessAllowed )
{
m_peripheralAccessAllowed = true;
if( getPeripherals().isEmpty() )
boolean hasAny = false;
for( EnumFacing facing : EnumFacing.VALUES )
{
m_peripheralAccessAllowed = false;
return;
WiredModemLocalPeripheral peripheral = m_peripherals[facing.ordinal()];
peripheral.attach( world, getPos(), facing );
hasAny |= peripheral.hasPeripheral();
}
if( !hasAny ) return;
m_peripheralAccessAllowed = true;
m_node.updatePeripherals( getConnectedPeripherals() );
}
else
{
m_peripheralAccessAllowed = false;
for( WiredModemLocalPeripheral peripheral : m_peripherals ) peripheral.detach();
m_node.updatePeripherals( Collections.emptyMap() );
}
updateAnim();
m_node.invalidate();
}
@Nonnull
private Map<String, IPeripheral> getPeripherals()
private Set<String> getConnectedPeripheralNames()
{
if( !m_peripheralAccessAllowed ) return Collections.emptySet();
Set<String> peripherals = new HashSet<>( 6 );
for( WiredModemLocalPeripheral m_peripheral : m_peripherals )
{
String name = m_peripheral.getConnectedName();
if( name != null ) peripherals.add( name );
}
return peripherals;
}
private Map<String, IPeripheral> getConnectedPeripherals()
{
if( !m_peripheralAccessAllowed ) return Collections.emptyMap();
Map<String, IPeripheral> peripherals = new HashMap<>( 6 );
for( EnumFacing facing : EnumFacing.VALUES )
{
BlockPos neighbour = getPos().offset( facing );
IPeripheral peripheral = TileCable.getPeripheral( getWorld(), neighbour, facing.getOpposite() );
if( peripheral != null && !(peripheral instanceof WiredModemPeripheral) )
{
String type = peripheral.getType();
int id = m_attachedPeripheralIDs[facing.ordinal()];
String oldType = m_attachedPeripheralTypes[facing.ordinal()];
if( id < 0 || !type.equals( oldType ) )
{
m_attachedPeripheralTypes[facing.ordinal()] = type;
id = m_attachedPeripheralIDs[facing.ordinal()] = IDAssigner.getNextIDFromFile( new File(
ComputerCraft.getWorldDir( getWorld() ),
"computer/lastid_" + type + ".txt"
) );
}
peripherals.put( type + "_" + id, peripheral );
}
}
for( WiredModemLocalPeripheral m_peripheral : m_peripherals ) m_peripheral.extendMap( peripherals );
return peripherals;
}
private String getCachedPeripheralName( EnumFacing facing )
private void updateConnectedPeripherals()
{
if( !m_peripheralAccessAllowed ) return null;
Map<String, IPeripheral> peripherals = getConnectedPeripherals();
if( peripherals.isEmpty() )
{
// If there are no peripherals then disable access and update the display state.
m_peripheralAccessAllowed = false;
updateAnim();
}
int id = m_attachedPeripheralIDs[facing.ordinal()];
String type = m_attachedPeripheralTypes[facing.ordinal()];
return id < 0 || type == null ? null : type + "_" + id;
m_node.updatePeripherals( peripherals );
}
// IWiredElementTile
@ -415,7 +406,7 @@ public IPeripheral getPeripheral( EnumFacing side )
@Override
protected boolean canSeePeripheral( @Nonnull String peripheralName )
{
return !peripheralName.equals( getCachedPeripheralName( side ) );
return !peripheralName.equals( m_peripherals[side.ordinal()].getConnectedName() );
}
@Nonnull

View File

@ -0,0 +1,139 @@
package dan200.computercraft.shared.peripheral.modem;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.shared.util.IDAssigner;
import dan200.computercraft.shared.util.PeripheralUtil;
import net.minecraft.block.Block;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.common.util.Constants;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.File;
import java.util.Collections;
import java.util.Map;
/**
* Represents a local peripheral exposed on the wired network
*
* This is responsible for getting the peripheral in world, tracking id and type and determining whether
* it has changed.
*/
public final class WiredModemLocalPeripheral
{
private int id;
private String type;
private IPeripheral peripheral;
/**
* Attach a new peripheral from the world
*
* @param world The world to search in
* @param origin The position to search from
* @param direction The direction so search in
* @return Whether the peripheral changed.
*/
public boolean attach( @Nonnull World world, @Nonnull BlockPos origin, @Nonnull EnumFacing direction )
{
IPeripheral oldPeripheral = this.peripheral;
IPeripheral peripheral = this.peripheral = getPeripheralFrom( world, origin, direction );
if( peripheral == null )
{
return oldPeripheral != null;
}
else
{
String type = peripheral.getType();
int id = this.id;
if( id > 0 && this.type == null )
{
// If we had an ID but no type, then just set the type.
this.type = type;
}
else if( id < 0 || !type.equals( this.type ) )
{
this.type = type;
this.id = IDAssigner.getNextIDFromFile( new File(
ComputerCraft.getWorldDir( world ),
"computer/lastid_" + type + ".txt"
) );
}
return oldPeripheral == null || !oldPeripheral.equals( peripheral );
}
}
/**
* Detach the current peripheral
*
* @return Whether the peripheral changed
*/
public boolean detach()
{
if( peripheral == null ) return false;
peripheral = null;
return true;
}
@Nullable
public String getConnectedName()
{
return peripheral != null ? type + "_" + id : null;
}
@Nullable
public IPeripheral getPeripheral()
{
return peripheral;
}
public boolean hasPeripheral()
{
return peripheral != null;
}
public void extendMap( @Nonnull Map<String, IPeripheral> peripherals )
{
if( peripheral != null ) peripherals.put( type + "_" + id, peripheral );
}
public Map<String, IPeripheral> toMap()
{
return peripheral == null
? Collections.emptyMap()
: Collections.singletonMap( type + "_" + id, peripheral );
}
public void writeNBT( @Nonnull NBTTagCompound tag, @Nonnull String suffix )
{
if( id >= 0 ) tag.setInteger( "peripheralID" + suffix, id );
if( type != null ) tag.setString( "peripheralType" + suffix, type );
}
public void readNBT( @Nonnull NBTTagCompound tag, @Nonnull String suffix )
{
id = tag.hasKey( "peripheralID" + suffix, Constants.NBT.TAG_ANY_NUMERIC )
? tag.getInteger( "peripheralID" + suffix ) : -1;
type = tag.hasKey( "peripheralType" + suffix, Constants.NBT.TAG_STRING )
? tag.getString( "peripheralType" + suffix ) : null;
}
private static IPeripheral getPeripheralFrom( World world, BlockPos pos, EnumFacing direction )
{
BlockPos offset = pos.offset( direction );
Block block = world.getBlockState( offset ).getBlock();
if( block == ComputerCraft.Blocks.wiredModemFull || block == ComputerCraft.Blocks.cable ) return null;
IPeripheral peripheral = PeripheralUtil.getPeripheral( world, offset, direction.getOpposite() );
return peripheral instanceof WiredModemPeripheral ? null : peripheral;
}
}

View File

@ -1,5 +1,7 @@
package dan200.computercraft.shared.wired;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import dan200.computercraft.api.network.Packet;
import dan200.computercraft.api.network.wired.IWiredNetwork;
import dan200.computercraft.api.network.wired.IWiredNode;
@ -283,9 +285,10 @@ public boolean remove( @Nonnull IWiredNode node )
}
@Override
public void invalidate( @Nonnull IWiredNode node )
public void updatePeripherals( @Nonnull IWiredNode node, @Nonnull Map<String, IPeripheral> newPeripherals )
{
WiredNode wired = checkNode( node );
Preconditions.checkNotNull( peripherals, "peripherals cannot be null" );
lock.writeLock().lock();
try
@ -293,11 +296,10 @@ public void invalidate( @Nonnull IWiredNode node )
if( wired.network != this ) throw new IllegalStateException( "Node is not on this network" );
Map<String, IPeripheral> oldPeripherals = wired.peripherals;
Map<String, IPeripheral> newPeripherals = wired.element.getPeripherals();
WiredNetworkChange change = WiredNetworkChange.changeOf( oldPeripherals, newPeripherals );
if( change.isEmpty() ) return;
wired.peripherals = newPeripherals;
wired.peripherals = ImmutableMap.copyOf( newPeripherals );
// Detach the old peripherals then remove them.
peripherals.keySet().removeAll( change.peripheralsRemoved().keySet() );

View File

@ -23,7 +23,6 @@
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;
@ -379,17 +378,10 @@ public void networkChanged( @Nonnull IWiredNetworkChange change )
remotePeripherals.putAll( change.peripheralsAdded() );
}
@Nonnull
@Override
public Map<String, IPeripheral> getPeripherals()
{
return Collections.unmodifiableMap( localPeripherals );
}
public NetworkElement addPeripheral( String name )
{
localPeripherals.put( name, new NetworkPeripheral() );
getNode().invalidate();
getNode().updatePeripherals( localPeripherals );
return this;
}