/*
* Project Beknyou
* Copyright (c) 2010-2011 Saint Paul College, All Rights Reserved
* Redistributions in source code form must reproduce the above
* Copyright and this condition.
* The contents of this file are subject to the GNU General Public
* License, Version 2 (the "License"); you may not use this file
* except in compliance with the License. A copy of the License is
* available at http://www.opensource.org/licenses/gpl-license.php.
*
*/
package com.benkyou.client;
import com.benkyou.client.network.*;
import com.benkyou.common.messages.*;
import com.benkyou.common.Player;
import com.benkyou.client.systems.DefaultCamSystem;
import com.benkyou.client.systems.SkySystem;
import com.jme3.app.SimpleApplication;
import com.jme3.renderer.RenderManager;
import java.awt.Canvas;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme3.scene.Node;
import com.jme3.network.Client;
import java.util.ArrayList;
import com.jme3.network.Network;
import com.jme3.network.serializing.Serializer;
import com.benkyou.client.systems.LightManagmentSystem;
import com.benkyou.client.systems.TerrainSystem;
import com.benkyou.client.appstates.WorldPhysicsAppState;
import com.benkyou.client.systems.ImagingSystem;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.math.FastMath;
import com.jme3.math.Matrix3f;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.texture.Texture;
import java.util.Iterator;
/**
* This is the main game client class that should be pointed to when generating
* jar files. GameClient is comprised of various
* {@link reference com.benkyou.client.systems} to create the default world.
* All objects to be created in 3 dimensional space should be made into a System
* class and should accept a <b> GameClient</b> object in their constructor.
* all object interaction should take place through the use of the <b>GameClient</b>
* object, therefore every time a system is added to the game client appropiate
* getters and setters should be written to allow interaction amongst the systems
*
* @author Austin Allman, Adam Hess
*
*/
public class GameClient extends SimpleApplication implements Runnable {
/**
* Creates a game client and connects it to the server and port passed into
* the constructor.
* TO-DO Create a efficient loading systems for attaching various listeners to
* the client based on what the server is capable off
* @param serverLocation ip of the server location
* @param servePort The port number the server is running on
*/
private Client myClient;
private ArrayList<Player> playerList;
private DefaultCamSystem camSys;
private String playerName;
private int playerID;
private TerrainSystem terrainSystem;
private SkySystem sky;
private WorldPhysicsAppState worldPhysics;
private FormHandler formHandler;
private ArrayList<String> classList;
private ImagingSystem vncImagingSystem;
private ImagingSystem webcamImagingSystem;
private Client webcamClient;
private Client vncClient;
private boolean up;
private boolean newPlayer;
private String playerUUID;
private boolean markForPlayerSync;
private ArrayList<Player> needsToBeSynced;
private ArrayList<String> needsToBeDeleted;
public GameClient(String serverLocation, int servePort) {
this();
//Logger.getLogger("").setLevel(Level.OFF);
//Logger.getLogger(WebcamListener.class.toString()).setLevel(Level.OFF);
Serializer.registerClass(WebcamMessage.class);
Serializer.registerClass(VNCMessage.class);
Serializer.registerClass(ChatClientMessage.class);
Serializer.registerClass(LoginMessage.class);
Serializer.registerClass(PlayerMessage.class);
Serializer.registerClass(PlayerSyncMessage.class);
Serializer.registerClass(PlayerDisconectMessage.class);
up = false;
newPlayer = true;
this.needsToBeSynced = new ArrayList<Player>();
this.needsToBeDeleted = new ArrayList<String>();
markForPlayerSync = true;
//Sets up a array list to store all of the players
playerList = new ArrayList<Player>();
try {
myClient = Network.connectToServer("199.17.224.227", 6000);
//myClient = Network.connectToServer("127.0.0.1", 6000);
myClient.start();
myClient.addMessageListener(new LoginListener(this), LoginMessage.class);
myClient.addMessageListener(new ChatClientListener(this), ChatClientMessage.class);
myClient.addMessageListener(new VNCListener(this), VNCMessage.class);
//myClient.addMessageListener(new VNCListener(this), VNCMessage.class);
myClient.addMessageListener(new WebcamListener(this), WebcamMessage.class);
myClient.addMessageListener(new PlayerMessageListener(this), PlayerMessage.class, PlayerSyncMessage.class, PlayerDisconectMessage.class);
} catch (IOException ex) {
System.out.println("\n\n\n\n\n\n\nERROR CONNECTING!!!\n" + ex);
Logger.getLogger(GameClient.class.getName()).log(Level.SEVERE, null, ex);
}
}
/**
* No arguments constructor used during debugging and development to bybass
* connecting to a server
*/
public GameClient() {
formHandler = new FormHandler(this);
formHandler.initPanel();
}
/**
* Main method to begin the game client
* TO-DO parse through args for client settings such as server location and
* server port.
* @param args
*/
public static void main(String args[]) {
GameClient app = new GameClient("127.0.0.1", 6140);
//GameClient app = new GameClient();
//app.start();
}
/**
* Sends a login message to the gaming server to login to the server
* @param name name of the user
* @param password
*/
public void login(String name, char[] password, int id) {
getMyClient().send(new LoginMessage(name, password, id, null));
}
/**
*
*/
@Override
public void simpleInitApp() {
//clears the debbuging messages
guiNode.detachAllChildren();
Quaternion vncYAW090 = new Quaternion().fromAngleAxis((7*FastMath.PI)/12, new Vector3f(0,1,0));
vncImagingSystem = new ImagingSystem(this, 140f,800,600);
rootNode.attachChild(vncImagingSystem.getScreen());
vncImagingSystem.getScreen().setLocalTranslation(-255f, -10f, 115f);
vncImagingSystem.getScreen().setLocalRotation(vncYAW090);
webcamImagingSystem = new ImagingSystem(this, 140f, 800, 600);
rootNode.attachChild(webcamImagingSystem.getScreen());
// (-117.84772, -3.4392495, -5.936719)
webcamImagingSystem.getScreen().setLocalTranslation(-295f, -10f, -30f);
Quaternion YAW090 = new Quaternion().fromAngleAxis((5*FastMath.PI)/12, new Vector3f(0,1,0));
webcamImagingSystem.getScreen().setLocalRotation(YAW090);
//ImagingSystem benkyouBanner = new ImagingSystem(this, 40f, 640, 480);
//rootNode.attachChild(benkyouBanner.getScreen());
//benkyouBanner.getScreen().setLocalTranslation(-30f, 10f, -80);
//Texture banner = assetManager.loadTexture("Textures/WelcomeBanner.jpg");
//Material mat_stl = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
//mat_stl.setTexture("ColorMap", banner);
//benkyouBanner.getScreen().setMaterial(mat_stl);
/**
* Sets flycam to work in JPanel and increases camera movement speed
*/
camSys = new DefaultCamSystem(flyCam, cam);
terrainSystem = new TerrainSystem(assetManager);
rootNode.attachChild(terrainSystem.getTerrain());
//craetes a simple sky for the world
sky = new SkySystem(assetManager);
rootNode.attachChild(getSky().getSky());
//geom.setIgnoreTransform(false);
//Sets up the list to be displayed in the class list
classList = new ArrayList<String>();
//stateManager.attach(worldPhysics);
//Set up world lighting
// LightManagmentSystem lightManagment = new LightManagmentSystem(this);
//Temp lighting code to get the avatar to show up
DirectionalLight sun = new DirectionalLight();
sun.setDirection(new Vector3f(-0.1f, -0.7f, -1.0f));
rootNode.addLight(sun);
//myClient.send(new ChatClientMessage(playerName, "Has joined the server!", true, null));
addMainPlayer();
// imagingSystems.get(0).generateImageQuad();
//Setting up the world physics
worldPhysics = new WorldPhysicsAppState(this);
stateManager.attach(worldPhysics);
// worldPhysics.setupAllPlayers();
System.out.println("Up before up?");
up = true;
//this.getWorldPhysics().getPhysicsSpace().enableDebug(assetManager);
}
/**
*
* @param tpf
*/
@Override
public void simpleUpdate(float tpf) {
if (newPlayer) {
Iterator playerIterator = getPlayerList().iterator();
while (playerIterator.hasNext()) {
Player p = (Player) playerIterator.next();
System.out.println(p + " newPlayer? " + newPlayer + " updateNeeded? " + p.isAtachementUpdate());
if (p.isAtachementUpdate()) {
if (!p.isAttached()) {
p.setChatter(new Chatter(p.getName(), p.getUUID()));
this.formHandler.addNewUser(p.getChatter());
//p.getAvatar().setLocalTranslation(Player.spawnLocation);
worldPhysics.setupAllPlayers();
p.setAttached(true);
//rootNode.attachChild(p.getAvatar());
}
p.setAtachementUpdate(false);
}
if (p.isMarkedForDeletion()) {
System.out.println("Deleting player " + p);
rootNode.detachChild(p.getAvatar());
rootNode.detachChild(p);
p.detachAllChildren();
//getPlayerList().remove(p);
p.setMarkedForDeletion(false);
this.formHandler.removeUser(p.getChatter());
}
newPlayer = false;
}
if(needsToBeDeleted.size() > 0){
for(String uuid : needsToBeDeleted){
Player deletePlayer;
deletePlayer = this.getPlayerByUUID(uuid);
deletePlayer.setMarkedForDeletion(true);
}
newPlayer = true;
needsToBeDeleted.clear();
}
}
if (markForPlayerSync && up) {
processSyncMessage(needsToBeSynced);
}
}
/**
*
* @param rm
*/
@Override
public void simpleRender(RenderManager rm) {
//TODO: add render code
}
/**
*
*/
public void createGamePanel() {
java.awt.EventQueue.invokeLater(this);
formHandler = new FormHandler(this);
formHandler.createLoginPanel();
// formHandler.initPanel();
//formHandler.startGame();
}
public void run() {
}
/**
*
* @param name
* @param id
*/
public void setMainPlayer(String name, int id, String uuid) {
playerName = name;
playerID = id;
playerUUID = uuid;
}
/**
*
*/
public void addMainPlayer() {
Player p = addPlayer(getPlayerName(), getPlayerID(), getMainPlayerUUID()).setAsMainPlayer();
getCamSys().setupChaseCam(p.getAvatar(), inputManager);
}
/**
*
* @param name
* @param id
* @return
*/
public Player addPlayer(String name, int id, String uuid) {
Player p = new Player(this, id, name, uuid);
getPlayerList().add(p);
//rootNode.attachChild(playerList.get(playerList.size() - 1));
return p;
}
/**
* @return the webcamState
*/
/**
* @return the myClient
*/
public Client getMyClient() {
return myClient;
}
/**
* @return the playerList
*/
public synchronized ArrayList<Player> getPlayerList() {
return playerList;
}
/**
* @return the camSys
*/
public DefaultCamSystem getCamSys() {
return camSys;
}
/**
* @return the playerName
*/
public String getPlayerName() {
return playerName;
}
/**
* @return the playerID
*/
public int getPlayerID() {
return playerID;
}
/**
* @return the terrain
*/
public TerrainSystem getTerrainSystem() {
return terrainSystem;
}
/**
* @return the sky
*/
public SkySystem getSky() {
return sky;
}
/**
* @return the worldPhysics
*/
public WorldPhysicsAppState getWorldPhysics() {
return worldPhysics;
}
/**
*
* @return
*/
public Node getRoot() {
return rootNode;
}
/**
*
* @return
*/
public FormHandler getFormHandler() {
return formHandler;
}
/**
*
* @param name
*/
public void addChatter(Chatter chatter) {
formHandler.addNewUser(chatter);
}
/**
*
* @param name
* @param message
*/
public void addChatText(String name, String message) {
formHandler.addTextToChatBox(name, message);
}
/**
*
* @param message
*/
public void sendChatMessage(String message) {
myClient.send(new ChatClientMessage(playerName, message));
}
/**
*
* @return
*/
public boolean isUp() {
return up;
}
/**
*
* @return
*/
public ImagingSystem getVNCImagingSystem() {
return vncImagingSystem;
}
/**
*
* @return
*/
public ImagingSystem getWebcamImagingSystem() {
return webcamImagingSystem;
}
public boolean isNewPlayer() {
return newPlayer;
}
public void setNewPlayer(Boolean newPlayer) {
this.newPlayer = newPlayer;
}
public Player getPlayerByName(String name) {
Player p = null;
for (Player search : getPlayerList()) {
if (search.getName().equalsIgnoreCase(name)) {
p = search;
}
}
return p;
}
public String getMainPlayerUUID() {
return playerUUID;
}
public Player getPlayerByUUID(String uuid) {
Player returner = null;
System.out.println("Searching for player with uuid " + uuid);
ArrayList<Player> players = (ArrayList<Player>) getPlayerList().clone();
Iterator playerIterator = getPlayerList().iterator();
while (playerIterator.hasNext()) {
Player p = (Player) playerIterator.next();
System.out.println("traversing through player list " + p + " for uuid " + uuid);
if (p.getUUID().equals(uuid)) {
returner = p;
}
}
return returner;
}
public void processSyncMessage(ArrayList<Player> players) {
if (up) {
System.out.println("\n###########");
boolean alreadyAdded = false;
for (Player p : players) {
System.out.println(p);
for (Player fromList : getPlayerList()) {
if (fromList.getUUID() != null && fromList.getUUID().equalsIgnoreCase(p.getUUID())) {
alreadyAdded = true;
}
}
if (!alreadyAdded) {
syncPlayer(p);
}
alreadyAdded = false;
}
System.out.println("##########\n");
markForPlayerSync = false;
newPlayer = true;
needsToBeSynced.clear();
} else {
needsToBeSynced.addAll(players);
}
}
private void syncPlayer(Player syncMessagePlayer) {
Player syncedPlayer = new Player(this, syncMessagePlayer.getID(), syncMessagePlayer.getName(), syncMessagePlayer.getUUID());
newPlayer = true;
getPlayerList().add(syncedPlayer);
}
public void removePlayer(String uUID) {
needsToBeDeleted.add(uUID);
newPlayer = true;
}
}