Add packet network API

This provides a publically accessible way of interacting with wireless
networks, hopefully extending to wired networks in the future.

Unlike the original INetwork/IReceiver system, networked devices listen
on all channels, filtering when they recieve the packet. This allows
other peripheral mods to be more flexible in their packet handling.
This commit is contained in:
SquidDev 2017-05-06 21:01:36 +01:00
parent 7f754f33bb
commit e6ef1cfadd
5 changed files with 333 additions and 0 deletions

View File

@ -0,0 +1,48 @@
/*
* 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 reachable receivers.
*
* @param packet The packet to send.
* @see IPacketReceiver#receiveDifferentDimension(Packet)
* @see IPacketReceiver#receiveSameDimension(Packet, double)
*/
void transmit( @Nonnull Packet packet );
}

View File

@ -0,0 +1,81 @@
/*
* 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 Packet#getRange()
*/
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 Packet#isInterdimensional()
*/
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 IPacketNetwork#transmit(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#transmit(Packet)
* @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,152 @@
/*
* 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#transmit(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 double m_range;
private final boolean m_interdimensional;
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, double range, boolean interdimensional, @Nonnull IPacketSender sender )
{
Preconditions.checkNotNull( sender, "sender cannot be null" );
m_channel = channel;
m_replyChannel = replyChannel;
m_payload = payload;
m_range = range;
m_interdimensional = interdimensional;
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;
}
/**
* Get the minimum distance this packet will travel.
*
* Packets may still travel further if there is a more sensitive receiver available.
*
* @return The distance this packet will travel.
* @see IPacketReceiver#getRange()
*/
public double getRange()
{
return m_range;
}
/**
* Whether this packet will travel across dimensions.
*
* Packets may still be received if there is a more sensitive receiver available.
*
* @return If this packet will travel across dimensions.
* @see IPacketReceiver#isInterdimensional()
*/
public boolean isInterdimensional()
{
return m_interdimensional;
}
/**
* 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( Double.compare( packet.m_range, m_range ) != 0 ) return false;
if( m_interdimensional != packet.m_interdimensional ) 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);
long temp = Double.doubleToLongBits( m_range );
result = 31 * result + (int) (temp ^ (temp >>> 32));
result = 31 * result + (m_interdimensional ? 1 : 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;