package WarTug;
//This includes everything in the server side game logic
import java.io.IOException;
import java.util.ArrayList;
import javax.management.timer.Timer;
import com.esotericsoftware.kryonet.Connection;
import com.esotericsoftware.kryonet.Listener;
import com.esotericsoftware.kryonet.Server;
import WarTug.Network.WarTugConnection;
import WarTug.Network.RegisterName;
public class WarTugServer implements Runnable {
Server server; //Server listening for client connections
public boolean end = false;
public int numPlayers;
public long start = 0;
private final long tickLength = 8000;
private long currTickTime = 0;
private ArrayList<SimpleUnit> allUnits = new ArrayList<SimpleUnit>(); //Holds all units tracked server side
private Player[] players = new Player[2];
private int currWave = 0;
public WarTugServer () throws IOException {
//Set-up Server here
server = new Server() {
protected Connection newConnection () {
// By providing our own connection implementation, we can store per
// connection state without a connection ID to state look up.
return new WarTugConnection();
}
};
// For consistency, the classes to be sent over the network are
// registered by the same method for both the client and server.
Network.register(server);
server.addListener(new Listener() {
public void received (Connection c, Object object) {
// We know all connections for this server are actually ChatConnections.
WarTugConnection connection = (WarTugConnection)c;
if (object instanceof RegisterName) {
if (numPlayers==2) return; //Only let two players on server
if (connection.name != null) return; // Ignore the object if the name is invalid.
String name = ((RegisterName)object).name;
if (name == null) return; //Ignore if no name
name = name.trim();
if (name.length() == 0) return;
// Store the name on the connection.
connection.name = name;
connection.playerNum = numPlayers; //Give player a player number based upon order of connection
players[numPlayers] = new Player(numPlayers);
synchronized(allUnits) {
allUnits.add(new UnitTreeOfLife(numPlayers));
}
//increment number of players
numPlayers++;
return;
}
if (object instanceof SimpleUnit) {
//Don't know if this will ever happen...
return;
}
if (object instanceof Garden) {
Garden g = (Garden) object;
if (g!=null) {
synchronized (players) {
players[g.playerNumber].garden = g;
}
}
}
if (object instanceof Network.ClearRequest) {
if (object != null) {
synchronized(allUnits) {
for (SimpleUnit u : allUnits) {
if (u.unitType != UnitType.treeOfLife)
u.dealDamage(1000);
}
}
}
}
}
public void disconnected (Connection c) {
//Need to decide what to do if a client dcs
}
});
server.bind(Network.port); //Binds all of the server listeners to a port
server.start();
}
public void run() {
//Here is where we have the main server game loop
while (!end && numPlayers<2)
{
Thread.yield();
}
start = System.currentTimeMillis();
while (!end){
long delta = System.currentTimeMillis() - start;
start = System.currentTimeMillis();
try {
Thread.sleep(100); //TODO:Perhaps make new function to mimic the effects of Display.sync(100), it might have to use time stamps, though...
} catch (InterruptedException e) {
e.printStackTrace();
}
if (isUnitSpawnTick(delta)) {
spawnUnits();
if (currWave % 3 == 0) {
server.sendToAllTCP(new Integer(1));
}
synchronized (players) {
for (Player p : players)
{
server.sendToAllTCP(p.garden);
}
}
}
//Send units to the clients, TODO:Maybe have this in unit manager.
//Pro: looping through units is done in unit manager, cleaner code.
//Con: Must pass server to unit manager
ArrayList<SimpleUnit> toRemove = new ArrayList<SimpleUnit>();
int winner = -1;
boolean gameOver = false;
synchronized(allUnits) {
for (SimpleUnit unit : allUnits){
unit.move(delta);
}
for (SimpleUnit unit : allUnits){
unit.doLogic(delta, allUnits);
}
for (SimpleUnit unit : allUnits) {
if (unit.isDead) {
toRemove.add(unit);
}
server.sendToAllTCP(unit);
}
for (SimpleUnit unit : toRemove) {
if (unit.unitType == UnitType.treeOfLife) {
gameOver = true;
if (winner == -1) {
if (unit.unitAllegiance == 0) {
winner = 1;
} else {
winner = 0;
}
} else {
winner = -1;
}
}
allUnits.remove(unit);
}
}
//Check if the game is over
if (gameOver) {
Network.sendEndGameStats(server, winner);
break;
}
}
}
private boolean isUnitSpawnTick(long delta) {
currTickTime += delta;
if (currTickTime >= tickLength) {
currTickTime -= tickLength;
currWave++;
return true;
} else {
return false;
}
}
private void spawnUnits() {
synchronized (players) {
for (Player p : players) {
addAllUnits(p.garden.spawnUnits());
}
}
}
private void addAllUnits(ArrayList<SimpleUnit> newUnits) {
for (SimpleUnit s : newUnits) {
allUnits.add(s);
}
}
}