package robombs.game;
import java.awt.Color;
import java.net.InetAddress;
import java.util.*;
import javax.swing.*;
import robombs.clientserver.*;
import robombs.game.gui.*;
import robombs.game.model.*;
import robombs.game.util.*;
import robombs.game.view.*;
import robombs.game.startup.*;
import robombs.game.sound.*;
import robombs.game.talkback.*;
import com.threed.jpct.*;
import com.threed.jpct.util.*;
/**
* The client, i.e. the actual game. This client also opens a window with a
* simple server browser to join an existing server or start a new one.
*/
public class BlueThunderClient extends AbstractClient implements DataTransferListener, ClientPreProcessor, GameClient, SelectionListener, EventProcessor {
static {
Config.glVSync = false;
Config.glUseUnappropriateModes = true;
Config.glTransparencyOffset = 0.0f;
Config.maxTextures = 64;
Config.maxPolysVisible = 25000;
Config.collideEllipsoidThreshold = 0.075f;
Config.collideEllipsoidSmoothing = false;
Config.collideOffset = 150;
Config.glTrilinear = true;
Config.glRefresh = 0;
Config.glZBufferDepth = 24;
Config.glColorDepth = 24;
Config.glWindowName = "Robombs " + Globals.GAME_VERSION;
Config.saveMemory = true;
Config.glAvoidTextureCopies = true;
Config.maxAnimationSubSequences = 128;
Config.farPlane = 500;
Config.lightMul = 2;
Config.glTriangleStrips = false;
Config.glBufferedBlits = true;
Config.glUseVBO = Globals.useVBO;
}
private int width = 800;
private int height = 600;
private boolean roundWon = false;
private FrameBuffer buffer = null;
private KeyMapper keyMapper = null;
private LocalPlayerObject player = new LocalPlayerObject();
private ClientObject playerView = null;
private IPostProcessor blo = null;
private KeyStates keyStates = null;
private DecalManager decals = null;
private ServerBrowser browser = null;
private ServerSelection serverSel = null;
private MouseMapper mouse = null;
private ServerEntry selectedServer = null;
private Highscores hiView = null;
private HighscoreTable tmpScores = null;
private boolean spawned = false;
private ShadowHelper shadower = null;
private GLFont bigFont = null;
private GLFont bannerFont = null;
private Table messages = null;
private Label clickMessage = null;
private Label roundMessage = null;
private int cpus = Runtime.getRuntime().availableProcessors();
private int trottleVal = cpus > 1 ? 0 : 5;
private boolean throttling = true;
private boolean shadows = true;
private boolean fullScreen = false;
private boolean shadowFilter = true;
private int shadowSize = 4096;
private int antiAliasing = 0;
private int mouseSensivity = 50;
private IconPainter icons = new IconPainter();
private BotClient botClient = null;
private Texture textBanner = null;
private Texture textBannerDead = null;
private Texture darken = null;
private Ticker respawnTicker = new Ticker(7000);
private Ticker tauntTicker = new Ticker(1000);
private boolean firing = false;
private boolean hasToRelease = false;
private GLFont smallFont = TextBlitter.create(9);
private long levelNameTime = 0;
private String levelName = "";
private boolean creditMode = true;
private int forcedStepsBack = 0;
private boolean mayTalkBack = TalkBack.mayTalkBack();
private Ticker tbTimer = new Ticker(20000);
private SkyBox skyBox = null;
private ReflectionHelper refHelper = null;
/**
* Create a new client. This starts the client and enters the game loop.
*
* @throws Exception
*/
public BlueThunderClient(String[] args) throws Exception {
if (args.length > 0) {
if (args[0].equals("nada")) {
shadows = false;
}
}
run();
}
public BlueThunderClient() throws Exception {
}
public void selected(VideoMode vm, boolean fullScreen, int shadowQuality, boolean shadowFiltering, int aa, int mouseSpeed) throws Exception {
Config.glSetDesiredVideoMode(vm, false);
width = vm.width;
height = vm.height;
this.fullScreen = fullScreen;
if (shadowQuality == 0) {
shadows = false;
} else {
shadows = true;
shadowSize = (int) Math.pow(2, 8 + shadowQuality);
}
this.shadowFilter = shadowFiltering;
this.antiAliasing = aa;
this.mouseSensivity = mouseSpeed;
run();
}
public void connect(ServerEntry server, String name) throws Exception {
if (!disConnectScheduled) {
try {
synchronized (world) {
world.removeAllObjects();
world.removeAllLights();
hiView = null;
selectedMaps.clear();
}
state.reset();
NetLogger.log("Connecting...");
while (mouse.buttonDown(0)) {
// Avoid entering the level while the mouse button is being
// pressed
org.lwjgl.input.Mouse.poll();
Thread.sleep(10);
org.lwjgl.opengl.Display.processMessages();
}
shouldBeConnected = true;
firstTransferFinished = false;
entitiesUpdated = false;
DataContainer dc = new DataContainer();
dc.add(name);
dc.add(mapList.getCheckSum());
dc.add(0); // 0==normal Client
dc.add(player.getObjectID());
clientImpl = new SimpleClient(server, true, dc);
clientImpl.addListener(this);
clientImpl.addPreProcessor(this);
clientImpl.connect();
eventQueue.clear();
selectedServer = server;
state.setState(NetState.STATE_CONNECTED);
// Decide if active transfers should be used (LAN) or not
// (Internet)
String serverIP = clientImpl.getServer();
System.out.println(serverIP);
if (serverIP.startsWith("127.0.0.1") || serverIP.startsWith("10.") || serverIP.startsWith("172.") || serverIP.startsWith("192.168.")) {
Globals.activeTransfer = true;
Globals.activeTransferForBots = true;
NetLogger.log("Client " + getClientID() + ": LAN transfer mode selected!");
} else {
Globals.activeTransfer = false;
Globals.activeTransferForBots = false;
NetLogger.log("Client " + getClientID() + ": Internet transfer mode selected!");
}
/*
* Globals.activeTransfer=false;
* Globals.activeTransferForBots=false;
* NetLogger.log("Client "+getClientID
* ()+": Internet transfer mode forced!");
*/
} catch (Exception e) {
if (clientImpl != null) {
clientImpl.disconnect();
}
shouldBeConnected = false;
clientImpl = null;
if (!Config.glFullscreen) {
JOptionPane.showMessageDialog(null, "Failed to connect: \"" + e.getMessage() + "\"");
}
throw e;
}
}
}
public void prepare() {
try {
long start = Ticker.getTime();
state.setState(NetState.STATE_PREPARING);
reInit(false);
state.setState(NetState.STATE_LEVEL_LOADED);
player.setPosition(new SimpleVector(0, Globals.skyLimit * 10f, 0));
player.setClientID(clientImpl.getClientID());
state.setState(NetState.STATE_WAITING);
messages.insertCell(2, 0, "Waiting for other players!");
Event ev = new Event(Event.LEVEL_LOADED, -99, -99, clientImpl.getClientID());
ev.setSourceClientID(clientImpl.getClientID());
synchronized (SYNC) {
eventQueue.add(ev);
}
player.setSpecialValue(Globals.LIVES);
waitTimer.reset();
NetLogger.log("Level prepared in " + (Ticker.getTime() - start) + "ms.");
levelNameTime = Ticker.getTime();
} catch (Exception e) {
throw new RuntimeException("Error while preparing level", e);
}
}
public void begin() {
// The Colorizer has to be resetted here, because otherwise, it may have
// created some
// data between a level request and the actual start of the game. This
// is not 100% correct
// behaviour IMHO, but it's hard to track...
Colorizer.getInstance().init();
player.activate();
respawn();
try {
// Give the respawn thread 100ms to breath...
Thread.sleep(100);
} catch (Exception e) {
}
state.setState(NetState.STATE_RUNNING);
}
public void disconnect() throws Exception {
synchronized (SYNC) {
state.reset();
spawned = false;
ready(false);
shouldBeConnected = false;
if (coMan != null) {
coMan.removeAll(world);
}
hiView = null;
if (player != null) {
player.setAlive();
player.deactivate();
}
synchronized (world) {
world.removeAllObjects();
world.removeAllLights();
}
roundMessage = null;
roundCompleted = false;
}
if (clientImpl != null) {
clientImpl.disconnect();
while (clientImpl.isConnected()) {
// Wait for the disconnect to finish...
Thread.sleep(100);
}
clientImpl = null;
if (disConnectScheduled) {
tmpScores = null;
disConnectScheduled = false;
serverSel.initialAndReconnect();
} else {
serverSel.initial();
}
//
}
disConnectScheduled = false;
clickMessage.setVisible(false);
TeamAssigner.clear();
System.runFinalization();
System.gc();
}
public ServerEntry getServer() {
return selectedServer;
}
public void startServer(int port) throws Exception {
if (serverImpl == null) {
serverImpl = new BlueThunderServer(port);
new Thread(serverImpl).start();
}
}
public void addBot() {
if (botClient == null || !botClient.isConnected()) {
try {
botClient = new BotClient(serverImpl);
botClient.run();
while (!botClient.isConnected()) {
Thread.sleep(50);
}
} catch (Exception e) {
NetLogger.log("Error while connecting bot client to the server!");
e.printStackTrace();
botClient = null;
}
} else {
botClient.addBot();
}
}
public List<String> getPlayers() {
if (hiView != null) {
// Get the names from the highscore table. Quite strange...:-)
return hiView.getPlayerNames();
} else {
return Collections.emptyList();
}
}
public List<Integer> getTeams() {
if (hiView != null) {
return hiView.getTeams();
} else {
return Collections.emptyList();
}
}
public void logout(int cid, PlayerInfo pi) {
if (botClient != null && botClient.getClientID() == cid) {
if (botClient.getBotCount() == 1) {
// The last one goes away...terminate that client. That will
// remove the remaining
// player automatically from the server.
serverImpl.logout(cid);
botClient.quit();
botClient = null;
} else {
botClient.removeBot(pi);
}
} else {
if (serverImpl != null) {
serverImpl.logout(cid);
}
}
TeamAssigner.removeTeamAssigment(cid, pi.getObjectID());
}
public void shutDownServer() throws Exception {
if (serverImpl != null) {
if (isConnected()) {
disconnect();
}
if (botClient != null) {
// Bot client running? Terminate that sucker!
botClient.quit();
botClient = null;
}
InfoLine il = new InfoLine(InfoLine.SYSTEM_OUT, 0, "msg", "Server stopped!");
InfoDataContainer idc = new InfoDataContainer();
idc.add(il);
serverImpl.broadcast(idc);
Thread.sleep(300); // Wait to make sure that the broadcast succeeds!
serverImpl.stop();
serverImpl = null;
}
}
public boolean runsServer() {
return serverImpl != null;
}
public BlueThunderServer getServerImpl() {
return serverImpl;
}
public void quit() {
try {
disconnect();
shutDownServer();
} catch (Exception e) {
// We are on our way to exit...no time for exceptions...
}
quit = true;
}
public void beforeReceiving() {
tmpScores = null;
super.beforeReceiving();
}
public void afterReceiving() {
if (tmpScores != null) {
// Highscores sind mitgekommen beim Transfer!
hiView = new Highscores(tmpScores);
tmpScores = null;
}
super.afterReceiving();
}
public MapList getMapList() {
return mapList;
}
/**
* Schedules a request for the next level.
*/
public void nextLevel() {
if (state.getState() == NetState.STATE_RUNNING) {
Event ev = new Event(Event.NEXT_LEVEL_REQUEST, -99, -99, clientImpl.getClientID());
ev.setSourceClientID(clientImpl.getClientID());
synchronized (SYNC) {
eventQueue.add(ev);
}
}
}
/**
* Starts a single player game. That's a game with all maps in the rotation
* plus 3 bots.
*/
public void startSinglePlayer() {
firstMap();
selectedMaps.clear();
if (serverImpl != null) {
serverImpl.stop();
while (serverImpl.isRunning()) {
try {
Thread.sleep(100);
NetLogger.log("Waiting for server to quit!");
} catch (Exception e) {
}
}
}
try {
startServer(serverSel.getPort());
while (!serverImpl.isRunning()) {
try {
Thread.sleep(100);
NetLogger.log("Waiting for server to start!");
} catch (Exception e) {
}
}
ServerEntry se = new ServerEntry("Single player server", InetAddress.getLocalHost(), serverSel.getPort(), 0);
connect(se, serverSel.getName());
selectedMaps.addAll(mapList.getMapInfos());
serverImpl.setSelectedMaps(selectedMaps);
serverSel.setMaps(selectedMaps);
} catch (Exception e) {
NetLogger.log("Unable to start single player mode!");
e.printStackTrace();
}
if (botClient != null) {
botClient.quit();
}
for (int i = 0; i < 5; i++) {
addBot();
}
serverImpl.setGameState(true);
InfoDataContainer dc = new InfoDataContainer();
int cnt = 0;
for (MapInfo mi : selectedMaps) {
InfoLine il = new InfoLine(InfoLine.MAP_ENTRY, cnt, mi.getName(), mi.getRealName() + "," + mi.getSet());
dc.add(il);
cnt++;
}
InfoLine il = new InfoLine(InfoLine.SERVER_STARTED_GAME, 0, "", "");
dc.add(il);
serverImpl.broadcast(dc);
serverImpl.setTimeOut(20000);
serverSel.setVisible(false);
}
/**
* Runs the client.
*
* @throws Exception
*/
private void run() throws Exception {
mapList = new MapList();
loadTextures();
loadSounds();
initBuffer();
initBrowser();
initGUI();
gameLoop();
exit();
}
/**
* Processes an info message from the server.
*
* @param il
* InfoLine the info
*/
protected void processInfo(InfoLine il) {
if (il.getType() == InfoLine.SERVER_STARTED_GAME && state.getState() <= NetState.STATE_WAITING) {
serverSel.setVisible(false);
NetLogger.log("Server has started the game!");
messages.insertCell(2, 0, "Loading game data!");
reloadScheduled = true;
}
if (il.getType() == InfoLine.NEXT_LEVEL && state.getState() == NetState.STATE_RUNNING) {
NetLogger.log("Server switches to the next level!");
serverSel.setVisible(false);
messages.insertCell(2, 0, "Loading next level!");
nextMap();
reloadScheduled = true;
}
if (il.getType() == InfoLine.ALL_CLIENTS_READY && state.getState() == NetState.STATE_WAITING) {
NetLogger.log("Client " + clientImpl.getClientID() + ": All clients are ready to go!");
messages.insertCell(2, 0, "Starting game!");
playerCount = Integer.parseInt(il.getValue());
respawnCount = 0;
begin();
}
if (il.getType() == InfoLine.END_GAME && state.getState() == NetState.STATE_RUNNING) {
NetLogger.log("Server wants to end game!");
disConnectScheduled = true;
}
if (il.getType() == InfoLine.ROUND_COMPLETED) {
NetLogger.log("Round completed");
roundCompleted = true;
String name = il.getKey();
int team = il.getCount();
boolean teamWin = team != 0;
String teamName = il.getValue();
if (name.length() == 0) {
name = "DRAW!";
} else {
if (teamWin) {
name = teamName;
}
name += " has won!";
}
int dim = TextBlitter.getWidth(bannerFont, name) / 2;
roundMessage = new Label((int) (buffer.getOutputWidth() / 2 - buffer.getOutputWidth() / 13.3333f - dim),
(int) (buffer.getOutputHeight() / 2 + buffer.getOutputWidth() / 10.66666f) - bannerFont.fontHeight / 2);
roundMessage.setFont(bannerFont);
roundMessage.setText(name);
roundMessage.setColor(Color.BLACK);
if (player.isDead() && player.getSpecialValue() <= 0 && (!teamWin || TeamAssigner.getTeam(player.getClientID(), player.getObjectID()) != team)) {
// Obviously no win
SoundManager.getInstance().play("boo", player.getPosition());
roundWon = false;
} else {
// a win!
SoundManager.getInstance().play("happykids", player.getPosition());
roundWon = true;
}
roundMessage.setVisible(true);
}
if (il.getType() == InfoLine.PLAYER_ADDED) {
NetLogger.log("'" + il.getValue() + "' added!");
}
if (il.getType() == InfoLine.TEAM_ASSIGNED) {
int team = il.getCount();
int cid = Integer.parseInt(il.getKey());
int oid = Integer.parseInt(il.getValue());
TeamAssigner.assignTeam(cid, oid, team);
NetLogger.log("Client " + cid + " has been assigned to team " + team);
if (runsServer()) {
serverImpl.sendScores();
}
}
if (il.getType() == InfoLine.READY_YOURSELF && !isReady() && !runsServer()) {
messages.insertCell(2, 0, "The server wants to start the game - please ready yourself!");
serverSel.directMessage("The server wants to start the game - please ready yourself!");
}
if (il.getType() == InfoLine.PLAYER_REMOVED) {
NetLogger.log("'" + il.getValue() + "' removed!");
int cid = Integer.parseInt(il.getKey());
if (cid == clientImpl.getClientID()) {
// Somehow, a message arrived that this client's player has been
// disconnected.
// This can be a server-side drop, we have to process it...
try {
disconnect();
} catch (Exception e) {
NetLogger.log("Unable to disconnect - already disconnected?");
}
}
respawnCount++; // Yes, this should really be ++, not --
}
if (il.getType() == InfoLine.SCORE_TABLE) {
if (tmpScores == null || (tmpScores.getLineCount() > 0 && il.getKey().equals("name") && il.getCount() == 0)) {
NetLogger.log("Client " + getClientID() + ": Receiving new high score list!");
tmpScores = new HighscoreTable();
}
tmpScores.addLineEntry(il);
}
if (il.getType() == InfoLine.MAP_ENTRY) {
// This logic is a bit unsafe, because it assumes, that the entries
// arrive in the
// correct order. However, this is always the case and the way how
// the server works
// ensures this, so it doesn't matter...
if (il.getCount() == 0) {
selectedMaps.clear();
firstMap();
}
if (il.getKey().length()>0) {
selectedMaps.add(new MapInfo(il.getKey(), il.getValue()));
}
}
if (il.getType() == InfoLine.SYSTEM_OUT) {
messages.insertCell(2, 0, il.getValue());
}
}
public void sendEvent(Event event) {
synchronized (SYNC) {
eventQueue.add(event);
}
}
/**
* Processes an event from the server. An event if something like
* "player fires a shot" or "player has died".
*
* @param event
* Event the event
*/
public void processEvent(Event event) {
switch (event.getType()) {
case Event.TAUNT:
// event.getOrigin() ist oftmals zu leise...daher nur aus der
// Richtung aber laut!
SimpleVector p = event.getOrigin();
p = p.calcSub(player.getPosition());
p = p.normalize();
SimpleVector s = new SimpleVector(player.getPosition());
s.add(p);
SoundManager.getInstance().play("taunt" + event.getValue(), s);
break;
case Event.PLAYER_DAMAGE:
if (event.getTargetClientID() == clientImpl.getClientID()) {
// Myself
player.addToValue(event.getValue());
}
break;
case Event.PLAYER_DEAD:
if (!roundCompleted) {
SoundManager.getInstance().play("scream", event.getOrigin());
if (event.getTargetClientID() != clientImpl.getClientID()) {
// Somebody else hit
ClientObject obj = coMan.getClientObject(event.getTargetID(), event.getTargetClientID());
if (obj != null) {
// Can't be null anyway...
obj.setCollisionMode(Object3D.COLLISION_CHECK_NONE);
}
} else {
// Myself
player.setDead();
respawnTicker.reset();
playerView.setCollisionMode(Object3D.COLLISION_CHECK_NONE);
if (player.getSpecialValue() <= 0) {
// All lives lost? Tell the server that we are out for
// this round.
Event ev = new Event(Event.ROUND_LOST, player, player);
eventQueue.add(ev);
SimpleVector viewPos = level.getCenter();
viewPos.y -= 200;
Camera cam = level.createAllViewingCamera(viewPos, buffer);
SoundManager.getInstance().play("boo", player.getPosition());
// processEvent is already synchronized to world...no
// need to resync it here...
Camera camy = world.getCamera();
camy.setBack(cam.getBack());
camy.setPosition(cam.getPosition());
camy.setFOV(Math.max(cam.getFOV(), cam.getYFOV()));
}
}
}
break;
case Event.BOMB_HIT:
if (event.getTargetClientID() == clientImpl.getClientID()) {
// Created by myself
bombMan.explode(event.getTargetID());
} else {
throw new RuntimeException("Client received an event for another client!?");
}
break;
case Event.BOMB_DISABLED:
if (event.getTargetClientID() == clientImpl.getClientID()) {
// Created by myself
bombMan.defuse(event.getTargetID());
}
SoundManager.getInstance().play("splash", event.getOrigin());
break;
case Event.BOMB_TOUCHED:
if (player.isInvincible() && event.getSourceClientID() == clientImpl.getClientID() && !player.getPlayerPowers().canKick()) {
// The local player is inVincible and has touched some bomb?
// Make it explode!
Event eve = new Event(Event.BOMB_OVERLOADED, event.getSourceID(), event.getTargetID(), event.getTargetClientID());
eventQueue.add(eve);
} else {
if (event.getTargetClientID() == clientImpl.getClientID() /*
* &&
* player
* .
* getPlayerPowers
* (
* ).canKick
* ()
*/) {
// Created by myself
boolean kicked = bombMan.startMoving(event.getTargetID(), event);
if (kicked) {
forcedStepsBack = Globals.stepBacks;
}
}
SoundManager.getInstance().play("woohoo", event.getOrigin());
}
break;
case Event.REMOVE_CRATE:
level.getCrateManager().explode(event, level);
break;
case Event.COLLECT_ITEM:
boolean bonus = level.getItemManager().collect(event, level, event.getSourceClientID() == clientImpl.getClientID(), player);
String sound = "bounce";
String texture = "star";
if (!bonus) {
sound = "cough";
texture = "slime";
}
SoundManager.getInstance().play(sound, event.getOrigin()); // Play
// sound...
// ...and create stars...silly idea to do this here...
ParticleManager pm = level.getParticleManager();
SimpleVector vel = new SimpleVector();
int end = 10;
if (Globals.enhancedGraphics) {
end = 20;
}
for (int i = 0; i < end; i++) {
vel.y = -0.3f - (float) Math.random() / 7f;
vel.x = 0.5f * (float) (Math.random() - 0.5f);
vel.z = 0.5f * (float) (Math.random() - 0.5f);
pm.addParticle(event.getOrigin(), vel, 10f, 2000, texture, 2f + (float) Math.random(), true, false, false, Color.WHITE);
}
break;
case Event.LOGIN_REJECTED:
if (event.getTargetClientID() == clientImpl.getClientID()) {
if (event.getSourceID() == -99) {
serverSel.message("Login rejected - the game is already running!");
}
if (event.getSourceID() == -98) {
serverSel.message("Login rejected - level data mismatch!");
}
NetLogger.log("Client login rejected by server!");
try {
disconnect();
serverSel.setVisible(true);
} catch (Exception e) {
NetLogger.log("Unable to disconnect from server!");
}
}
break;
case Event.FIRE:
if (event.getSourceClientID() != clientImpl.getClientID()) {
// Someone else has fired!
dropper.addDrop(event.getOrigin(), event.getDirection(), level, true);
if (fireTicker.getTicks() > 0) {
// This isn't really correct...but making it correct is very
// expensive. So we don't care for now...
SoundManager.getInstance().play("water", event.getOrigin());
fireTicker.reset();
}
}
break;
case Event.PLACE_BOMB:
if (event.getSourceClientID() != clientImpl.getClientID()) {
// Someone else has placed a bomb!
NetLogger.log("Bomb placed at " + event.getOrigin());
GridPosition gp = bombMan.getBombMask().getGrid(event.getOrigin().x, event.getOrigin().z);
bombMan.getBombMask().setMaskAt(gp, MapMask.BOMB);
}
SoundManager.getInstance().play("drop", event.getOrigin());
break;
case Event.ENTITY_REMOVE:
// For "normal" Objects, the server just doesn't transmit a removed
// object. For bombs,
// this isn't sufficient, because they have to be removed from the
// manager's grid mask
// This is why the server broadcasts this removal. There is no
// check, if this is really a bomb.
// The server doesn't broadcast anything else ATM, so it's hacky but
// fine this way. If this
// changes, we need different events for some kind of typing.
if (event.getSourceClientID() != clientImpl.getClientID()) {
// Someone else has removed a bomb...
ClientObject co = coMan.getClientObject(event.getSourceID(), event.getSourceClientID());
GridPosition gp2 = null;
if (co != null) {
SimpleVector sv = co.getTransformedCenter();
gp2 = bombMan.getBombMask().getGrid(sv.x, sv.z);
}
NetLogger.log("Bomb removed at " + event.getOrigin());
GridPosition gp = bombMan.getBombMask().getGrid(event.getOrigin().x, event.getOrigin().z);
if (gp2 != null && !gp.equals(gp2)) {
// This is a little bit kludgy, but i had so many problems
// with bombs remaining in
// the grid that were long gone, that i want to be 110% sure
// now...:-)
NetLogger.log("Local and remote grid don't match...cleaning both!");
bombMan.getBombMask().setMaskAt(gp, MapMask.NO_BOMB);
bombMan.getBombMask().setMaskAt(gp2, MapMask.NO_BOMB);
} else {
bombMan.getBombMask().setMaskAt(gp, MapMask.NO_BOMB);
}
}
break;
case Event.PLAYER_RESET_HEALTH:
if (event.getSourceClientID() == clientImpl.getClientID()) {
// Myself...
player.setValue(100);
SoundManager.getInstance().play("comeon", player.getPosition());
} else {
ClientObject obj = coMan.getClientObject(event.getSourceID(), event.getSourceClientID());
if (obj != null) {
obj.setCollisionMode(Object3D.COLLISION_CHECK_OTHERS | Object3D.COLLISION_CHECK_SELF);
}
}
respawnCount++;
break;
}
}
/**
* Initializes the startup-GUI, i.e. the server browser.
*
* @throws Exception
*/
private void initGUI() throws Exception {
messages = new Table("msgs", 3, 1, 10, height - 60, 500, height - 10);
serverSel = new ServerSelection(browser, this, buffer.getOutputHeight());
serverSel.setVisible(false);
bigFont = TextBlitter.create(buffer.getOutputWidth() / 20);
createMessageText("Click to respawn!", true);
clickMessage.setVisible(false);
bannerFont = TextBlitter.create(buffer.getOutputWidth() / (2 * 15));
}
private void createMessageText(String txt, boolean semiCenter) {
int dim = TextBlitter.getWidth(bigFont, txt) / 2;
int sub = 0;
int add = 0;
Color col = Color.BLACK;
if (semiCenter) {
sub = buffer.getOutputWidth() / 16;
add = buffer.getOutputHeight() / 4;
col = Color.WHITE;
}
clickMessage = new Label(buffer.getOutputWidth() / 2 - dim - sub, buffer.getOutputHeight() / 2 - bigFont.fontHeight / 2 + add);
clickMessage.setFont(bigFont);
clickMessage.setText(txt);
clickMessage.setColor(col);
}
private void initBrowser() {
if (browser != null) {
browser.stopBrowser();
while (browser.isRunning()) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
browser = new ServerBrowser(7002);
browser.startBrowser();
}
/**
* Initializes the client.
*/
private void initClient() {
coMan = new ClientObjectManager(shadower, false);
bombMan = new LocalBombManager(level, shadower);
timeout = new Ticker(2000);
keyStates = new KeyStates();
}
/**
* Prepares the data from the client that should be send to the server.
*/
protected void prepareClientData() {
if (clientImpl != null) {
if (state.getState() >= NetState.STATE_LEVEL_LOADED) {
ExtendedDataContainer playerAndObjects = new ExtendedDataContainer();
playerAndObjects.add(player);
synchronized (KILL_SYNC) {
toKill.addAll(bombMan.fillOrKill(playerAndObjects, eventQueue));
}
DataContainer edc = eventQueue.getEvents(clientImpl.getClientID());
eventQueue.clear();
clientImpl.setContainers(new DataContainer[] { playerAndObjects, edc });
} else {
// Events only..
DataContainer edc = eventQueue.getEvents(clientImpl.getClientID());
eventQueue.clear();
clientImpl.setContainers(new DataContainer[] { new ExtendedDataContainer(), edc });
}
}
}
private void initBuffer() {
Logger.setOnError(Logger.ON_ERROR_THROW_EXCEPTION);
Config.glFullscreen = fullScreen;
buffer = new FrameBuffer(width, height, this.antiAliasing * 10); // Relies
// on
// the
// constants...:-)
buffer.disableRenderer(IRenderer.RENDERER_SOFTWARE);
buffer.enableRenderer(IRenderer.RENDERER_OPENGL);
shadows = shadows && buffer.supports(FrameBuffer.SUPPORT_FOR_SHADOW_MAPPING);
/*
* if (!buffer.isInitialized()) { // Error with this mode? Try 1024768
* instead...this has to be replaced by a "real" video mode selection //
* in a "real" game. buffer = new FrameBuffer(1024, 768,
* FrameBuffer.SAMPLINGMODE_NORMAL);
* buffer.disableRenderer(IRenderer.RENDERER_SOFTWARE);
* buffer.enableRenderer(IRenderer.RENDERER_OPENGL); }
*/
keyMapper = new KeyMapper();
mouse = new MouseMapper(buffer);
fireTicker = new Ticker(900);
bombTicker = new Ticker(200);
}
/**
* Initializes the game world.
*/
private void initWorld() {
dummy = new PlayerDummy(this.getClientID());
dummy.setEventQueue(eventQueue);
world.addObject(dummy);
world.getCamera().setFOVLimits(0, 100);
dummy.setCollisionMode(Object3D.COLLISION_CHECK_SELF);
level.addToWorld(world);
if (Globals.skyBox && skyBox == null) {
skyBox = new SkyBox(20000);
if (Globals.compiledObjects) {
skyBox.compile();
}
}
world.getLights().setRGBScale(Lights.RGB_SCALE_2X);
}
/**
* Initializes the player. The local player on the client is, opposed to
* remote players, no real 3D object but just a data representation.
*/
private void initPlayer() {
dummy.setObjectID(player.getObjectID());
player.reset();
player.setTurnSpeed(mouseSensivity);
}
private void initPlayerView() {
playerView = ClientObjectManager.createLocalPlayerObject(player, world, eventQueue);
playerView.setCollisionMode(Object3D.COLLISION_CHECK_SELF | Object3D.COLLISION_CHECK_OTHERS);
playerView.addCollisionListener(new ClientObjectCollisionListener(player, true));
if (shadows) {
shadower.addCaster(playerView);
// shadower.addReceiver(playerView);
}
player.setView(playerView);
dummy.setMaster(playerView);
}
/**
* Fires a bullet into the current view direction of the local player.
*/
private void fire(long ticks) {
if (!serverSel.isVisible() && !creditMode && state.getState() == NetState.STATE_RUNNING && allPlayersHaveSpawned()) {
PlayerPowers powers = player.getPlayerPowers();
boolean mayFire = (firing && powers.getWater() > 0) || (!firing && powers.getWater() == powers.getMaxWater());
int sick = powers.isSick();
if ((KeyStates.fire || mouse.buttonDown(0) || mouse.buttonDown(1) || sick == PlayerPowers.DROP_IMMEDIATELY) && clientImpl != null && clientImpl.isConnected()) {
if (!player.isDead() && !hasToRelease) {
if (mouse.buttonDown(0) && mayFire) {
fireBullet(ticks);
}
if (mouse.buttonDown(1) || sick == PlayerPowers.DROP_IMMEDIATELY) {
placeBomb();
}
} else {
if (clickMessage.isVisible() && player.getSpecialValue() > 0 && player.isDead()) {
clickMessage.setVisible(false);
respawn();
hasToRelease = true;
}
}
} else {
hasToRelease = false;
bombTicker.forward();
}
if (sick == PlayerPowers.DROP_IMMEDIATELY) {
// In this mode, nothing has to be released...you'll drop the
// bomb anyway...:-)
hasToRelease = false;
}
if (mouse.buttonDown(0) && mayFire && !hasToRelease) {
firing = true;
} else {
if (firing) {
SoundManager.getInstance().stop("water");
}
firing = false;
}
}
}
private void fireBullet(long ticks) {
player.setAnimation(Animations.FIRE);
player.setAnimationSpeed(20);
/*
* if (fireTicker.getTicks() > 0) {
*
* LocalObject bul = bulMan.addBullet(player, world, eventQueue); Event
* ev = new Event(Event.FIRE, player, bul);
* ev.setOrigin(player.getPosition()); eventQueue.add(ev);
* fireTicker.reset(); }
*/
SimpleVector pos = player.getPosition();
for (int i = 0; i < ticks; i++) {
SimpleVector[] data = dropper.addDrop(player, level);
Event ev = new Event(Event.FIRE, player, player);
ev.setOrigin(data[0]);
pos = data[0];
ev.setDirection(data[1]);
eventQueue.add(ev);
}
if (!firing) {
SoundManager.getInstance().play("water", pos, true);
} else {
SoundManager.getInstance().move("water", pos);
}
}
public int[] getLocalPlayerInfo() {
return new int[] { this.getClientID(), this.player.getObjectID() };
}
private void placeBomb() {
if (bombTicker.getTicks() > 0) {
if (bombMan.getCount() < player.getPlayerPowers().getBombCount()) {
// Only do this, if you are allowed to...
LocalObject bomb = bombMan.addBomb(clientImpl, player, world, eventQueue);
if (bomb != null) {
Event ev = new Event(Event.PLACE_BOMB, player, bomb);
ev.setOrigin(player.getPosition());
eventQueue.add(ev);
}
}
}
}
/**
* Respawn!
*/
private void respawn() {
if (player.getSpecialValue() > 0 && !roundCompleted && !respawnRunning) {
// Do this in another thread to make sure, that the server has send
// its data at least once
// before respawning.
entitiesUpdated = false;
respawnRunning = true;
new Thread() {
public void run() {
setPriority(Thread.MAX_PRIORITY);
spawned = false;
SimpleVector respawn = null;
int its = 0;
int cnt = 0;
try {
while (!entitiesUpdated && cnt < 100) {
Thread.sleep(50);
cnt++;
}
} catch (Exception e) {
}
if (cnt == 100) {
respawnRunning = false;
throw new RuntimeException("Client: Unable to respawn. Some remote data is missing!");
}
synchronized (SYNC) {
List<LocalPlayerObject> pis = new ArrayList<LocalPlayerObject>();
pis.add(player);
do {
SimpleVector s = new SimpleVector(spawnPoints[(clientImpl.getClientID() - 1 + its) % spawnPoints.length]);
SimpleVector ss = new SimpleVector();
ss.y = -3;
if ((isFree(s, level.getCrateManager(), bombMan, BlueThunderClient.this.coMan) && world.checkCollisionSpherical(s, ss, 3f).equals(ss)) || its > 15) {
respawn = s;
} else {
its++;
NetLogger.log("Client: " + s + " is blocked!");
}
} while (respawn == null);
if (player.getSpecialValue() == Globals.LIVES) {
// Only recolor if this is a new round's start.
Colorizer.getInstance().colorize(playerView, player);
}
player.setPosition(respawn);
playerView.setCollisionMode(Object3D.COLLISION_CHECK_SELF | Object3D.COLLISION_CHECK_OTHERS);
player.setAlive();
player.setInvincible(true);
// Align the player, so that he looks into the level's
// center!
player.getRotation().setIdentity();
player.getViewRotation().setIdentity();
SimpleVector pos = new SimpleVector(level.getCenter());
pos.y = player.getPosition().y;
pos = pos.calcSub(player.getPosition());
float yRot = -matrixToRad(pos.getRotationMatrix()).y;
player.getRotation().rotateY(yRot);
player.getViewRotation().rotateAxis(player.getViewRotation().getYAxis(), yRot);
synchronized (world) {
// Has to be synchronized with rendering, because
// the ShadowHelper changes the
// world's camera.
player.alignCamera(world.getCamera(), 50);
}
if (serverImpl != null) {
serverSel.serverIsPlaying();
} else {
serverSel.clientIsPlaying();
}
spawned = true;
Event ev = new Event(Event.PLAYER_RESPAWNED, player, player);
ev.setOrigin(respawn);
eventQueue.add(ev);
}
clickMessage.setVisible(false);
fireTicker.reset();
bombTicker.reset();
hasToRelease = true;
respawnRunning = false;
}
}.start();
}
}
/**
* Updates the particles.
*
* @param ticks
* long the number of ticks passed since last call
*/
private void updateParticles(long ticks) {
if (state.getState() == NetState.STATE_RUNNING) {
level.getParticleManager().move(ticks);
level.getSmokeCloudManager().move(ticks);
level.getDebrisManager().process(ticks);
dropper.process(level, bombMan, coMan);
}
}
/**
* Draw the GUI (i.e. the server selection as there is no more GUI in this
* example) if visible.
*/
private void drawGUI() {
if (serverSel.isVisible()) {
mouse.show();
serverSel.evaluateInput(mouse, keyMapper);
serverSel.draw(buffer);
} else {
mouse.hide();
if (creditMode) {
//buffer.clear();
buffer.blit(TextureManager.getInstance().getTexture("credits"), 0, 0, buffer.getOutputWidth() / 2 - height / 2, buffer.getOutputHeight() / 2 - height / 2, 512,
512, height, height, 60, false, null);
buffer.blit(TextureManager.getInstance().getTexture("crazy"), 0, 0, 0, 0, 512, 512, buffer.getOutputWidth(), buffer.getOutputHeight(), 2, true, null);
if (KeyStates.fire || mouse.buttonDown(0) || mouse.buttonDown(1) || KeyStates.exit) {
KeyStates.exit = false;
KeyStates.fire = false;
creditMode = false;
serverSel.setVisible(true);
while (mouse.buttonDown(0)) {
try {
Thread.sleep(10);
buffer.displayGLOnly();
} catch (Exception e) {
}
}
}
}
}
if (KeyStates.tab && hiView != null) {
int width = hiView.getWidth();
int height = hiView.getHeight();
buffer.blit(TextureManager.getInstance().getTexture("highback"), 0, 0, hiView.getX() - 8, hiView.getY() - 8, 128, 128, width + 7, height + 14, 13, false, null);
hiView.draw(buffer);
}
}
private void drawMessages() {
messages.draw(buffer);
if (roundMessage == null || !roundMessage.isVisible()) {
clickMessage.draw(buffer);
}
if (roundMessage != null) {
if (roundMessage.isVisible()) {
int width = buffer.getOutputWidth();
int height = width / 2;
int start = buffer.getOutputHeight() / 2 - height / 2;
Texture tex = textBanner;
if (!roundWon) {
tex = textBannerDead;
}
buffer.blit(darken, 0, 0, 0, 0, 16, 16, width, buffer.getOutputHeight(), 5, false, null);
buffer.blit(tex, 0, 0, 0, start, 512, 256, width, height, 20, false, null);
}
roundMessage.draw(buffer);
}
}
private void taunt() {
int taunt = -1;
if (KeyStates.one) {
taunt = 0;
}
if (KeyStates.two) {
taunt = 1;
}
if (KeyStates.three) {
taunt = 2;
}
if (KeyStates.four) {
taunt = 3;
}
if (KeyStates.five) {
taunt = 4;
}
if (KeyStates.six) {
taunt = 5;
}
if (KeyStates.seven) {
taunt = 6;
}
if (KeyStates.eight) {
taunt = 7;
}
if (KeyStates.nine) {
taunt = 8;
}
if (KeyStates.ten) {
taunt = 9;
}
if (taunt != -1 && tauntTicker.getTicks() > 0) {
Event ev = new Event(Event.TAUNT, -99, -99, -99);
ev.setOrigin(player.getPosition());
ev.setValue(taunt);
eventQueue.add(ev);
tauntTicker.reset();
}
}
/**
* The game loop. This is where the game...well...loops...:-)
*
* @throws Exception
*/
private void gameLoop() throws Exception {
Ticker ticker = new Ticker(20);
blo = new com.threed.jpct.procs.BloomGLProcessor(15, 4, 1, 1);
// ((com.threed.jpct.procs.BloomGLProcessor) blo).setCombining(false);
buffer.addPostProcessor(blo);
Color clearColor = new Color(134, 178, 238);
int fps = 0;
int lfps = 0;
long sleepDiv = 0;
long start = Ticker.getTime();
Texture blood = TextureManager.getInstance().getTexture("blood");
int xw = buffer.getOutputWidth();
int yw = buffer.getOutputHeight();
// Do this once to init things...
world.renderScene(buffer);
world.draw(buffer);
int sleepy = (int) ((1000f / (float) Globals.frameLimit) + 0.5f);
Thread.currentThread().setPriority(Thread.NORM_PRIORITY + 1);
while (!quit) {
// System.out.println(state.getState());
checkWaitingState();
if (disConnectScheduled) {
try {
disconnect();
} catch (Exception e) {
// Don't care...
}
}
if (reloadScheduled) {
reloadScheduled = false;
createMessageText("Loading...", false);
clickMessage.setVisible(true);
buffer.clear(clearColor);
clickMessage.draw(buffer);
buffer.update();
buffer.displayGLOnly();
prepare();
clickMessage.setVisible(false);
tbTimer.reset();
}
long ft = Ticker.getTime();
int ticks = ticker.getTicks();
if (ticks > 0) {
if (!serverSel.isVisible()) {
KeyStates.poll(keyMapper);
}
if (state.getState() >= NetState.STATE_WAITING) {
synchronized (SYNC) {
updatePlayer(ticks);
fire(ticks);
taunt();
updatePlayerView(ticks);
updateRemoteEntities(ticks, false);
updateCrates(ticks);
level.getCrateManager().processGlows(ticks, level, player);
bombMan.processLocalBombs(player, level, ticks);
checkTimeout();
updateExplosions(ticks);
if (eventQueue != null && clientImpl != null) {
eventQueue.processLocalEvents(this, clientImpl.getClientID());
}
}
updateCamera(ticks);
// Thread.yield();
updateParticles(ticks);
cleanUp();
}
modified = true;
if (clientImpl != null && Globals.activeTransfer) {
clientImpl.triggerTransfer();
}
} else {
Thread.yield();
}
if (spawned && !disConnectScheduled) {
// Event processing is synced to the world too now.
// That way, the drawing doesn't have to be synchronized to SYNC
if (!shadows) {
buffer.clear(clearColor);
if (skyBox != null) {
skyBox.render(world, buffer);
}
synchronized (world) {
level.shadowPolygonsVisible(false);
world.renderScene(buffer);
}
world.draw(buffer);
} else {
synchronized (world) {
if (refHelper != null) {
refHelper.drawScene(world, buffer);
}
shadower.updateShadowMap();
buffer.clear(clearColor);
if (skyBox != null) {
skyBox.render(world, buffer);
}
level.shadowPolygonsVisible(false);
shadower.drawScene(false);
level.shadowPolygonsVisible(true);
}
world.draw(buffer);
}
if (KeyStates.bloom) {
buffer.runPostProcessors();
}
if (KeyStates.wireFrame) {
world.drawWireframe(buffer, Color.WHITE);
}
} else {
buffer.clear(clearColor);
}
cheats();
if (clientImpl != null && !clientImpl.isConnected() && shouldBeConnected) {
messages.insertCell(2, 0, "Disconnected from Server!");
serverSel.setVisible(true);
shouldBeConnected = false;
}
if (player != null && player.isDead() && spawned && !roundCompleted) {
buffer.blit(blood, 0, 0, 0, 0, 512, 512, xw, yw, 17, false, null);
}
// if (shadower!=null) {
// System.out.println(shadower.getReceiverCount()+"/"+shadower.getCasterCount());
// }
TextBlitter.blitText(smallFont, buffer, lfps + " fps", 5, buffer.getOutputHeight() - 12, Color.YELLOW);
if (state.getState() >= NetState.STATE_RUNNING && Ticker.hasNotPassed(levelNameTime, 6000)) {
TextBlitter.blitText(buffer, "Welcome to '" + levelName + "'", 5, 10);
}
if (state.getState() == NetState.STATE_RUNNING) {
icons.paintIcons(player, buffer);
}
drawMessages();
if (state.getState() != NetState.STATE_PREPARING) {
drawGUI();
}
if (Ticker.hasPassed(start, 1000)) {
start = Ticker.getTime();
lfps = fps;
fps = 0;
}
buffer.update();
buffer.displayGLOnly();
if (mayTalkBack && state.getState() >= NetState.STATE_WAITING && tbTimer.getTicks() > 0) {
TalkBack.talkBack(buffer);
mayTalkBack = false;
}
fps++;
ft = Ticker.getTime() - ft;
throttling = KeyStates.throttle;
long sleepTime = Math.max(trottleVal, sleepy - ft) - sleepDiv;
if (sleepTime < 0) {
// Sanity check, but this shouldn't happen
sleepTime = 0;
}
if (throttling) {
long st = Ticker.getTime();
Thread.sleep(sleepTime); // Gives network and other threads some
// time to breath
long et = Ticker.getTime();
sleepDiv = (et - st) - sleepTime;
if (!Globals.correctSleepTime) {
sleepDiv = 0;
}
} else {
Thread.yield();
}
/*
* if (!runsServer()) { Thread.sleep(25); }
*/
if (KeyStates.exit) {
serverSel.setVisible(!serverSel.isVisible());
KeyStates.exit = false;
}
if (org.lwjgl.opengl.Display.isCloseRequested()) {
quit();
}
}
}
private void cheats() {
if (bombMan != null) {
if (KeyStates.lifeTime) {
bombMan.setLifeTime(200000);
} else {
bombMan.setLifeTime(2000);
}
}
if (KeyStates.populate) {
KeyStates.populate = false;
synchronized (SYNC) {
level.populate(bombMan, clientImpl, world, eventQueue);
}
}
if (KeyStates.nextLevel) {
KeyStates.nextLevel = false;
nextLevel();
}
if (KeyStates.f1) {
NetGlobals.clientWaitTime = 30;
}
if (KeyStates.f2) {
NetGlobals.clientWaitTime = 50;
}
if (KeyStates.f3) {
NetGlobals.clientWaitTime = 80;
}
}
/**
* Load resources like textures, the level etc.
*
* @throws Exception
*/
private void loadTextures() throws Exception {
TextureUtils.loadGameTextures();
TextureManager tm = TextureManager.getInstance();
textBanner = tm.getTexture("textbanner");
textBannerDead = tm.getTexture("textbannerLost");
darken = tm.getTexture("black");
}
private void loadSounds() {
SoundUtils.loadSounds();
}
private void loadLevel() throws Exception {
System.gc();
System.runFinalization();
decals = new DecalManager(world);
MapInfo mi = selectedMaps.get(getMapNumber());
levelName = mi.getRealName();
Logger.log("Loading level " + mi.getName() + "...", Logger.MESSAGE);
level = new Level("data/levels/" + mi.getName(), mi.getSet(), world, eventQueue, decals, false);
Camera cam = world.getCamera();
cam.setFOV(orgFOV);
createSpawnPoints();
setLighting();
}
private void setLighting() {
world.removeAllLights();
int col = 100;
if (buffer.supports(FrameBuffer.SUPPORT_FOR_RGB_SCALING)) {
world.setAmbientLight(col >> 1, col >> 1, col >> 1);
} else {
world.setAmbientLight(col, col, col);
}
Projector proj = createProjector();
setSun(proj);
if (shadows) {
enableShadowing(proj);
if (coMan != null) {
coMan.setShadowHelper(shadower);
}
if (bombMan != null) {
bombMan.setShadowHelper(shadower);
}
level.makeReceiver(shadower);
level.getCrateManager().makeCaster(shadower);
}
if (Globals.enhancedGraphics && Globals.reflections) {
refHelper = level.enableReflections(buffer);
}
}
private void enableShadowing(Projector proj) {
if (shadows) {
shadower = new ShadowHelper(world, buffer, new Projector(), shadowSize);
shadower.setCullingMode(Globals.shadowCulling);
shadower.setLightSource(proj);
if (Config.glShadowZBias == 0.5f) {
Config.glShadowZBias = 0;
}
shadower.setFiltering(shadowFilter);
shadower.setAmbientLight(new Color(45, 45, 45));
}
}
private Projector createProjector() {
SimpleVector viewPos = level.getCenter();
viewPos.y -= 200;
viewPos.z -= 100;
Camera cam = level.createAllViewingCamera(viewPos, buffer);
Projector proj = new Projector();
proj.setFOVLimits(0, 100);
proj.setPosition(cam.getPosition());
proj.setBack(cam.getBack());
proj.setFOV(cam.getFOV());
proj.setYFOV(cam.getYFOV());
return proj;
}
private void setSun(Projector proj) {
Light light = new Light(world);
light.setPosition(proj.getPosition());
light.setAttenuation(-1);
light.setDiscardDistance(-1);
int col = 100;
if (Globals.compiledObjects) {
col = 200;
}
light.setIntensity(new SimpleVector(col, col, col));
}
/**
* Terminate everything including the VM.
*
* @throws Exception
*/
private void exit() throws Exception {
if (clientImpl != null) {
clientImpl.disconnect();
while (clientImpl.isConnected()) {
Thread.sleep(20);
}
}
SoundManager.getInstance().dispose();
Thread.sleep(200);
// buffer.disableRenderer(IRenderer.RENDERER_OPENGL); // Causes a crash
// on some machines...
buffer.dispose();
System.out.println("Game terminated!");
Thread.sleep(300);
System.exit(0);
}
/**
* Updates the local player. Albeit the local player is no mesh, this method
* takes care of setting the correct animation because that will be
* transfered to the server and all other clients.
*
* @param ticks
* long the number of ticks passed
*/
private void updatePlayer(long ticks) {
if (state.getState() == NetState.STATE_RUNNING && allPlayersHaveSpawned()) {
// System.out.println("Player at :"+level.getMask().getGrid(player.getPosition().x,
// player.getPosition().z));
coMan.enterCollisionMode();
bombMan.enterCollisionMode(player);
bombMan.moveBombs(world, ticks);
if (!player.isDead()) {
if (!firing) {
player.getPlayerPowers().addWater(ticks);
} else {
if (!hasToRelease) {
player.getPlayerPowers().useWater(ticks << 1);
}
}
playerView.setVisibility(false);
boolean moved = player.move(world, keyStates, mouse, ticks, dummy, forcedStepsBack);
if (forcedStepsBack > 0) {
forcedStepsBack -= ticks;
}
playerView.setVisibility(true);
if (moved) {
if (forcedStepsBack > 0) {
player.setAnimation(Animations.HIT);
player.setAnimationSpeed(30);
} else {
if (mouse.buttonDown(1)) {
player.setAnimation(Animations.CROUCH_MOVE);
player.setAnimationSpeed(20);
} else {
player.setAnimation(Animations.MOVE);
player.setAnimationSpeed(40);
}
}
} else {
if (mouse.buttonDown(1)) {
player.setAnimation(Animations.CROUCH_NONE);
} else {
player.setAnimation(Animations.NONE);
}
player.setAnimationSpeed(300);
}
} else {
if (Ticker.hasPassed(player.deadSince(), 1000)) {
player.setAnimation(Animations.DEAD);
if (!clickMessage.isVisible()) {
if (Ticker.hasPassed(player.deadSince(), 2000) && player.getSpecialValue() > 0 && !roundCompleted) {
createMessageText("Click to respawn!", true);
clickMessage.setVisible(true);
} else {
if (player.getSpecialValue() <= 0) {
createMessageText("You are DEAD!", true);
clickMessage.setVisible(true);
}
}
}
} else {
player.setAnimation(Animations.DIE);
}
player.setAnimationSpeed(80);
}
coMan.leaveCollisionMode();
bombMan.leaveCollisionMode();
if (clickMessage.isVisible() && player.getSpecialValue() > 0 && respawnTicker.getTicks() > 0 && player.isDead()) {
clickMessage.setVisible(false);
respawn();
}
}
}
private void updatePlayerView(long ticks) {
if (playerView != null && state.getState() == NetState.STATE_RUNNING) {
playerView.setToLocalObject(player);
playerView.process(ticks, level);
playerView.processSpecial(player);
}
}
private void updateCamera(int ticks) {
if (player != null) {
Camera camera = world.getCamera();
player.alignCamera(camera, ticks);
}
}
private void reInit(boolean withBrowser) throws Exception {
roundCompleted = false;
synchronized (world) {
roundMessage = null;
synchronized (KILL_SYNC) {
toKill.clear();
}
synchronized (SYNC) {
spawned = false;
world.removeAllObjects();
// Don't change the unload order to be nice to the
// TextureManager
// One has to know how it works internaly to optimize this, but
// i do...:-)
if (coMan != null) {
// Unload player textures!
Colorizer.getInstance().unload(buffer);
}
if (shadower != null) {
shadower.dispose();
shadower = null;
}
if (refHelper != null) {
TextureManager.getInstance().unloadTexture(buffer, refHelper.getReflectionTexture());
refHelper = null;
}
world.removeAllLights();
bombMan = null;
level = null;
loadLevel();
initWorld();
initPlayer();
if (withBrowser) {
initBrowser();
}
initClient();
initPlayerView();
}
// System.gc();
}
}
}