Yes, TestChatClient/Server works.
Here you go:
public class PlaneClient {
private Client client;
public static final String NAME = "PlaneStorm";
public static final int VERSION = 1;
public static final int PORT = 51101;
public static final int UDP_PORT = 51101;
public PlaneClient(String host) throws IOException {
int connects = 0;
initializeClasses();
try{
client = Network.connectToServer(NAME, VERSION,
host, PORT, UDP_PORT);
}catch (Exception ex){
throw new IOException("Unable to connect to server at "
+ host + "!");
}
ChatHandler handler = new ChatHandler();
client.addMessageListener(handler, PlaneMessage.class);
client.addMessageListener(handler, PlaneData.class);
client.addMessageListener(handler, Damage.class);
client.start();
while (!client.isConnected()){
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
connects++;
if (connects > 100){
throw new IOException("Unable to connect to server at "
+ host + "!");
}
}
System.out.println("Connected to server!");
}
public static void initializeClasses() {
// Doing it here means that the client code only needs to
// call our initialize.
Serializer.registerClass(PlaneData.class);
Serializer.registerClass(PlaneMessage.class);
Serializer.registerClass(Damage.class);
}
private class ChatHandler implements MessageListener<Client> {
@Override
public void messageReceived(Client source, Message m) {
if (m instanceof PlaneMessage){
planeMessage(m);
}else
if (m instanceof PlaneData){
planeData(m);
System.err.println("PlaneData!");
}else{
System.err.println("Invalid message!");
}
}
}
public void planeData(Message m){
PlaneData data = (PlaneData) m;
if (Plane.ifExists(data.name)){
Plane pl = Plane.getPlane(data.name);
pl.health = data.health;
}
System.out.println("PData");
if (data.name == null || PlaneClient.name == null){
return;
}
if (data.name.equals(PlaneClient.name)){
/*if (!Main.m.crashed){
Main.m.health = data.health;
}else{
Main.m.health = 0;
}*/
Main.m.health = data.health;
System.out.println("Data received! " + data.health);
}else{
System.out.println("Not me: " + data.name + " | " + PlaneClient.name);
}
}
public void planeMessage(Message m){
PlaneMessage chat = (PlaneMessage) m;
//System.out.println("ReceivedLoc:" + chat.getLocation());
String name = chat.getName();
if (!name.equals(PlaneClient.name)){
if (Plane.ifExists(name)){
Plane pl = Plane.getPlane(name);
pl.setLocation(chat.getLocation());
pl.setRotation(chat.getRotation());
System.out.println("Set rotation/location!");
}else{
if (!Plane.create.contains(name)){
Plane.create.add(name);
}
}
}
}
public void closeConnection(){
client.close();
}
public static String name = "Bob" + ((int) (Math.random() * 1000));
public void sendPlaneData(){
if (!started()) return;
Vector3f location = Main.m.plane.getLocalTranslation();
Quaternion rotation = Main.m.plane.getLocalRotation();
//System.out.println("Sending: " + (location == null) + "" + (rotation == null));
PlaneMessage chat = new PlaneMessage(name, location, rotation);
chat.setReliable(true);
client.send(chat);
}
public void sendData(){
if (!started()) return;
PlaneData chat = new PlaneData(name, Main.health);
chat.setReliable(true);
client.send(chat);
}
public boolean started(){
if (!client.isStarted()){
client.start();
return false;
}else{
return true;
}
}
public void sendDamage(Plane pl, Vector3f location){
if (!started()) return;
Damage dam = new Damage(pl.name, location);
dam.setReliable(true);
client.send(dam);
}
}
Server:
public class PlaneServer {
// Normally these and the initialized method would
// be in shared constants or something.
public static final String NAME = "PlaneStorm";
public static final int VERSION = 1;
public static final int PORT = 51101;
public static final int UDP_PORT = 51101;
public static void initializeClasses() {
// Doing it here means that the client code only needs to
// call our initialize.
Serializer.registerClass(PlaneMessage.class);
Serializer.registerClass(PlaneData.class);
Serializer.registerClass(Damage.class);
}
static Server server;
public static void main(String... args) throws Exception {
initializeClasses();
// Use this to test the client/server name version check
server = Network.createServer(NAME, VERSION, PORT, UDP_PORT);
server.start();
ChatHandler handler = new ChatHandler();
server.addMessageListener(handler, PlaneMessage.class);
server.addMessageListener(handler, PlaneData.class);
server.addMessageListener(handler, Damage.class);
// Keep running basically forever
while (server.isRunning()){
Thread.sleep(500);
update();
}
}
private static class ChatHandler implements MessageListener<HostedConnection> {
public ChatHandler() {
}
public void messageReceived(HostedConnection source, Message m) {
if (m instanceof PlaneMessage) {
planeMessage(source, m);
}
if (m instanceof PlaneData){
System.out.println("PlaneData!");
planeData(source, m);
}
if (m instanceof Damage){
planeDamage(source, m);
}
}
}
public static void planeData(HostedConnection source, Message m){
PlaneData data = (PlaneData) m;
if (names.containsKey(data.name)){
Player pl = names.get(data.name);
if (data.health <= 0){
pl.crashed = true;
pl.health = 0;
}
if (data.health == 3000){
pl.crashed = false;
pl.health = 3000;
}
}
}
public static void planeDamage(HostedConnection source, Message m){
Damage data = (Damage) m;
if (names.containsKey(data.name)){
Player pl = names.get(data.name);
pl.health -=50;
}
}
public static void planeMessage(HostedConnection source, Message m){
PlaneMessage pl = (PlaneMessage) m;
// Keep track of the name just in case we
// want to know it for some other reason later and it's
// a good example of session data
source.setAttribute("name", ((PlaneMessage) m).getName());
//System.out.println("Broadcasting:" + m + " reliable:" + m.isReliable());
// Just rebroadcast... the reliable flag will stay the
// same so if it came in on UDP it will go out on that too
server.broadcast(m);
if (!names.containsKey(pl.getName())){
Player player = new Player(pl.getName());
}else{
Player pla = names.get(pl.getName());
pla.location = pl.location;
pla.rotation = pl.rotation.getRotationColumn(2);
}
}
static HashMap<String, Player> names = new HashMap<String, Player>();
public static class Player{
public Vector3f location;
public Vector3f rotation; //Convert to quaternion when sending to client
public String name;
public double health = 3000;
boolean crashed = false;
int timeout = 500;
public Player(String name){
this.name = name;
names.put(name, this);
}
}
long ID = 0;
public class Plane{
public Vector3f location;
public Vector3f rotation; //Convert to quaternion when sending to client
public String name;
public double health = 3000;
boolean crashed = false;
public Plane(){
name = "Watcher" + ID;
float rand1 = (float) (2000f + (Math.random() * 6000f));
float rand2 = (float) (2000f + (Math.random() * 6000f));
Vector3f lo = new Vector3f(rand1, 700, rand2);
this.location = lo;
}
}
static int MAX_HEIGHT = 1000;
public static void update(){
System.out.println("Updating");
for (Player pl : names.values()){
pl.timeout--;
if (pl.timeout < 0){
names.remove(pl.name);
}
try{
if (pl.location.y > MAX_HEIGHT){
pl.location.y = MAX_HEIGHT;
}
if (pl.health > 0){
pl.health -= 1;
}
System.out.println("1: " + names.values().size());
PlaneData send =
new PlaneData(pl.name, pl.health);
send.setReliable(true);
server.broadcast(send);
System.out.println("2: " + send.health);
}catch (Exception e){
//Exception thrown because location == null
}
}
}
@Serializable
public static class PlaneMessage extends AbstractMessage {
private String name;
public Vector3f location;
public Quaternion rotation;
public PlaneMessage() {
}
public PlaneMessage(String name, Vector3f location, Quaternion rot) {
setName(name);
this.location = location;
this.rotation = rot;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setLocation(Vector3f location){
this.location = location;
}
public Vector3f getLocation(){
return location;
}
public void setRotation(Quaternion quat){
this.rotation = quat;
}
public Quaternion getRotation(){
return rotation;
}
}
@Serializable
public static class PlaneData extends AbstractMessage {
public String name;
public double health;
public PlaneData(){
}
public PlaneData(String name, double health) {
this.name = name;
this.health = health;
}
}
@Serializable
public static class Damage extends AbstractMessage {
public String name;
public Vector3f location;
public Damage(){
}
public Damage(String name, Vector3f location) {
this.name = name;
this.location = location;
}
}
}
Before you ask, this is more of a testing/prototype project, hence some messy code.