summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJesse Morgan <jesse@jesterpm.net>2011-03-05 00:25:23 +0000
committerJesse Morgan <jesse@jesterpm.net>2011-03-05 00:25:23 +0000
commit6a4d24f95534d05aa526eb4b057397edcfc05067 (patch)
tree92d8b24d7336d392210f47714e7a2bbc8fa88c1e /src
parentcbb09f132ad988d4da2ded127eaea8b4248fb93f (diff)
Rough Addition of P2P code.
Diffstat (limited to 'src')
-rw-r--r--src/alden/Peer.java588
-rw-r--r--src/alden/PeerCoordinates.java53
-rw-r--r--src/alden/PeerInformation.java39
-rw-r--r--src/alden/PeerMessage.java28
-rw-r--r--src/tesseract/TesseractServer.java34
-rw-r--r--src/tesseract/TesseractUI.java29
-rw-r--r--src/tesseract/World.java83
-rw-r--r--src/tesseract/objects/PhysicalObject.java10
8 files changed, 810 insertions, 54 deletions
diff --git a/src/alden/Peer.java b/src/alden/Peer.java
new file mode 100644
index 0000000..931cc10
--- /dev/null
+++ b/src/alden/Peer.java
@@ -0,0 +1,588 @@
+package alden;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Observable;
+
+import javax.swing.SwingWorker;
+import javax.vecmath.Vector2f;
+
+
+@SuppressWarnings("restriction")
+public class Peer extends Observable {
+ /**
+ * The default port number for incoming network connections.
+ */
+ public static final int DEFAULT_SERVER_PORT = 5507;
+
+ private PeerInformation myInfo;
+ private ArrayList<PeerInformation> peers;
+ private ServerSocket serverSocket;
+ private SwingWorker<Object,Object> worker;
+
+ /**
+ * A flag indicating whether internal operation messages (useful for
+ * debugging) are logged to the console. This field may be modified at any
+ * time.
+ */
+ public boolean logEnabled;
+
+ /**
+ * Initializes a new <code>Peer</code> object. The <code>Peer</code> is
+ * not connected to a network and sends a log of internal operation
+ * messages to the console.
+ */
+ public Peer() {
+ this(true);
+ }
+
+ /**
+ * Initializes a new <code>Peer</code> object with message logging
+ * controlled by the <code>logEnabled</code> parameter. The
+ * <code>Peer</code> is not connected to a network.
+ *
+ * @param logEnabled Initial value for the <code>logEnabled</code> field.
+ */
+ public Peer(boolean logEnabled) {
+ myInfo = new PeerInformation();
+ this.logEnabled = logEnabled;
+ }
+
+ /**
+ * Establishes a new peer-to-peer network with this <code>Peer</code>
+ * as the sole member. The logical coordinates of this
+ * <code>Peer</code> are chosen randomly.
+ *
+ * @return <code>true</code> if the new network was established
+ * successfully, or <code>false</code> otherwise.
+ */
+ public boolean createNetwork() {
+ return createNetwork(new PeerCoordinates());
+ }
+
+ /**
+ * Establishes a new peer-to-peer network with this <code>Peer</code>
+ * as the sole member. The logical coordinates of this
+ * <code>Peer</code> are specified by parameter <code>location</code>.
+ *
+ * @param location Logical coordinates for this <code>Peer</code>
+ * within the new network.
+ *
+ * @return <code>true</code> if the new network was established
+ * successfully, or <code>false</code> otherwise.
+ */
+ public boolean createNetwork(PeerCoordinates location) {
+ if (serverSocket == null)
+ if (!startServer())
+ return false;
+ peers = new ArrayList<PeerInformation>();
+ myInfo.location = location;
+ logMessage("Established network @ " + myInfo.location);
+ return true;
+ }
+
+ /**
+ * Connects this <code>Peer</code> to an existing peer-to-peer network. The
+ * port number of the known <code>Peer</code> must be
+ * {@link #DEFAULT_SERVER_PORT DEFAULT_SERVER_PORT}. The logical coordinates
+ * of this <code>Peer</code> are chosen randomly.
+ *
+ * @param host
+ * The domain name or IP address of a <code>Peer</code> within
+ * the network.
+ *
+ * @return <code>true</code> if this <code>Peer</code> successfully
+ * connected to the network, or <code>false</code> otherwise.
+ */
+ public boolean connectToNetwork(String host) {
+ return connectToNetwork(host, DEFAULT_SERVER_PORT);
+ }
+
+ /**
+ * Connects this <code>Peer</code> to an existing peer-to-peer network. The
+ * port number of the known <code>Peer</code> must be
+ * {@link #DEFAULT_SERVER_PORT DEFAULT_SERVER_PORT}. The preferred logical
+ * coordinates of this <code>Peer</code> are specified by parameter
+ * <code>location</code>, but the actual logical coordinates may be chosen
+ * randomly to avoid collision with other <code>Peer</code>s.
+ *
+ * @param host
+ * The domain name or IP address of a <code>Peer</code> within
+ * the network.
+ * @param location
+ * Preferred logical coordinates for this <code>Peer</code>.
+ *
+ * @return <code>true</code> if this <code>Peer</code> successfully
+ * connected to the network, or <code>false</code> otherwise.
+ */
+ public boolean connectToNetwork(String host, PeerCoordinates location) {
+ return connectToNetwork(host, DEFAULT_SERVER_PORT, location);
+ }
+
+ /**
+ * Connects this <code>Peer</code> to an existing peer-to-peer network. The
+ * logical coordinates of this <code>Peer</code> are chosen randomly.
+ *
+ * @param host
+ * The domain name or IP address of a <code>Peer</code> within
+ * the network.
+ * @param port
+ * The port number of a <code>Peer</code> within the network.
+ *
+ * @return <code>true</code> if this <code>Peer</code> successfully
+ * connected to the network, or <code>false</code> otherwise.
+ */
+ public boolean connectToNetwork(String host, int port) {
+ try {
+ return connectToNetwork(InetAddress.getByName(host), port);
+ } catch (UnknownHostException e) {
+ System.err.println(e);
+ return false;
+ }
+ }
+
+ /**
+ * Connects this <code>Peer</code> to an existing peer-to-peer network. The
+ * preferred logical coordinates of this <code>Peer</code> are specified by
+ * parameter <code>location</code>, but the actual logical coordinates may
+ * be chosen randomly to avoid collision with other <code>Peer</code>s.
+ *
+ * @param host
+ * The domain name or IP address of a <code>Peer</code> within
+ * the network.
+ * @param port
+ * The port number of a <code>Peer</code> within the network.
+ * @param location
+ * Preferred logical coordinates for this <code>Peer</code>.
+ *
+ * @return <code>true</code> if this <code>Peer</code> successfully
+ * connected to the network, or <code>false</code> otherwise.
+ */
+ public boolean connectToNetwork(String host, int port, PeerCoordinates location) {
+ try {
+ return connectToNetwork(InetAddress.getByName(host), port, location);
+ } catch (UnknownHostException e) {
+ System.err.println(e);
+ return false;
+ }
+ }
+
+ /**
+ * Connects this <code>Peer</code> to an existing peer-to-peer network. The
+ * port number of the known <code>Peer</code> must be
+ * {@link #DEFAULT_SERVER_PORT DEFAULT_SERVER_PORT}. The logical coordinates
+ * of this <code>Peer</code> are chosen randomly.
+ *
+ * @param host
+ * The IP address of a <code>Peer</code> within the network.
+ *
+ * @return <code>true</code> if this <code>Peer</code> successfully
+ * connected to the network, or <code>false</code> otherwise.
+ */
+ public boolean connectToNetwork(InetAddress host) {
+ return connectToNetwork(host, DEFAULT_SERVER_PORT);
+ }
+
+ /**
+ * Connects this <code>Peer</code> to an existing peer-to-peer network. The
+ * port number of the known <code>Peer</code> must be
+ * {@link #DEFAULT_SERVER_PORT DEFAULT_SERVER_PORT}. The preferred logical
+ * coordinates of this <code>Peer</code> are specified by parameter
+ * <code>location</code>, but the actual logical coordinates may be chosen
+ * randomly to avoid collision with other <code>Peer</code>s.
+ *
+ * @param host
+ * The IP address of a <code>Peer</code> within the network.
+ * @param location
+ * Preferred logical coordinates for this <code>Peer</code>.
+ *
+ * @return <code>true</code> if this <code>Peer</code> successfully
+ * connected to the network, or <code>false</code> otherwise.
+ */
+ public boolean connectToNetwork(InetAddress host, PeerCoordinates location) {
+ return connectToNetwork(host, DEFAULT_SERVER_PORT, location);
+ }
+
+ /**
+ * Connects this <code>Peer</code> to an existing peer-to-peer network. The
+ * logical coordinates of this <code>Peer</code> are chosen randomly.
+ *
+ * @param host
+ * The IP address of a <code>Peer</code> within the network.
+ * @param port
+ * The port number of a <code>Peer</code> within the network.
+ *
+ * @return <code>true</code> if this <code>Peer</code> successfully
+ * connected to the network, or <code>false</code> otherwise.
+ */
+ public boolean connectToNetwork(InetAddress host, int port) {
+ return connectToNetwork(host, port, new PeerCoordinates());
+ }
+
+ /**
+ * Connects this <code>Peer</code> to an existing peer-to-peer network. The
+ * preferred logical coordinates of this <code>Peer</code> are specified by
+ * parameter <code>location</code>, but the actual logical coordinates may
+ * be chosen randomly to avoid collision with other <code>Peer</code>s.
+ *
+ * @param host
+ * The IP address of a <code>Peer</code> within the network.
+ * @param port
+ * The port number of a <code>Peer</code> within the network.
+ * @param location
+ * Preferred logical coordinates for this <code>Peer</code>.
+ *
+ * @return <code>true</code> if this <code>Peer</code> successfully connects
+ * to the network, or <code>false</code> otherwise.
+ */
+ public boolean connectToNetwork(InetAddress host, int port, PeerCoordinates location) {
+ if (serverSocket == null)
+ if (!startServer())
+ return false;
+ try {
+ Socket socket = new Socket();
+ try {
+ socket.connect(new InetSocketAddress(host, port), 10000);
+ } catch (IOException e) {
+ System.out.println("Unable to connect to " + host + ":" + port);
+ return false;
+ }
+ ObjectOutputStream socketOut = new ObjectOutputStream(socket.getOutputStream());
+ socketOut.writeObject(createJoinMessage(location));
+ socket.close();
+ while (myInfo.location == null)
+ Thread.sleep(1000);
+ logMessage("Joined network @ " + myInfo.location);
+ return true;
+ } catch (Exception e) {
+ System.err.println(e);
+ return false;
+ }
+ }
+
+ /**
+ * Disconnects this <code>Peer</code> from the peer-to-peer network.
+ */
+ public synchronized void disconnectFromNetwork() {
+ PeerMessage mesg = createAddPeersMessage();
+ mesg.peers = peers;
+ for (PeerInformation peer : peers)
+ sendMessage(mesg, peer);
+ mesg = createRemovePeersMessage();
+ for (PeerInformation peer : peers)
+ sendMessage(mesg, peer);
+ worker.cancel(true);
+ try {
+ serverSocket.close();
+ } catch (IOException e) {
+ }
+ serverSocket = null;
+ System.out.println(myInfo + " disconnected");
+ }
+
+ /**
+ * Identifies the <code>Peer</code> in the network adjacent to this
+ * <code>Peer</code> in the direction (<code>x</code>,<code>y</code>).
+ *
+ * @param x
+ * X component of a direction relative to the logical coordinates
+ * of this <code>Peer</code>.
+ * @param y
+ * Y component of a direction relative to the logical coordinates
+ * of this <code>Peer</code>.
+ *
+ * @return A <code>PeerInformation</code> object representing the adjacent
+ * <code>Peer</code>, or <code>null</code> if no adjacent
+ * <code>Peer</code> exists.
+ */
+ public synchronized PeerInformation getPeerInDirection(float x, float y) {
+ float minDistance = Float.POSITIVE_INFINITY;
+ PeerInformation minPeer = null;
+
+ Vector2f startPoint = new Vector2f(myInfo.location.getX(), myInfo.location.getY());
+ Vector2f direction = new Vector2f(x, y);
+ for (PeerInformation peer : peers) {
+ Vector2f normal = new Vector2f(peer.location.getX() - startPoint.x, peer.location.getY() - startPoint.y);
+ Vector2f midpoint = new Vector2f((peer.location.getX() + startPoint.x) / 2f, (peer.location.getY() + startPoint.y) / 2f);
+
+ float denominator = direction.dot(normal);
+ if (denominator == 0)
+ continue;
+ midpoint.scaleAdd(-1, startPoint, midpoint);
+ float distance = midpoint.dot(normal) / denominator;
+ if (distance > 0 && distance < minDistance) {
+ minDistance = distance;
+ minPeer = peer;
+ }
+ }
+
+ // Tuples for fixed boundaries: normal.x, normal.y, point.x, point.y
+ float boundaries[] = {1, 0, PeerCoordinates.MIN_X, PeerCoordinates.MIN_Y,
+ 0, 1, PeerCoordinates.MIN_X, PeerCoordinates.MIN_Y,
+ -1, 0, PeerCoordinates.MAX_X, PeerCoordinates.MAX_Y,
+ 0, -1, PeerCoordinates.MAX_X, PeerCoordinates.MAX_X};
+ for (int i = 0; i < boundaries.length; i += 4) {
+ Vector2f normal = new Vector2f(boundaries[i], boundaries[i+1]);
+ Vector2f point = new Vector2f(boundaries[i+2], boundaries[i+3]);
+
+ float denominator = direction.dot(normal);
+ if (denominator == 0)
+ continue;
+ point.scaleAdd(-1, startPoint, point);
+ float distance = point.dot(normal) / denominator;
+ if (distance > 0 && distance < minDistance)
+ return null;
+ }
+
+ return minPeer;
+ }
+
+ /**
+ * A method that sends a CollidableObject to all
+ * <code>Peer</code>s in the network.
+ *
+ * @param payload
+ * A CollidableObject.
+ *
+ * @return <code>true</code> if the message was successfully sent to all
+ * <code>Peer</code>s, or <code>false</code> otherwise.
+ */
+ public synchronized boolean sendToAllPeers(CollidableObject payload) {
+ PeerMessage message = createPayloadMessage(payload);
+ boolean success = true;
+ for (PeerInformation peer : peers)
+ success = sendMessage(message, peer) && success;
+ return success;
+ }
+
+ /**
+ * A method that sends an object to all
+ * <code>Peer</code>s in the network.
+ *
+ * @param payload
+ * An object.
+ *
+ * @return <code>true</code> if the message was successfully sent to all
+ * <code>Peer</code>s, or <code>false</code> otherwise.
+ */
+ public synchronized boolean sendExtraToAllPeers(Object payload) {
+ PeerMessage message = createExtraMessage(payload);
+ boolean success = true;
+ for (PeerInformation peer : peers)
+ success = sendMessage(message, peer) && success;
+ return success;
+ }
+
+ private boolean startServer() {
+ return startServer(DEFAULT_SERVER_PORT);
+ }
+
+ private boolean startServer(int port) {
+ while (true) {
+ try {
+ serverSocket = new ServerSocket(port);
+ } catch (IOException e) {
+ port++;
+ continue;
+ } catch (SecurityException e) {
+ System.err.println(e);
+ return false;
+ }
+ try {
+ myInfo.address = InetAddress.getLocalHost();
+ } catch (UnknownHostException e) {
+ System.err.println(e);
+ try {
+ serverSocket.close();
+ } catch (IOException e1) {
+ }
+ serverSocket = null;
+ return false;
+ }
+ myInfo.port = port;
+ break;
+ }
+
+ System.out.println("Listening on " + myInfo.address + ":" + myInfo.port);
+
+ worker = new SwingWorker<Object,Object>() {
+ protected Object doInBackground() throws Exception {
+ while (!isCancelled()) {
+ logMessage("Waiting for peer connection...");
+ try {
+ Socket socket = serverSocket.accept();
+ processConnection(socket);
+ } catch (SocketException e) {
+ } catch (IOException e) {
+ System.err.println(e);
+ }
+ }
+ return null;
+ }
+ };
+ worker.execute();
+
+ return true;
+ }
+
+ private synchronized void processConnection(Socket socket) {
+ ObjectInputStream socketIn;
+ PeerMessage mesg;
+ try {
+ socketIn = new ObjectInputStream(socket.getInputStream());
+ mesg = (PeerMessage)socketIn.readObject();
+ } catch (Exception e) {
+ System.err.println(e);
+ return;
+ }
+ if (mesg.sender.address == null || mesg.type != PeerMessage.Type.JOIN)
+ mesg.sender.address = socket.getInetAddress();
+ switch (mesg.type) {
+ case JOIN:
+ logMessage("Received JOIN message from " + mesg.sender);
+ while (true) {
+ PeerInformation peer = lookup(mesg.sender.location);
+ if (peer != myInfo) {
+ sendMessage(mesg, peer);
+ break;
+ } else if (myInfo.location.equals(mesg.sender.location))
+ mesg.sender.location.setToRandomCoordinate();
+ else {
+ sendMessage(createJoinResultMessage(mesg.sender.location), mesg.sender);
+ break;
+ }
+ }
+ break;
+ case JOIN_RESULT:
+ logMessage("Received JOIN_RESULT message from " + mesg.sender);
+ assert(peers == null);
+ peers = mesg.peers;
+ assert(myInfo.location == null);
+ myInfo.location = mesg.location;
+ PeerMessage newMesg = createAddPeersMessage();
+ for (PeerInformation peer : peers) {
+ logMessage("Adding peer " + peer);
+ sendMessage(newMesg, peer);
+ }
+ logMessage("Adding peer " + mesg.sender);
+ sendMessage(newMesg, mesg.sender);
+ peers.add(mesg.sender);
+ break;
+ case ADD_PEERS:
+ logMessage("Received ADD_PEERS message from " + mesg.sender);
+ if (!peers.contains(mesg.sender)) {
+ logMessage("Adding peer " + mesg.sender);
+ peers.add(mesg.sender);
+ }
+ for (PeerInformation peer : mesg.peers)
+ if (!peers.contains(peer) && !myInfo.equals(peer)) {
+ logMessage("Adding peer " + peer);
+ peers.add(peer);
+ }
+ break;
+ case REMOVE_PEERS:
+ logMessage("Received REMOVE_PEERS message from " + mesg.sender);
+ if (peers.contains(mesg.sender)) {
+ logMessage("Removing peer " + mesg.sender);
+ peers.remove(mesg.sender);
+ }
+ for (PeerInformation peer : mesg.peers)
+ if (peers.contains(peer)) {
+ logMessage("Removing peer " + peer);
+ peers.remove(peer);
+ }
+ break;
+
+ case PAYLOAD:
+ logMessage("Received PAYLOAD message from " + mesg.sender);
+
+ setChanged();
+ notifyObservers(mesg.payload);
+
+ break;
+
+ case EXTRA:
+ logMessage("Received EXTRA message from " + mesg.sender);
+
+ if (mesg.id != null && mesg.id.equals(PeerMessage.DEFAULT_ID)) {
+ setChanged();
+ notifyObservers(mesg.extra);
+ }
+
+ break;
+ }
+ }
+
+ private synchronized PeerInformation lookup(PeerCoordinates location) {
+ double minDistance = myInfo.location.distanceTo(location);
+ int min = -1;
+ for (int i = 0; i < peers.size(); i++) {
+ double distance = peers.get(i).location.distanceTo(location);
+ if (distance < minDistance) {
+ minDistance = distance;
+ min = i;
+ }
+ }
+ if (min == -1)
+ return myInfo;
+ return peers.get(min);
+ }
+
+ private boolean sendMessage(PeerMessage message, PeerInformation destination) {
+ try {
+ Socket socket = new Socket(destination.address, destination.port);
+ ObjectOutputStream socketOut = new ObjectOutputStream(socket.getOutputStream());
+ socketOut.writeObject(message);
+ socket.close();
+ } catch (IOException e) {
+ System.err.println(e);
+ return false;
+ }
+ return true;
+ }
+
+ private PeerMessage createJoinMessage(PeerCoordinates location) {
+ PeerInformation tmp = new PeerInformation(null, myInfo.port, location);
+ return new PeerMessage(PeerMessage.Type.JOIN, tmp);
+ }
+
+ private PeerMessage createJoinResultMessage(PeerCoordinates location) {
+ PeerMessage mesg = new PeerMessage(PeerMessage.Type.JOIN_RESULT, myInfo);
+ mesg.peers = peers;
+ mesg.location = location;
+ return mesg;
+ }
+
+ private PeerMessage createAddPeersMessage() {
+ return new PeerMessage(PeerMessage.Type.ADD_PEERS, myInfo);
+ }
+
+ private PeerMessage createRemovePeersMessage() {
+ return new PeerMessage(PeerMessage.Type.REMOVE_PEERS, myInfo);
+ }
+
+ private PeerMessage createPayloadMessage(CollidableObject payload) {
+ PeerMessage mesg = new PeerMessage(PeerMessage.Type.PAYLOAD, myInfo);
+ mesg.payload = payload;
+ return mesg;
+ }
+
+ private PeerMessage createExtraMessage(Object payload) {
+ PeerMessage mesg = new PeerMessage(PeerMessage.Type.EXTRA, myInfo);
+ mesg.extra = payload;
+ return mesg;
+ }
+
+ private void logMessage(String text) {
+ if (logEnabled)
+ System.out.println(new Date() + " -- " + text);
+ }
+}
diff --git a/src/alden/PeerCoordinates.java b/src/alden/PeerCoordinates.java
new file mode 100644
index 0000000..4d0e445
--- /dev/null
+++ b/src/alden/PeerCoordinates.java
@@ -0,0 +1,53 @@
+package alden;
+import java.io.*;
+
+public class PeerCoordinates implements Serializable {
+ private static final long serialVersionUID = 3667108226485766929L;
+ public static final int MIN_X = 0;
+ public static final int MAX_X = 99;
+ public static final int MIN_Y = 0;
+ public static final int MAX_Y = 99;
+
+ private int x;
+ private int y;
+
+ public PeerCoordinates() {
+ setToRandomCoordinate();
+ }
+
+ public PeerCoordinates(int x, int y) {
+ if (x < MIN_X || x > MAX_X || y < MIN_Y || y > MAX_Y)
+ throw new IllegalArgumentException();
+
+ this.x = x;
+ this.y = y;
+ }
+
+ public int getX() {
+ return x;
+ }
+
+ public int getY() {
+ return y;
+ }
+
+ public double distanceTo(PeerCoordinates other) {
+ return Math.sqrt((x - other.x) * (x - other.x) + (y - other.y) * (y - other.y));
+ }
+
+ public String toString() {
+ return "(" + x + ", " + y + ")";
+ }
+
+ public boolean equals(Object other) {
+ if (!(other instanceof PeerCoordinates))
+ return false;
+
+ return x == ((PeerCoordinates)other).x && y == ((PeerCoordinates)other).y;
+ }
+
+ public void setToRandomCoordinate() {
+ x = MIN_X + (int)((MAX_X - MIN_X + 1) * Math.random());
+ y = MIN_Y + (int)((MAX_Y - MIN_Y + 1) * Math.random());
+ }
+}
diff --git a/src/alden/PeerInformation.java b/src/alden/PeerInformation.java
new file mode 100644
index 0000000..3d94f11
--- /dev/null
+++ b/src/alden/PeerInformation.java
@@ -0,0 +1,39 @@
+package alden;
+import java.io.*;
+import java.net.*;
+
+public class PeerInformation implements Serializable {
+ private static final long serialVersionUID = 3667108226485766929L;
+ public static final String DEFAULT_ID = "something unique";
+
+ public InetAddress address;
+ public int port;
+ public PeerCoordinates location;
+ public String id;
+
+ public PeerInformation() {
+ id = DEFAULT_ID;
+ }
+
+ public PeerInformation(PeerInformation other) {
+ this(other.address, other.port, other.location);
+ }
+
+ public PeerInformation(InetAddress address, int port, PeerCoordinates location) {
+ this();
+ this.address = address;
+ this.port = port;
+ this.location = location;
+ }
+
+ public String toString() {
+ return address + ":" + port + " @ " + location;
+ }
+
+ public boolean equals(Object other) {
+ if (!(other instanceof PeerInformation))
+ return false;
+
+ return location.equals(((PeerInformation)other).location);
+ }
+}
diff --git a/src/alden/PeerMessage.java b/src/alden/PeerMessage.java
new file mode 100644
index 0000000..a5af7de
--- /dev/null
+++ b/src/alden/PeerMessage.java
@@ -0,0 +1,28 @@
+package alden;
+import java.io.*;
+import java.util.*;
+
+
+public class PeerMessage implements Serializable {
+ private static final long serialVersionUID = 3667108226485766929L;
+ public static final String DEFAULT_ID = "TesseractProject";
+
+ public enum Type {
+ JOIN, JOIN_RESULT, ADD_PEERS, REMOVE_PEERS, PAYLOAD, EXTRA;
+ }
+
+ public Type type;
+ public PeerInformation sender;
+ public PeerCoordinates location;
+ public ArrayList<PeerInformation> peers;
+ public CollidableObject payload;
+ public Object extra;
+ public String id;
+
+ public PeerMessage(Type type, PeerInformation sender) {
+ this.type = type;
+ this.sender = sender;
+ peers = new ArrayList<PeerInformation>();
+ this.id = DEFAULT_ID;
+ }
+}
diff --git a/src/tesseract/TesseractServer.java b/src/tesseract/TesseractServer.java
new file mode 100644
index 0000000..3518c38
--- /dev/null
+++ b/src/tesseract/TesseractServer.java
@@ -0,0 +1,34 @@
+package tesseract;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+import alden.Peer;
+
+/**
+ * This class is not part of the deliverable. This class is simply a server to
+ * help peers get into the network.
+ *
+ * @author jesse
+ */
+public class TesseractServer {
+ public static void main(String[] args) {
+ BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
+ Peer server = new Peer();
+ server.createNetwork();
+
+ try {
+ Thread.sleep(2000);
+ } catch (InterruptedException e1) {
+ }
+ while (true) {
+ System.out.print("Enter text to send: ");
+ try {
+ String input = in.readLine();
+ server.sendExtraToAllPeers(input);
+ } catch (IOException e) {
+ }
+ }
+ }
+}
diff --git a/src/tesseract/TesseractUI.java b/src/tesseract/TesseractUI.java
index 1d6a5cc..85f46a1 100644
--- a/src/tesseract/TesseractUI.java
+++ b/src/tesseract/TesseractUI.java
@@ -42,10 +42,9 @@ import tesseract.newmenu.NewParticleMenuItem;
import tesseract.newmenu.NewPlanarPolygonMenuItem;
import tesseract.newmenu.NewSurfBoardMenuItem;
import tesseract.newmenu.NewToroidMenuItem;
-import tesseract.objects.Box;
-import tesseract.objects.ChainLink2;
import tesseract.objects.PhysicalObject;
import tesseract.objects.Sphere;
+import alden.Peer;
import com.sun.j3d.utils.picking.PickCanvas;
import com.sun.j3d.utils.picking.PickResult;
@@ -84,6 +83,11 @@ public class TesseractUI extends JFrame {
private World myWorld;
/**
+ * The Peer Object
+ */
+ private Peer myPeer;
+
+ /**
* The Canvas.
*/
private Canvas3D myCanvas;
@@ -121,9 +125,12 @@ public class TesseractUI extends JFrame {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ myPeer = new Peer(true);
+
myWorld = new World(
new BoundingBox(new Point3d(-UNIT / 2, -UNIT / 2, -UNIT / 2),
- new Point3d(UNIT / 2, UNIT / 2, UNIT / 2)));
+ new Point3d(UNIT / 2, UNIT / 2, UNIT / 2)),
+ myPeer);
myCurrentObject = null;
@@ -150,20 +157,8 @@ public class TesseractUI extends JFrame {
// THIS IS WHERE OBJECTS ARE FORCED INTO EXISTANCE
// TODO: REMOVE TEST CODE
- // Lookie! Linked chainlinks!
- //myWorld.addObject(new ChainLink2(new Vector3f(0.15f, 0, 0), 1));
- //ChainLink2 o = new ChainLink2(new Vector3f(), 1);
- //o.setRotation();
-
- //myWorld.addForce(new AirDrag());
-
- //World.addObject(new Box(0.18f, 0.1f, 0.25f, new Vector3f(0.1f, -0.10f, 0)));
- //myWorld.addObject(new Box(0.18f, 0.25f, 0.1f, new Vector3f(-0.1f, 0, 0)));
- PhysicalObject s = new Sphere(.05f, new Vector3f());
- s.setAngularVelocity(new Vector3f(0, 2, 0));
- myWorld.addObject(s);
-
- //myWorld.addObject(o);
+ myPeer.connectToNetwork("127.0.0.1");
+ //myPeer.createNetwork();
}
/**
diff --git a/src/tesseract/World.java b/src/tesseract/World.java
index e898a27..eb9d26b 100644
--- a/src/tesseract/World.java
+++ b/src/tesseract/World.java
@@ -3,12 +3,13 @@ package tesseract;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
+import java.util.Observable;
+import java.util.Observer;
import javax.media.j3d.BoundingBox;
import javax.media.j3d.BoundingLeaf;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
-import javax.media.j3d.Canvas3D;
import javax.media.j3d.DirectionalLight;
import javax.media.j3d.IndexedLineArray;
import javax.media.j3d.Light;
@@ -19,20 +20,17 @@ import javax.vecmath.Point3d;
import javax.vecmath.Vector3f;
import tesseract.forces.Force;
-import tesseract.objects.PhysicalObject;
-
import tesseract.objects.HalfSpace;
-
-import com.sun.j3d.utils.picking.PickTool;
-import com.sun.j3d.utils.picking.behaviors.PickTranslateBehavior;
-import com.sun.j3d.utils.picking.behaviors.PickZoomBehavior;
+import tesseract.objects.PhysicalObject;
+import alden.CollidableObject;
+import alden.Peer;
/**
* Model of the 3D world.
*
* @author Jesse Morgan
*/
-public class World {
+public class World implements Observer {
/**
* Root element of the world.
*/
@@ -46,25 +44,17 @@ public class World {
/**
* A list of the objects in the world.
*/
- private List<PhysicalObject> myObjects;
+ private List<CollidableObject> myObjects;
/**
* A list of the forces in the world.
*/
private List<Force> myForces;
- //private List<ParticleEmitter> emitters;
- //private boolean enableEmitters;
-
- // A list of all the particles in the world
- //private List<Particle> particles;
-
- // A list of all the objects particles may collide with
- //private List<ParticleCollidableObject> collidables;
-
- // Available forces
- //private static final ParticleForceGenerator forces[] = {new Gravity(0.4f)};
- //private boolean activeForces[];
+ /**
+ * The peer object for this world.
+ */
+ private Peer myPeer;
/**
* Update rate for the world.
@@ -76,11 +66,13 @@ public class World {
*
* @param bounds The bounding box of the world.
*/
- public World(final BoundingBox bounds) {
+ public World(final BoundingBox bounds, final Peer peer) {
myVirtualWorldBounds = bounds;
-
+ myPeer = peer;
+ myPeer.addObserver(this);
+
myForces = new LinkedList<Force>();
- myObjects = new LinkedList<PhysicalObject>();
+ myObjects = new LinkedList<CollidableObject>();
// TODO: Should this go here?
myScene = new BranchGroup();
@@ -174,25 +166,30 @@ public class World {
*/
public void tick() {
// Iterate over objects in the world.
- Iterator<PhysicalObject> itr = myObjects.iterator();
+ Iterator<CollidableObject> itr = myObjects.iterator();
List<PhysicalObject> children = new LinkedList<PhysicalObject>();
while (itr.hasNext()) {
- PhysicalObject obj = itr.next();
+ CollidableObject obj = itr.next();
// Apply forces
- for (Force force : myForces) {
- force.applyForceTo(obj);
+ if (obj instanceof PhysicalObject) {
+ for (Force force : myForces) {
+ force.applyForceTo((PhysicalObject) obj);
+ }
}
// Update the object's state.
obj.updateState(1f / UPDATE_RATE);
// Spawn new objects?
- List<PhysicalObject> newChildren = obj.spawnChildren(1f / UPDATE_RATE);
- if (newChildren != null) {
- children.addAll(newChildren);
+ if (obj instanceof PhysicalObject) {
+ List<PhysicalObject> newChildren =
+ ((PhysicalObject) obj).spawnChildren(1f / UPDATE_RATE);
+ if (newChildren != null) {
+ children.addAll(newChildren);
+ }
}
// If it leaves the bounds of the world, DESTROY IT
@@ -212,7 +209,7 @@ public class World {
}
}
- // Add new children to thr world.
+ // Add new children to the world.
for (PhysicalObject obj : children) {
myScene.addChild(obj.getGroup());
}
@@ -232,7 +229,7 @@ public class World {
*
* @param obj The object to add
*/
- public void addObject(final PhysicalObject obj) {
+ public void addObject(final CollidableObject obj) {
myScene.addChild(obj.getGroup());
myObjects.add(obj);
}
@@ -261,11 +258,29 @@ public class World {
public void resetWorld() {
myForces.clear();
- for (PhysicalObject obj : myObjects) {
+ for (CollidableObject obj : myObjects) {
obj.detach();
}
myObjects.clear();
addHalfspaces();
}
+
+ /**
+ * Observer Callback.
+ * Called when a PAYLOAD or EXTRA peer message is recieved.
+ *
+ * @param peer The network peer.
+ * @param obj The object from the network.
+ */
+ public void update(final Observable peer, final Object obj) {
+ if (obj != null) {
+ if (obj instanceof PhysicalObject) {
+ addObject((PhysicalObject) obj);
+
+ } else if (obj instanceof CollidableObject) {
+ addObject((CollidableObject) obj);
+ }
+ }
+ }
}
diff --git a/src/tesseract/objects/PhysicalObject.java b/src/tesseract/objects/PhysicalObject.java
index c743e8e..d4e4e3b 100644
--- a/src/tesseract/objects/PhysicalObject.java
+++ b/src/tesseract/objects/PhysicalObject.java
@@ -2,7 +2,6 @@ package tesseract.objects;
import java.util.List;
-import javax.media.j3d.GeometryArray;
import javax.media.j3d.Node;
import javax.media.j3d.Shape3D;
import javax.media.j3d.TransformGroup;
@@ -20,12 +19,17 @@ import com.sun.j3d.utils.geometry.Primitive;
* to the transform group for it to be visible.
*
* @author Jesse Morgan
- */
+ */
public class PhysicalObject extends CollidableObject {
+ /**
+ * Generated Serial UID
+ */
+ private static final long serialVersionUID = -8418338503604062404L;
+
protected boolean collidable;
protected boolean mySelected;
-
+
public PhysicalObject(final Vector3f thePosition, final float mass) {
super(mass);
this.position.set(thePosition);