gvsu/cs654/final-proj/BlobWarsServer.java
josh 723c3cc876 push full world to new players, push player resets properly
git-svn-id: svn://anubis/gvsu@105 45c1a28c-8058-47b2-ae61-ca45b979098e
2008-04-13 23:39:22 +00:00

336 lines
11 KiB
Java

import java.io.*;
import java.util.*;
import java.net.*;
public class BlobWarsServer
{
public static final int PORT = 38491;
private ServerSocket m_socket;
private BlobWarsWorld m_world;
private Vector<ClientUpdate> m_clientUpdates;
private HashMap<Socket, String> m_socketToPlayerName;
private HashMap<String, Player> m_lastPlayers;
private HashMap<Integer, Shot> m_lastShots;
private int m_lastNumPlayersAlive;
public static void main(String[] args)
{
BlobWarsServer bws = new BlobWarsServer();
bws.mainloop();
}
public BlobWarsServer()
{
m_lastNumPlayersAlive = 0;
m_world = new BlobWarsWorld();
m_clientUpdates = new Vector<ClientUpdate>();
m_socketToPlayerName = new HashMap<Socket, String>();
try {
m_socket = new ServerSocket(PORT);
} catch (Exception e) {
e.printStackTrace();
return;
}
}
private class ClientUpdate
{
public Socket socket;
public String message;
}
public void mainloop()
{
if (m_socket == null)
return;
new Thread(new ServerGameLoop()).start();
/* listen loop to accept new connections */
for (;;)
{
Socket client;
try {
client = m_socket.accept();
} catch (Exception e) {
System.out.println("Socket error!");
e.printStackTrace();
break;
}
/* handle the client in a separate thread */
Thread t = new Thread(new ClientHandler(client));
t.start();
}
}
private void processClientUpdate(ClientUpdate cu)
{
StringTokenizer st = new StringTokenizer(cu.message, ":");
Vector<String> tokens = new Vector<String>();
while (st.hasMoreTokens())
{
tokens.add(st.nextToken());
}
String[] arr = tokens.toArray(new String[1]);
if (arr.length < 1)
return;
if (arr[0].equals("NAME"))
{
if (arr.length < 2)
return;
System.out.println("Player '" + arr[1] + "' signed on.");
m_world.addPlayer(arr[1]);
m_socketToPlayerName.put(cu.socket, arr[1]);
m_lastPlayers.clear(); // clearing the last information will
m_lastShots.clear(); // push everything to the new player
return;
}
/* the rest of the commands all require a player to be registered */
if (!m_socketToPlayerName.containsKey(cu.socket))
return;
String playerName = m_socketToPlayerName.get(cu.socket);
if (arr[0].equals("SHOOT")) {
m_world.shoot(playerName);
} else if (arr[0].equals("UP")) {
m_world.moveUp(playerName);
} else if (arr[0].equals("DOWN")) {
m_world.moveDown(playerName);
} else if (arr[0].equals("LEFT")) {
m_world.moveLeft(playerName);
} else if (arr[0].equals("RIGHT")) {
m_world.moveRight(playerName);
}
}
private class ServerGameLoop implements Runnable
{
public void run()
{
for (;;)
{
try {
Thread.sleep(45);
} catch (InterruptedException ie) {
System.out.println("ServerGameLoop: interrupted!");
return;
}
/* apply changes from clients */
synchronized (m_clientUpdates)
{
for (ClientUpdate cu : m_clientUpdates)
{
processClientUpdate(cu);
}
m_clientUpdates.clear();
}
/* step the BlobWars world */
m_world.step();
/* calculated updated players */
HashMap<String, Player> pushPlayers =
new HashMap<String, Player>();
HashMap<String, Player> players = m_world.getPlayers();
if (m_lastPlayers == null)
pushPlayers.putAll(m_world.getPlayers());
else
{
for (String name : players.keySet())
{
if (!m_lastPlayers.containsKey(name))
pushPlayers.put(name, players.get(name));
else if (!players.get(name).equals(
m_lastPlayers.get(name)))
pushPlayers.put(name, players.get(name));
}
}
/* calculate updated shots */
HashMap<Integer, Shot> pushShots =
new HashMap<Integer, Shot>();
HashMap<Integer, Shot> shots = m_world.getShots();
if (m_lastShots == null)
pushShots.putAll(m_world.getShots());
else
{
for (Integer shotid : shots.keySet())
{
if (!m_lastShots.containsKey(shotid))
pushShots.put(shotid, shots.get(shotid));
else if (!shots.get(shotid).equals(
m_lastShots.get(shotid)))
pushShots.put(shotid, shots.get(shotid));
}
}
/* build up the update string */
String sendLine = "";
for (Player p : pushPlayers.values())
{
sendLine += "PLAYER:" + p + "\n";
}
for (Shot s : pushShots.values())
{
sendLine += "SHOT:" + s + "\n";
}
/* add remove messages for all players / shots that are gone */
if (m_lastPlayers != null)
{
for (String playerName : m_lastPlayers.keySet())
{
if (!players.containsKey(playerName))
{
/* player playerName has left since last update */
sendLine += "RMPLAYER:" + playerName + "\n";
}
}
}
if (m_lastShots != null)
{
for (Integer id : m_lastShots.keySet())
{
if (!shots.containsKey(id))
{
/* shot has expired since last update */
sendLine += "RMSHOT:" + id + "\n";
}
}
}
/* check number of players alive */
Player alivePlayer = null;
int alivePlayers = 0;
for (Player p : players.values())
{
if (p.health > 0.0)
{
alivePlayers++;
alivePlayer = p;
}
}
/* save the player / shot data into the "last" variables */
m_lastPlayers = PlayerClone(players);
m_lastShots = ShotClone(shots);
/* declare a winner if there is one and reset the players */
if (alivePlayers == 1 && alivePlayers < m_lastNumPlayersAlive)
{
/* game is over, alivePlayer won */
sendLine += "WINNER:" + alivePlayer.name + "\n";
m_world.resetPlayers();
}
m_lastNumPlayersAlive = alivePlayers;
/* write updated info to each client */
synchronized (m_socketToPlayerName)
{
for (Socket client : m_socketToPlayerName.keySet())
{
try {
BufferedWriter bw = new BufferedWriter(
new OutputStreamWriter(
client.getOutputStream()));
bw.write(sendLine, 0, sendLine.length());
bw.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
}
private class ClientHandler implements Runnable
{
private Socket m_socket;
public ClientHandler(Socket socket)
{
m_socket = socket;
System.out.println("Incoming connection from " +
m_socket.getInetAddress().getHostAddress());
}
public void run()
{
BufferedReader br;
try {
br = new BufferedReader(
new InputStreamReader(m_socket.getInputStream()));
} catch (IOException ioe) {
ioe.printStackTrace();
return;
}
for (;;)
{
String line;
try {
line = br.readLine();
} catch (Exception e) {
// e.printStackTrace();
break;
}
if (line == null)
break;
// System.out.println("SERVER GOT LINE: " + line);
if (line.equals("QUIT"))
break;
ClientUpdate cu = new ClientUpdate();
cu.socket = m_socket;
cu.message = line;
synchronized (m_clientUpdates)
{
m_clientUpdates.add(cu);
}
}
/* end of client handling loop, remove client from world */
synchronized (m_socketToPlayerName)
{
if (m_socketToPlayerName.containsKey(m_socket))
{
System.out.println("Player '" +
m_socketToPlayerName.get(m_socket) +
"' signed off.");
m_world.removePlayer(m_socketToPlayerName.get(m_socket));
m_socketToPlayerName.remove(m_socket);
}
try {
m_socket.close();
} catch (Exception e) {}
}
}
}
public HashMap<String, Player> PlayerClone(HashMap<String, Player> orig)
{
HashMap<String, Player> newhm = new HashMap<String, Player>();
for (String name : orig.keySet())
{
Player p = orig.get(name).clone();
newhm.put(name, p);
}
return newhm;
}
public HashMap<Integer, Shot> ShotClone(HashMap<Integer, Shot> orig)
{
HashMap<Integer, Shot> newhm = new HashMap<Integer, Shot>();
for (Integer id : orig.keySet())
{
Shot s = orig.get(id).clone();
newhm.put(id, s);
}
return newhm;
}
}