/*
* AQP Project
* http://http://code.google.com/p/aqp-project/
* Alexandre Gomez - Clément Troesch - Fabrice Latterner
*/
package com.aqpproject.network.game;
import com.aqpproject.game.Singleton;
import com.aqpproject.tools.Vector2D;
import com.aqpproject.visualisation.Visualisation;
import com.aqpproject.worldmodel.Control;
import com.aqpproject.worldmodel.data.Item;
import com.aqpproject.worldmodel.game.entity.*;
import com.aqpproject.worldmodel.game.state.RaceGameState;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author Alexandre, Fabrice
*/
public class NetworkThreadClient extends Thread {
public NetworkThreadClient(InetAddress adresseIP, int port) {
m_updateTime = 30;
m_lastUpdate = 0;
m_adresseIP = adresseIP;
m_port = port;
m_isGameLaunched = false;
//Liste des touches dont l'état doit être envoyé au serveur
m_listKeyboard = new ArrayList<>();
m_listKeyboard.add(Control.Z);
m_listKeyboard.add(Control.S);
m_listKeyboard.add(Control.Q);
m_listKeyboard.add(Control.D);
m_listKeyboard.add(Control.SPACE);
m_listKeyboard.add(Control.SHIFT_LEFT);
m_listKeyboard.add(Control.GP_UP);
m_listKeyboard.add(Control.GP_DOWN);
m_listKeyboard.add(Control.GP_LEFT);
m_listKeyboard.add(Control.GP_RIGHT);
m_listKeyboard.add(Control.GP_A);
m_listKeyboard.add(Control.GP_B);
m_listKeyboard.add(Control.GP_X);
m_listKeyboard.add(Control.GP_Y);
m_listKeyboard.add(Control.GP_BACK);
m_listKeyboard.add(Control.GP_R2);
m_listKeyboard.add(Control.GP_L2);
}
@Override
public void run() {
Socket echoSocket = null;
PrintWriter out = null;
BufferedReader in = null;
try {
echoSocket = new Socket(m_adresseIP, m_port);
out = new PrintWriter(echoSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
Singleton.getOptionsController().setConnexionStatus("CONNECTED");
} catch (UnknownHostException e) {
Singleton.getOptionsController().setConnexionStatus("UNKNOWN HOST");
} catch (IOException e) {
Singleton.getOptionsController().setConnexionStatus("I/O NOT AVAILABLE");
}
if (Singleton.getOptionsController().getconnexionStatus().equals("CONNECTED") && !echoSocket.isClosed()) {
String fromServer;
String fromUser;
String test = "a";
try {
while (test.equals("a")) {
if (Singleton.getNetwork().getSendName()) {
fromUser = "2;" + Singleton.getOptionsController().getPseudo();
Singleton.getNetwork().setSendName(false);
out.println(fromUser);
}
if (Singleton.getNetwork().getSendCar()) {
fromUser = "3;" + Singleton.getOptionsController().getCar();
Singleton.getNetwork().setSendCar(false);
out.println(fromUser);
}
if (Singleton.getNetwork().getSendClientDisconnexion()) {
fromUser = "4";
Singleton.getNetwork().setSendClientDisconnexion(false);
out.println(fromUser);
}
//Send inputs from user
if (m_isGameLaunched && !Singleton.getOptionsController().getFinished() && Singleton.getWorldModel().getTime() - m_lastUpdate > m_updateTime) {
fromUser = "1;" + m_name;
HashMap<Control, Boolean> keyboardState = Singleton.getInput().getKeyboardState();
for (Control c : m_listKeyboard) {
if (keyboardState.containsKey(c)) {
if (keyboardState.get(c)) {
fromUser = fromUser + ";1";
} else {
fromUser = fromUser + ";0";
}
} else {
fromUser = fromUser + ";0";
}
}
out.println(fromUser);
m_updateTime = Singleton.getWorldModel().getTime();
}
//Read server data
if (in.ready()) {
try {
if ((fromServer = in.readLine()) != null) {
processInput(fromServer);
in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
}
} catch (Exception e) {
System.out.println("error");
}
}
try {
this.sleep(15);
} catch (InterruptedException ex) {
break;
}
}
} catch (IOException ex) {
Logger.getLogger(NetworkGame.class.getName()).log(Level.SEVERE, null, ex);
}
}
try {
out.close();
in.close();
echoSocket.close();
} catch (Exception ex) {
// Logger.getLogger(NetworkGame.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void processInput(String s) {
Singleton.getNetwork().setMessage(s);
StringTokenizer st = new StringTokenizer(s, ";");
if (st.hasMoreTokens()) {
try {
int element = Integer.parseInt(st.nextToken());
switch (element) {
case 1:
initGame(s);
break;
case 2:
prepareMap(s);
break;
case 3:
updateGame(s);
break;
}
} catch (NumberFormatException e) {
System.out.println("Not a number !");
}
}
}
private void initGame(String s) {
ArrayList<String> carList = new ArrayList<>();
ArrayList<String> pseudoList = new ArrayList<>();
ArrayList<String> nameList = new ArrayList<>();
ArrayList<Integer> posList = new ArrayList<>();
int nbPlayers = 0;
String playerName = "";
StringTokenizer st = new StringTokenizer(s, ";");
st.nextToken();
nbPlayers = Integer.parseInt(st.nextToken());
playerName = st.nextToken();
for (int i = 0; i < nbPlayers; i++) {
nameList.add(st.nextToken());
carList.add(st.nextToken());
pseudoList.add(st.nextToken());
posList.add(Integer.parseInt(st.nextToken()));
}
Singleton.getWorldModel().setNextState(new RaceGameState("MULTI", playerName, Singleton.getOptionsController().getMap(), posList, pseudoList, nameList, carList));
m_isGameLaunched = true;
}
private void prepareMap(String s) {
StringTokenizer st = new StringTokenizer(s, ";");
st.nextToken();
Singleton.getOptionsController().setMap(st.nextToken());
}
private void updateGame(String s) {
StringTokenizer st = new StringTokenizer(s, ";");
st.nextToken();
for (int i = 0; i < ((RaceGameState) Singleton.getWorldModel().getState()).getCars().size(); i++) {
String actorName = st.nextToken();
float posX = Float.parseFloat(st.nextToken());
float posY = Float.parseFloat(st.nextToken());
float rot = Float.parseFloat(st.nextToken());
float velX = Float.parseFloat(st.nextToken());
float velY = Float.parseFloat(st.nextToken());
boolean isPoweredDown = Boolean.parseBoolean(st.nextToken());
boolean isBoosted = Boolean.parseBoolean(st.nextToken());
boolean isColliding = Boolean.parseBoolean(st.nextToken());
float pointX = Float.parseFloat(st.nextToken());
float pointY = Float.parseFloat(st.nextToken());
boolean isStatic = Boolean.parseBoolean(st.nextToken());
String type = st.nextToken();
int cpt = Integer.parseInt(st.nextToken());
try {
Item it = ((RaceGameState) Singleton.getWorldModel().getState()).getCars().get(i).getInventory().peek();
if (!type.equals("null")) {
if (it == null) {
((RaceGameState) Singleton.getWorldModel().getState()).getCars().get(i).getInventory().setNextItem(type, cpt);
}
} else {
((RaceGameState) Singleton.getWorldModel().getState()).getCars().get(i).getInventory().deleteAll();
((RaceGameState) Singleton.getWorldModel().getState()).getCars().get(i).getInventory().updateMiniatures();
}
((RaceGameState) Singleton.getWorldModel().getState()).getCars().get(i).setSparklingPosition(new Vector2D(pointX, pointY), isStatic);
((RaceGameState) Singleton.getWorldModel().getState()).getCars().get(i).setColliding(isColliding);
Singleton.getPhysics().setLinearVelocity(actorName, new Vector2D(velX, velY));
Singleton.getPhysics().setBodyPosition(actorName, new Vector2D(posX, posY));
Singleton.getPhysics().setRotation(actorName, rot);
if (!((RaceGameState) Singleton.getWorldModel().getState()).getCars().get(i).getPowerDown() && isPoweredDown) {
((RaceGameState) Singleton.getWorldModel().getState()).getCars().get(i).applyPowerDown();
} else if (((RaceGameState) Singleton.getWorldModel().getState()).getCars().get(i).getPowerDown() && !isPoweredDown) {
((RaceGameState) Singleton.getWorldModel().getState()).getCars().get(i).deletePowerDown();
}
if (!((RaceGameState) Singleton.getWorldModel().getState()).getCars().get(i).getBoost() && isBoosted) {
((RaceGameState) Singleton.getWorldModel().getState()).getCars().get(i).applyBoost();
} else if (((RaceGameState) Singleton.getWorldModel().getState()).getCars().get(i).getBoost() && !isBoosted) {
((RaceGameState) Singleton.getWorldModel().getState()).getCars().get(i).deleteBoost();
}
} catch (NullPointerException e) {
System.out.println("error update actor");
}
}
//Update missilesingleton.getWorldModel().
Set<String> currentItemList = ((RaceGameState) Singleton.getWorldModel().getState()).getWorldEntities().keySet();
ArrayList<String> newItemList = new ArrayList();
ArrayList<String> currentMissileList = new ArrayList();
ArrayList<String> currentBombList = new ArrayList();
ArrayList<String> currentMineList = new ArrayList();
ArrayList<String> currentDynamicObjectList = new ArrayList();
for (String it : currentItemList) {
if (it.startsWith("Missile_") && !it.endsWith("_Explosion")) {
currentMissileList.add(it);
} else if (it.startsWith("Bomb_") && !it.endsWith("_Explosion")) {
currentBombList.add(it);
} else if (it.startsWith("Mine_") && !it.endsWith("_Explosion")) {
currentMineList.add(it);
} else if (it.startsWith("dynamic")) {
currentDynamicObjectList.add(it);
}
}
int cptMissiles = Integer.parseInt(st.nextToken());
for (int i = 0; i < cptMissiles; i++) {
String missileName = st.nextToken();
Float posX = Float.parseFloat(st.nextToken());
Float posY = Float.parseFloat(st.nextToken());
Float rot = Float.parseFloat(st.nextToken());
String emitter = st.nextToken();
newItemList.add(missileName);
if (((RaceGameState) Singleton.getWorldModel().getState()).getWorldEntities().containsKey(missileName)) {
Singleton.getPhysics().setBodyPosition(missileName, new Vector2D(posX, posY));
Singleton.getPhysics().setRotation(missileName, rot);
} else {
((RaceGameState) Singleton.getWorldModel().getState()).getWorldEntities().put(missileName, new WEMissile(missileName, new Vector2D(posX, posY), rot, (WECar) ((RaceGameState) Singleton.getWorldModel().getState()).getWorldEntities().get(emitter), ((RaceGameState) Singleton.getWorldModel().getState())));
}
}
int cptBomb = Integer.parseInt(st.nextToken());
for (int i = 0; i < cptBomb; i++) {
String bombName = st.nextToken();
Float posX = Float.parseFloat(st.nextToken());
Float posY = Float.parseFloat(st.nextToken());
Float rot = Float.parseFloat(st.nextToken());
String emitter = st.nextToken();
newItemList.add(bombName);
if (((RaceGameState) Singleton.getWorldModel().getState()).getWorldEntities().containsKey(bombName)) {
Singleton.getPhysics().setBodyPosition(bombName, new Vector2D(posX, posY));
Singleton.getPhysics().setRotation(bombName, rot);
//Singleton.getVisualisation().updateActor(missileName, posX, posY, rot);
} else {
((RaceGameState) Singleton.getWorldModel().getState()).getWorldEntities().put(bombName, new WEBomb(bombName, new Vector2D(posX, posY), rot, (WECar) ((RaceGameState) Singleton.getWorldModel().getState()).getWorldEntities().get(emitter), ((RaceGameState) Singleton.getWorldModel().getState())));
}
}
int cptMine = Integer.parseInt(st.nextToken());
for (int i = 0; i < cptMine; i++) {
String mineName = st.nextToken();
Float posX = Float.parseFloat(st.nextToken());
Float posY = Float.parseFloat(st.nextToken());
Float rot = Float.parseFloat(st.nextToken());
newItemList.add(mineName);
if (!((RaceGameState) Singleton.getWorldModel().getState()).getWorldEntities().containsKey(mineName)) {
((RaceGameState) Singleton.getWorldModel().getState()).getWorldEntities().put(mineName, new WEMine(mineName, new Vector2D(posX, posY), rot, null, ((RaceGameState) Singleton.getWorldModel().getState())));
}
}
int cptDynamicObjects = Integer.parseInt(st.nextToken());
for (int i = 0; i < cptDynamicObjects; i++) {
String dynamicObjectName = st.nextToken();
Float posX = Float.parseFloat(st.nextToken());
Float posY = Float.parseFloat(st.nextToken());
Float rot = Float.parseFloat(st.nextToken());
newItemList.add(dynamicObjectName);
if (((RaceGameState) Singleton.getWorldModel().getState()).getWorldEntities().containsKey(dynamicObjectName)) {
Singleton.getPhysics().setBodyPosition(dynamicObjectName, new Vector2D(posX, posY));
Singleton.getPhysics().setRotation(dynamicObjectName, rot);
//Singleton.getVisualisation().updateActor(missileName, posX, posY, rot);
} else {
//rien
}
}
boolean isTrolling = Boolean.parseBoolean(st.nextToken());
String emitter = st.nextToken();
if (isTrolling) {
((RaceGameState) Singleton.getWorldModel().getState()).activateTroll((WECar) ((RaceGameState) Singleton.getWorldModel().getState()).getWorldEntities().get(emitter));
}
//Finish list
int cptFinish = Integer.parseInt(st.nextToken());
ArrayList<String> nameList = new ArrayList<>();
ArrayList<Long> timeList = new ArrayList<>();
for (int i = 0; i < cptFinish; i++) {
nameList.add(st.nextToken());
timeList.add(Long.parseLong(st.nextToken()));
}
((RaceGameState) Singleton.getWorldModel().getState()).setFinishNames(nameList);
((RaceGameState) Singleton.getWorldModel().getState()).setFinishTimes(timeList);
//Suppression des items
for (String str : currentMissileList) {
if (newItemList.indexOf(str) < 0) {
((WEMissile) ((RaceGameState) Singleton.getWorldModel().getState()).getWorldEntities().get(str)).startStaticContact(new Vector2D(0, 0), new Vector2D(0, 0));
// Singleton.getVisualisation().deleteActor(str,false);
// ((RaceGameState)Singleton.getWorldModel().getState()).getWorldEntities().get(str).setActive(false);
}
}
for (String str : currentBombList) {
if (newItemList.indexOf(str) < 0) {
((WEBomb) ((RaceGameState) Singleton.getWorldModel().getState()).getWorldEntities().get(str)).explode();
// ((WEBomb)((RaceGameState)Singleton.getWorldModel().getState()).getWorldEntities().get(str)).startStaticContact(new Vector2D(0,0), new Vector2D(0,0));
}
}
for (String str : currentMineList) {
if (newItemList.indexOf(str) < 0) {
((WEMine) ((RaceGameState) Singleton.getWorldModel().getState()).getWorldEntities().get(str)).explode();
}
}
for (String str : currentDynamicObjectList) {
if (newItemList.indexOf(str) < 0) {
((RaceGameState) Singleton.getWorldModel().getState()).getWorldEntities().get(str).setActive(false);
}
}
}
private InetAddress m_adresseIP;
private int m_port;
private String m_name;
private ArrayList<Control> m_listKeyboard;
private boolean m_isGameLaunched;
private long m_updateTime;
private long m_lastUpdate;
}