1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2024-06-29 00:23:23 +00:00

Merge pull request #205 from SquidDev-CC/feature/packet-network-api

Expose wireless network in the public API
This commit is contained in:
Daniel Ratcliffe 2017-05-18 23:57:44 +01:00 committed by GitHub
commit f3c291cb4d
17 changed files with 523 additions and 284 deletions

View File

@ -11,6 +11,7 @@
import dan200.computercraft.api.filesystem.IWritableMount;
import dan200.computercraft.api.media.IMedia;
import dan200.computercraft.api.media.IMediaProvider;
import dan200.computercraft.api.network.IPacketNetwork;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.api.peripheral.IPeripheralProvider;
import dan200.computercraft.api.permissions.ITurtlePermissionProvider;
@ -736,6 +737,11 @@ public static Iterable<IPocketUpgrade> getVanillaPocketUpgrades() {
return upgrades;
}
public IPacketNetwork getWirelessNetwork()
{
return WirelessNetwork.getUniversal();
}
public static int createUniqueNumberedSaveDir( World world, String parentSubPath )
{
return IDAssigner.getNextIDFromDirectory(new File(getWorldDir(world), parentSubPath));

View File

@ -10,6 +10,7 @@
import dan200.computercraft.api.filesystem.IWritableMount;
import dan200.computercraft.api.media.IMedia;
import dan200.computercraft.api.media.IMediaProvider;
import dan200.computercraft.api.network.IPacketNetwork;
import dan200.computercraft.api.peripheral.IComputerAccess;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.api.peripheral.IPeripheralProvider;
@ -289,6 +290,27 @@ public static void registerPocketUpgrade( @Nonnull IPocketUpgrade upgrade )
}
}
/**
* Attempt to get the game-wide wireless network.
*
* @return The global wireless network, or {@code null} if it could not be fetched.
*/
public static IPacketNetwork getWirelessNetwork()
{
findCC();
if( computerCraft_getWirelessNetwork != null )
{
try
{
return (IPacketNetwork) computerCraft_getWirelessNetwork.invoke( null );
} catch (Exception e) {
// It failed;
}
}
return null;
}
// The functions below here are private, and are used to interface with the non-API ComputerCraft classes.
// Reflection is used here so you can develop your mod without decompiling ComputerCraft and including
// it in your solution, and so your mod won't crash if ComputerCraft is installed.
@ -330,6 +352,8 @@ private static void findCC()
computerCraft_registerPocketUpgrade = findCCMethod( "registerPocketUpgrade", new Class<?>[] {
IPocketUpgrade.class
} );
computerCraft_getWirelessNetwork = findCCMethod( "getWirelessNetwork", new Class<?>[] {
} );
} catch( Exception e ) {
System.out.println( "ComputerCraftAPI: ComputerCraft not found." );
} finally {
@ -365,4 +389,5 @@ private static Method findCCMethod( String name, Class<?>[] args )
private static Method computerCraft_registerMediaProvider = null;
private static Method computerCraft_registerPermissionProvider = null;
private static Method computerCraft_registerPocketUpgrade = null;
private static Method computerCraft_getWirelessNetwork = null;
}

View File

@ -0,0 +1,58 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2017. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.api.network;
import javax.annotation.Nonnull;
/**
* A packet network represents a collection of devices which can send and receive packets.
*
* @see Packet
* @see IPacketReceiver
*/
public interface IPacketNetwork
{
/**
* Add a receiver to the network.
*
* @param receiver The receiver to register to the network.
*/
void addReceiver( @Nonnull IPacketReceiver receiver );
/**
* Remove a receiver from the network.
*
* @param receiver The device to remove from the network.
*/
void removeReceiver( @Nonnull IPacketReceiver receiver );
/**
* Determine whether this network is wireless.
*
* @return Whether this network is wireless.
*/
boolean isWireless();
/**
* Submit a packet for transmitting across the network. This will route the packet through the network, sending it
* to all receivers within range (or any interdimensional ones).
*
* @param packet The packet to send.
* @see #transmitInterdimensional(Packet)
* @see IPacketReceiver#receiveSameDimension(Packet, double)
*/
void transmitSameDimension( @Nonnull Packet packet, double range );
/**
* Submit a packet for transmitting across the network. This will route the packet through the network, sending it
* to all receivers across all dimensions.
*
* @param packet The packet to send.
* @see #transmitSameDimension(Packet, double)
* @see IPacketReceiver#receiveDifferentDimension(Packet)
*/
void transmitInterdimensional( @Nonnull Packet packet );
}

View File

@ -0,0 +1,84 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2017. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.api.network;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
/**
* An object on an {@link IPacketNetwork}, capable of receiving packets.
*/
public interface IPacketReceiver
{
/**
* Get the world in which this packet receiver exists.
*
* @return The receivers's world.
*/
@Nonnull
World getWorld();
/**
* Get the position in the world at which this receiver exists.
*
* @return The receiver's position.
*/
@Nonnull
Vec3d getPosition();
/**
* Get the maximum distance this receiver can send and receive messages.
*
* When determining whether a receiver can receive a message, the largest distance of the packet and receiver is
* used - ensuring it is within range. If the packet or receiver is inter-dimensional, then the packet will always
* be received.
*
* @return The maximum distance this device can send and receive messages.
* @see #isInterdimensional()
* @see #receiveSameDimension(Packet packet, double)
* @see IPacketNetwork#transmitInterdimensional(Packet)
*/
double getRange();
/**
* Determine whether this receiver can receive packets from other dimensions.
*
* A device will receive an inter-dimensional packet if either it or the sending device is inter-dimensional.
*
* @return Whether this receiver receives packets from other dimensions.
* @see #getRange()
* @see #receiveDifferentDimension(Packet)
* @see IPacketNetwork#transmitInterdimensional(Packet)
*/
boolean isInterdimensional();
/**
* Receive a network packet from the same dimension.
*
* @param packet The packet to receive. Generally you should check that you are listening on the given channel and,
* if so, queue the appropriate modem event.
* @param distance The distance this packet has travelled from the source.
* @see Packet
* @see #getRange()
* @see IPacketNetwork#transmitSameDimension(Packet, double)
* @see IPacketNetwork#transmitInterdimensional(Packet)
*/
void receiveSameDimension( @Nonnull Packet packet, double distance );
/**
* Receive a network packet from a different dimension.
*
* @param packet The packet to receive. Generally you should check that you are listening on the given channel and,
* if so, queue the appropriate modem event.
* @see Packet
* @see IPacketNetwork#transmitInterdimensional(Packet)
* @see IPacketNetwork#transmitSameDimension(Packet, double)
* @see #isInterdimensional()
*/
void receiveDifferentDimension( @Nonnull Packet packet );
}

View File

@ -0,0 +1,42 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2017. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.api.network;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
/**
* An object on a {@link IPacketNetwork}, capable of sending packets.
*/
public interface IPacketSender
{
/**
* Get the world in which this packet sender exists.
*
* @return The sender's world.
*/
@Nonnull
World getWorld();
/**
* Get the position in the world at which this sender exists.
*
* @return The sender's position.
*/
@Nonnull
Vec3d getPosition();
/**
* Get some sort of identification string for this sender. This does not strictly need to be unique, but you
* should be able to extract some identifiable information from it.
*
* @return This device's id.
*/
@Nonnull
String getSenderID();
}

View File

@ -0,0 +1,118 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2017. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.api.network;
import com.google.common.base.Preconditions;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* Represents a packet which may be sent across a {@link IPacketNetwork}.
*
* @see IPacketSender
* @see IPacketNetwork#transmitSameDimension(Packet, double)
* @see IPacketNetwork#transmitInterdimensional(Packet)
* @see IPacketReceiver#receiveDifferentDimension(Packet)
* @see IPacketReceiver#receiveSameDimension(Packet, double)
*/
public class Packet
{
private final int m_channel;
private final int m_replyChannel;
private final Object m_payload;
private final IPacketSender m_sender;
/**
* Create a new packet, ready for transmitting across the network.
*
* @param channel The channel to send the packet along. Receiving devices should only process packets from on
* channels they are listening to.
* @param replyChannel The channel to reply on.
* @param payload The contents of this packet. This should be a "valid" Lua object, safe for queuing as an
* event or returning from a peripheral call.
* @param sender The object which sent this packet.
*/
public Packet( int channel, int replyChannel, @Nullable Object payload, @Nonnull IPacketSender sender )
{
Preconditions.checkNotNull( sender, "sender cannot be null" );
m_channel = channel;
m_replyChannel = replyChannel;
m_payload = payload;
m_sender = sender;
}
/**
* Get the channel this packet is sent along. Receivers should generally only process packets from on channels they
* are listening to.
*
* @return This packet's channel.
*/
public int getChannel()
{
return m_channel;
}
/**
* The channel to reply on. Objects which will reply should send it along this channel.
*
* @return This channel to reply on.
*/
public int getReplyChannel()
{
return m_replyChannel;
}
/**
* The actual data of this packet. This should be a "valid" Lua object, safe for queuing as an
* event or returning from a peripheral call.
*
* @return The packet's payload
*/
@Nullable
public Object getPayload()
{
return m_payload;
}
/**
* The object which sent this message.
*
* @return The sending object.
*/
@Nonnull
public IPacketSender getSender()
{
return m_sender;
}
@Override
public boolean equals( Object o )
{
if( this == o ) return true;
if( o == null || getClass() != o.getClass() ) return false;
Packet packet = (Packet) o;
if( m_channel != packet.m_channel ) return false;
if( m_replyChannel != packet.m_replyChannel ) return false;
if( m_payload != null ? !m_payload.equals( packet.m_payload ) : packet.m_payload != null ) return false;
return m_sender.equals( packet.m_sender );
}
@Override
public int hashCode()
{
int result;
result = m_channel;
result = 31 * result + m_replyChannel;
result = 31 * result + (m_payload != null ? m_payload.hashCode() : 0);
result = 31 * result + m_sender.hashCode();
return result;
}
}

View File

@ -0,0 +1,10 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2017. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
@API( owner="ComputerCraft", provides="ComputerCraft|API|Network", apiVersion="${version}" )
package dan200.computercraft.api.network;
import net.minecraftforge.fml.common.API;

View File

@ -1,18 +0,0 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2017. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.peripheral.modem;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
public interface INetwork
{
void addReceiver( IReceiver receiver );
void removeReceiver( IReceiver receiver );
void transmit( int channel, int replyChannel, Object payload, World world, Vec3d pos, double range, boolean interdimensional, Object senderObject );
boolean isWireless();
}

View File

@ -1,20 +0,0 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2017. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.peripheral.modem;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
public interface IReceiver
{
int getChannel();
World getWorld();
Vec3d getWorldPosition();
boolean isInterdimensional();
double getReceiveRange();
void receiveSameDimension( int replyChannel, Object payload, double distance, Object senderObject );
void receiveDifferentDimension( int replyChannel, Object payload, Object senderObject );
}

View File

@ -8,83 +8,25 @@
import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.network.IPacketNetwork;
import dan200.computercraft.api.network.IPacketReceiver;
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.HashMap;
import java.util.Map;
public abstract class ModemPeripheral
implements IPeripheral
{
private static class SingleChannelReceiver implements IReceiver
{
private ModemPeripheral m_owner;
private int m_channel;
public SingleChannelReceiver( ModemPeripheral owner, int channel )
{
m_owner = owner;
m_channel = channel;
}
// IReceiver implementation
@Override
public int getChannel()
{
return m_channel;
}
@Override
public World getWorld()
{
return m_owner.getWorld();
}
@Override
public Vec3d getWorldPosition()
{
return m_owner.getWorldPosition();
}
@Override
public boolean isInterdimensional()
{
return m_owner.isInterdimensional();
}
@Override
public double getReceiveRange()
{
return m_owner.getReceiveRange();
}
@Override
public void receiveSameDimension( int replyChannel, Object payload, double distance, Object senderObject )
{
if( senderObject != m_owner )
{
m_owner.receiveSameDimension( m_channel, replyChannel, payload, distance );
}
}
@Override
public void receiveDifferentDimension( int replyChannel, Object payload, Object senderObject )
{
if( senderObject != m_owner )
{
m_owner.receiveDifferentDimension( m_channel, replyChannel, payload );
}
}
}
private INetwork m_network;
implements IPeripheral, IPacketSender, IPacketReceiver
{
private IPacketNetwork m_network;
private IComputerAccess m_computer;
private final Map<Integer, IReceiver> m_channels;
private final TIntSet m_channels;
private boolean m_open;
private boolean m_changed;
@ -93,23 +35,19 @@ public ModemPeripheral()
{
m_network = null;
m_computer = null;
m_channels = new HashMap<Integer, IReceiver>();
m_channels = new TIntHashSet();
m_open = false;
m_changed = true;
}
private synchronized void setNetwork( INetwork network )
private synchronized void setNetwork( IPacketNetwork network )
{
if( m_network != network )
{
// Leave old network
if( m_network != null )
{
for( IReceiver iReceiver : m_channels.values() )
{
m_network.removeReceiver( iReceiver );
}
m_network.removeReceiver( this );
}
// Set new network
@ -118,10 +56,7 @@ private synchronized void setNetwork( INetwork network )
// Join new network
if( m_network != null )
{
for( IReceiver iReceiver : m_channels.values() )
{
m_network.addReceiver( iReceiver );
}
m_network.addReceiver( this );
}
}
}
@ -131,10 +66,6 @@ protected void switchNetwork()
setNetwork( getNetwork() );
}
protected abstract World getWorld();
protected abstract Vec3d getPosition();
public synchronized void destroy()
{
setNetwork( null );
@ -151,53 +82,45 @@ public synchronized boolean pollChanged()
}
return false;
}
protected abstract double getTransmitRange();
protected abstract boolean isInterdimensional();
public synchronized boolean isActive()
{
return (m_computer != null) && m_open;
}
public synchronized Vec3d getWorldPosition()
{
return getPosition();
}
public synchronized double getReceiveRange()
{
return getTransmitRange();
}
public void receiveSameDimension( int channel, int replyChannel, Object payload, double distance )
@Override
public void receiveSameDimension( @Nonnull Packet packet, double distance )
{
if( packet.getSender() == this ) return;
synchronized (m_channels)
{
if( m_computer != null && m_channels.containsKey( channel ) )
if( m_computer != null && m_channels.contains( packet.getChannel() ) )
{
m_computer.queueEvent( "modem_message", new Object[] {
m_computer.getAttachmentName(), channel, replyChannel, payload, distance
m_computer.getAttachmentName(), packet.getChannel(), packet.getReplyChannel(), packet.getPayload(), distance
} );
}
}
}
public void receiveDifferentDimension( int channel, int replyChannel, Object payload )
@Override
public void receiveDifferentDimension( @Nonnull Packet packet )
{
if( packet.getSender() == this ) return;
synchronized (m_channels)
{
if( m_computer != null && m_channels.containsKey( channel ) )
if( m_computer != null && m_channels.contains( packet.getChannel() ) )
{
m_computer.queueEvent( "modem_message", new Object[] {
m_computer.getAttachmentName(), channel, replyChannel, payload
m_computer.getAttachmentName(), packet.getChannel(), packet.getReplyChannel(), packet.getPayload()
} );
}
}
}
protected abstract INetwork getNetwork();
protected abstract IPacketNetwork getNetwork();
// IPeripheral implementation
@ -247,19 +170,14 @@ public Object[] callMethod( @Nonnull IComputerAccess computer, @Nonnull ILuaCont
int channel = parseChannel( arguments, 0 );
synchronized( this )
{
if( !m_channels.containsKey( channel ) )
if( !m_channels.contains( channel ) )
{
if( m_channels.size() >= 128 )
{
throw new LuaException( "Too many open channels" );
}
IReceiver receiver = new SingleChannelReceiver( this, channel );
m_channels.put( channel, receiver );
if( m_network != null )
{
m_network.addReceiver( receiver );
}
m_channels.add( channel );
if( !m_open )
{
m_open = true;
@ -275,7 +193,7 @@ public Object[] callMethod( @Nonnull IComputerAccess computer, @Nonnull ILuaCont
int channel = parseChannel( arguments, 0 );
synchronized( this )
{
boolean open = m_channels.containsKey( channel );
boolean open = m_channels.contains( channel );
return new Object[] { open };
}
}
@ -285,15 +203,8 @@ public Object[] callMethod( @Nonnull IComputerAccess computer, @Nonnull ILuaCont
int channel = parseChannel( arguments, 0 );
synchronized( this )
{
if( m_channels.containsKey( channel ) )
if( m_channels.remove( channel ) )
{
IReceiver receiver = m_channels.get( channel );
if( m_network != null )
{
m_network.removeReceiver( receiver );
}
m_channels.remove( channel );
if( m_channels.size() == 0 )
{
m_open = false;
@ -310,13 +221,6 @@ public Object[] callMethod( @Nonnull IComputerAccess computer, @Nonnull ILuaCont
{
if( m_channels.size() > 0 )
{
if( m_network != null )
{
for( IReceiver iReceiver : m_channels.values() )
{
m_network.removeReceiver( iReceiver );
}
}
m_channels.clear();
if( m_open )
@ -340,7 +244,15 @@ public Object[] callMethod( @Nonnull IComputerAccess computer, @Nonnull ILuaCont
Vec3d position = getPosition();
if( world != null && position != null && m_network != null)
{
m_network.transmit( channel, replyChannel, payload, world, position, getTransmitRange(), isInterdimensional(), this );
Packet packet = new Packet( channel, replyChannel, payload, this );
if( isInterdimensional() )
{
m_network.transmitInterdimensional( packet );
}
else
{
m_network.transmitSameDimension( packet, getRange() );
}
}
}
return null;
@ -377,10 +289,7 @@ public synchronized void detach( @Nonnull IComputerAccess computer )
{
if( m_network != null )
{
for( IReceiver iReceiver : m_channels.values() )
{
m_network.removeReceiver( iReceiver );
}
m_network.removeReceiver( this );
m_channels.clear();
m_network = null;
}
@ -394,11 +303,22 @@ public synchronized void detach( @Nonnull IComputerAccess computer )
}
}
@Override
public abstract boolean equals( IPeripheral other );
public IComputerAccess getComputer()
{
return m_computer;
}
@Nonnull
@Override
public String getSenderID()
{
if( m_computer == null )
{
return "unknown";
}
else
{
return m_computer.getID() + "_" + m_computer.getAttachmentName();
}
}
}

View File

@ -13,6 +13,8 @@
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
public class TileAdvancedModem extends TileModemBase
{
// Statics
@ -27,14 +29,16 @@ public Peripheral( TileModemBase entity )
m_entity = entity;
}
@Nonnull
@Override
public World getWorld()
{
return m_entity.getWorld();
}
@Nonnull
@Override
protected Vec3d getPosition()
public Vec3d getPosition()
{
BlockPos pos = m_entity.getPos().offset( m_entity.getDirection() );
return new Vec3d( (double)pos.getX(), (double)pos.getY(), (double)pos.getZ() );

View File

@ -12,6 +12,9 @@
import dan200.computercraft.api.filesystem.IWritableMount;
import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.network.IPacketNetwork;
import dan200.computercraft.api.network.IPacketReceiver;
import dan200.computercraft.api.network.Packet;
import dan200.computercraft.api.peripheral.IComputerAccess;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.shared.common.BlockGeneric;
@ -38,7 +41,7 @@
import java.util.*;
public class TileCable extends TileModemBase
implements INetwork
implements IPacketNetwork
{
private static final double MIN = 0.375;
private static final double MAX = 1 - MIN;
@ -65,31 +68,33 @@ public Peripheral( TileCable entity )
}
@Override
protected boolean isInterdimensional()
public boolean isInterdimensional()
{
return false;
}
@Override
protected double getTransmitRange()
public double getRange()
{
return 256.0;
}
@Override
protected INetwork getNetwork()
protected IPacketNetwork getNetwork()
{
return m_entity;
}
@Nonnull
@Override
protected World getWorld()
public World getWorld()
{
return m_entity.getWorld();
}
@Nonnull
@Override
protected Vec3d getPosition()
public Vec3d getPosition()
{
EnumFacing direction = m_entity.getDirection();
BlockPos pos = m_entity.getPos().offset( direction );
@ -233,8 +238,8 @@ public boolean equals( IPeripheral other )
// Members
private final Map<Integer, Set<IReceiver>> m_receivers;
private final Queue<Packet> m_transmitQueue;
private final Set<IPacketReceiver> m_receivers;
private final Queue<PacketWrapper> m_transmitQueue;
private boolean m_peripheralAccessAllowed;
private int m_attachedPeripheralID;
@ -248,8 +253,8 @@ public boolean equals( IPeripheral other )
public TileCable()
{
m_receivers = new HashMap<Integer, Set<IReceiver>>();
m_transmitQueue = new LinkedList<Packet>();
m_receivers = new HashSet<IPacketReceiver>();
m_transmitQueue = new LinkedList<PacketWrapper>();
m_peripheralAccessAllowed = false;
m_attachedPeripheralID = -1;
@ -564,7 +569,7 @@ public void update()
{
while( m_transmitQueue.peek() != null )
{
Packet p = m_transmitQueue.remove();
PacketWrapper p = m_transmitQueue.remove();
if( p != null )
{
dispatchPacket( p );
@ -573,53 +578,45 @@ public void update()
}
}
}
// INetwork implementation
// IPacketNetwork implementation
@Override
public void addReceiver( IReceiver receiver )
public void addReceiver( @Nonnull IPacketReceiver receiver )
{
synchronized( m_receivers )
{
int channel = receiver.getChannel();
Set<IReceiver> receivers = m_receivers.get( channel );
if( receivers == null )
{
receivers = new HashSet<IReceiver>();
m_receivers.put( channel, receivers );
}
receivers.add( receiver );
m_receivers.add( receiver );
}
}
@Override
public void removeReceiver( IReceiver receiver )
public void removeReceiver( @Nonnull IPacketReceiver receiver )
{
synchronized( m_receivers )
{
int channel = receiver.getChannel();
Set<IReceiver> receivers = m_receivers.get( channel );
if( receivers != null )
{
receivers.remove( receiver );
}
m_receivers.remove( receiver );
}
}
@Override
public void transmit( int channel, int replyChannel, Object payload, World world, Vec3d pos, double range, boolean interdimensional, Object senderObject )
public void transmitSameDimension( @Nonnull Packet packet, double range )
{
Packet p = new Packet();
p.channel = channel;
p.replyChannel = replyChannel;
p.payload = payload;
p.senderObject = senderObject;
synchronized( m_transmitQueue )
{
m_transmitQueue.offer(p);
m_transmitQueue.offer( new PacketWrapper( packet, range ) );
}
}
@Override
public void transmitInterdimensional( @Nonnull Packet packet )
{
synchronized( m_transmitQueue )
{
m_transmitQueue.offer( new PacketWrapper( packet, Double.MAX_VALUE ) );
}
}
@Override
public boolean isWireless()
{
@ -726,21 +723,28 @@ public void visit( TileCable modem, int distance )
// private stuff
// Packet sending
private class Packet
private static class PacketWrapper
{
public int channel;
public int replyChannel;
public Object payload;
public Object senderObject;
final Packet m_packet;
final double m_range;
private PacketWrapper( Packet m_packet, double m_range )
{
this.m_packet = m_packet;
this.m_range = m_range;
}
}
private void dispatchPacket( final Packet packet )
private void dispatchPacket( final PacketWrapper packet )
{
searchNetwork( new ICableVisitor() {
public void visit( TileCable modem, int distance )
{
modem.receivePacket( packet, distance );
if( distance <= packet.m_range)
{
modem.receivePacket( packet.m_packet, distance );
}
}
} );
}
@ -749,13 +753,9 @@ private void receivePacket( Packet packet, int distanceTravelled )
{
synchronized( m_receivers )
{
Set<IReceiver> receivers = m_receivers.get( packet.channel );
if( receivers != null )
for (IPacketReceiver device : m_receivers)
{
for( IReceiver receiver : receivers )
{
receiver.receiveSameDimension( packet.replyChannel, packet.payload, (double) distanceTravelled, packet.senderObject );
}
device.receiveSameDimension( packet, distanceTravelled );
}
}
}

View File

@ -33,14 +33,16 @@ public Peripheral( TileModemBase entity )
m_entity = entity;
}
@Nonnull
@Override
protected World getWorld()
public World getWorld()
{
return m_entity.getWorld();
}
@Nonnull
@Override
protected Vec3d getPosition()
public Vec3d getPosition()
{
BlockPos pos = m_entity.getPos().offset( m_entity.getDirection() );
return new Vec3d( (double)pos.getX(), (double)pos.getY(), (double)pos.getZ() );

View File

@ -7,6 +7,7 @@
package dan200.computercraft.shared.peripheral.modem;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.network.IPacketNetwork;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
@ -20,13 +21,13 @@ public WirelessModemPeripheral( boolean advanced )
}
@Override
protected boolean isInterdimensional()
public boolean isInterdimensional()
{
return m_advanced;
}
@Override
protected double getTransmitRange()
public double getRange()
{
if( m_advanced )
{
@ -56,7 +57,7 @@ protected double getTransmitRange()
}
@Override
protected INetwork getNetwork()
protected IPacketNetwork getNetwork()
{
return WirelessNetwork.getUniversal();
}

View File

@ -6,12 +6,17 @@
package dan200.computercraft.shared.peripheral.modem;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import com.google.common.base.Preconditions;
import dan200.computercraft.api.network.IPacketNetwork;
import dan200.computercraft.api.network.IPacketReceiver;
import dan200.computercraft.api.network.IPacketSender;
import dan200.computercraft.api.network.Packet;
import java.util.*;
import javax.annotation.Nonnull;
import java.util.HashSet;
import java.util.Set;
public class WirelessNetwork implements INetwork
public class WirelessNetwork implements IPacketNetwork
{
private static WirelessNetwork s_universalNetwork = null;
@ -28,68 +33,65 @@ public static void resetNetworks()
{
s_universalNetwork = null;
}
private Map<Integer, Set<IReceiver>> m_receivers;
private final Set<IPacketReceiver> m_receivers;
private WirelessNetwork()
{
m_receivers = new HashMap<Integer, Set<IReceiver>>();
m_receivers = new HashSet<IPacketReceiver>();
}
@Override
public synchronized void addReceiver( IReceiver receiver )
public synchronized void addReceiver( @Nonnull IPacketReceiver receiver )
{
int channel = receiver.getChannel();
Set<IReceiver> receivers = m_receivers.get( channel );
if( receivers == null )
{
receivers = new HashSet<IReceiver>();
m_receivers.put( channel, receivers );
}
receivers.add( receiver );
Preconditions.checkNotNull( receiver, "device cannot be null" );
m_receivers.add( receiver );
}
@Override
public synchronized void removeReceiver( IReceiver receiver )
public synchronized void removeReceiver( @Nonnull IPacketReceiver receiver )
{
int channel = receiver.getChannel();
Set<IReceiver> receivers = m_receivers.get( channel );
if( receivers != null )
{
receivers.remove( receiver );
}
Preconditions.checkNotNull( receiver, "device cannot be null" );
m_receivers.remove( receiver );
}
@Override
public synchronized void transmit( int channel, int replyChannel, Object payload, World world, Vec3d pos, double range, boolean interdimensional, Object senderObject )
public synchronized void transmitSameDimension( @Nonnull Packet packet, double range )
{
Set<IReceiver> receivers = m_receivers.get( channel );
if( receivers != null )
Preconditions.checkNotNull( packet, "packet cannot be null" );
for( IPacketReceiver device : m_receivers )
{
for( IReceiver receiver : receivers )
{
tryTransmit( receiver, replyChannel, payload, world, pos, range, interdimensional, senderObject );
}
tryTransmit( device, packet, range, false );
}
}
private void tryTransmit( IReceiver receiver, int replyChannel, Object payload, World world, Vec3d pos, double range, boolean interdimensional, Object senderObject )
@Override
public synchronized void transmitInterdimensional( @Nonnull Packet packet )
{
if( receiver.getWorld() == world )
Preconditions.checkNotNull( packet, "packet cannot be null" );
for (IPacketReceiver device : m_receivers)
{
Vec3d position = receiver.getWorldPosition();
double receiveRange = Math.max( range, receiver.getReceiveRange() ); // Ensure range is symmetrical
double distanceSq = position.squareDistanceTo( pos );
if( interdimensional || receiver.isInterdimensional() || distanceSq <= ( receiveRange * receiveRange ) )
tryTransmit( device, packet, 0, true );
}
}
private void tryTransmit( IPacketReceiver receiver, Packet packet, double range, boolean interdimensional )
{
IPacketSender sender = packet.getSender();
if( receiver.getWorld() == sender.getWorld() )
{
double receiveRange = Math.max( range, receiver.getRange() ); // Ensure range is symmetrical
double distanceSq = receiver.getPosition().squareDistanceTo( sender.getPosition() );
if( interdimensional || receiver.isInterdimensional() || distanceSq <= (receiveRange * receiveRange) )
{
receiver.receiveSameDimension( replyChannel, payload, Math.sqrt( distanceSq ), senderObject );
receiver.receiveSameDimension( packet, Math.sqrt( distanceSq ) );
}
}
else
{
if( interdimensional || receiver.isInterdimensional() )
{
receiver.receiveDifferentDimension( replyChannel, payload, senderObject );
receiver.receiveDifferentDimension( packet );
}
}
}

View File

@ -1,3 +1,8 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2017. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.pocket.peripherals;
import dan200.computercraft.api.peripheral.IPeripheral;
@ -5,11 +10,7 @@
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2017. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
import javax.annotation.Nonnull;
public class PocketModemPeripheral extends WirelessModemPeripheral
{
@ -33,14 +34,16 @@ public void setLocation( World world, double x, double y, double z )
}
}
@Nonnull
@Override
protected World getWorld()
public World getWorld()
{
return m_world;
}
@Nonnull
@Override
protected Vec3d getPosition()
public Vec3d getPosition()
{
if( m_world != null )
{

View File

@ -42,14 +42,16 @@ public Peripheral( ITurtleAccess turtle, boolean advanced )
m_turtle = turtle;
}
@Nonnull
@Override
protected World getWorld()
public World getWorld()
{
return m_turtle.getWorld();
}
@Nonnull
@Override
protected Vec3d getPosition()
public Vec3d getPosition()
{
BlockPos turtlePos = m_turtle.getPosition();
return new Vec3d(