/* * Copyright (C) 2012 JPII and contributors * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.jpii.navalbattle.pavo; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; import java.awt.Polygon; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.awt.event.MouseWheelEvent; import java.awt.geom.Point2D; import java.awt.image.BufferedImage; import java.io.Serializable; import java.util.Calendar; import com.jpii.navalbattle.NavalBattle; import com.jpii.navalbattle.data.RoketGamerData; import com.jpii.navalbattle.game.NavalClient; import com.jpii.navalbattle.game.NavalServer; import com.jpii.navalbattle.pavo.grid.Entity; import com.jpii.navalbattle.pavo.grid.GridedEntityTileOrientation; import com.jpii.navalbattle.pavo.grid.Location; import com.jpii.navalbattle.pavo.grid.Tile; import com.jpii.navalbattle.pavo.gui.GridWindow; import com.jpii.navalbattle.pavo.gui.NewWindowManager; import com.jpii.navalbattle.pavo.gui.controls.PWindow; import com.jpii.navalbattle.pavo.io.PavoClient; import com.jpii.navalbattle.pavo.io.PavoImage; import com.jpii.navalbattle.pavo.io.PavoServer; import com.jpii.navalbattle.util.FileUtils; import com.jpii.navalbattle.util.GameStatistics; import com.jpii.navalbattle.util.RoketUtils; public class Game extends Renderable implements Runnable, Serializable { private static final long serialVersionUID = 1L; private Thread updator; private Thread chunkrender; private Thread renderer; private boolean gameRunning = true; private int state = 0; private World world; private long numUpdates = 0; private boolean forceUpdate = false; private int lastTime = -1; private int lastw = 0, lasth = 0; private NewWindowManager windowsnt; private PavoImage shadow; public static Game Instance; private NavalClient client; private PavoServer server; private boolean isClient = false; private boolean needsPumping = false; public static PavoSettings Settings = new PavoSettings(); /** * Creates a new instance of the game. */ public Game(WorldSize ws) { server = new NavalServer(this); //System.out.println("Server status: " + server.start()); windowsnt = new NewWindowManager(this); world = new World(this,ws); threadInit(); buffer = new PavoImage(Game.Settings.currentWidth,Game.Settings.currentHeight,BufferedImage.TYPE_3BYTE_BGR); shadow = (PavoImage)PavoHelper.createInnerShadow(Game.Settings.currentWidth,Game.Settings.currentHeight); int yeart = Calendar.getInstance().get(Calendar.YEAR); String years = Integer.toString(yeart); yearf = Integer.parseInt(years.substring(0,2)); yearl = Integer.parseInt(years.substring(2)); Instance = this; } /** * Creates a new instance of the game with given * startup parameters. * @param pos The type of state to open the game * in. * @param flags The flags/parameters for the * <code>PavoOpenState</code>. */ public Game(WorldSize ws,PavoOpenState pos, String flags) { if (pos == PavoOpenState.OPEN_SERVER) { client = new NavalClient(this,flags); System.out.println("Client status: " + client.start()); isClient = true; //client.send("HELLO"); //client.send("HELLO"); //client.send("HELLO"); while (client.getSeed() == Long.MIN_VALUE) { } akamaideli3242very(); Game.Settings.seed = client.getSeed(); NavalBattle.getWindowHandler().getToasterManager().setDisplayTime(8000); NavalBattle.getWindowHandler().getToasterManager().showToaster("Sucessfully connected to the server."); } windowsnt = new NewWindowManager(this); world = new World(this,ws); threadInit(); buffer = new PavoImage(Game.Settings.currentWidth,Game.Settings.currentHeight,BufferedImage.TYPE_3BYTE_BGR); shadow = (PavoImage)PavoHelper.createInnerShadow(Game.Settings.currentWidth,Game.Settings.currentHeight); int yeart = Calendar.getInstance().get(Calendar.YEAR); String years = Integer.toString(yeart); yearf = Integer.parseInt(years.substring(0,2)); yearl = Integer.parseInt(years.substring(2)); Instance = this; } boolean isConnected = false; boolean ranCheckup = false; /** * Determines if currently connected to a client, or * to server. * @return */ public boolean isConnectedToClientOrServer() { return isConnected; } /** * No touching. */ public void akamaideli3242very() { isConnected = true; } /** * Gets the client (if the current workstation * is acting as a client). * * Use <code></code> * @return */ public PavoClient getSelfClient() { return client; } /** * Gets the server (if the current workstation us * acting as a server). * * Use <code></code> * @return */ public PavoServer getSelfServer() { return server; } /** * Determines whether the current workstation is * acting as a client or as a server. * * @return true if the workstation is a client, * false if the workstation is a server. */ public boolean isAClient() { return isClient; } public void shutdown() { //if (isAClient()) //this.getSelfClient().halt(); //else //this.getSelfServer().stop(); //System.out.println("s"); gameRunning = false; try { Thread.sleep(250); } catch (Throwable t) { } } /** * Gets the window manager for the Game. * @return */ public NewWindowManager getWindows() { return windowsnt; } /** * Gets the total number of updates that the updater has performed. * @return */ public long getNumUpdates() { return numUpdates; } /** * Don't play with. */ private void threadInit() { int js = 0; if (Settings.OverClock) js = Thread.MAX_PRIORITY; else js = Thread.NORM_PRIORITY; updator = new Thread(this); state = 1; updator.setPriority(js); updator.setName("updatorThread"); updator.setDaemon(true); updator.start(); updator.setPriority(js); long lastStart = System.currentTimeMillis(); while (lastStart + 500 > System.currentTimeMillis()) { } chunkrender = new Thread(this); state = 2; chunkrender.setPriority(js); chunkrender.setName("chunkGenThread"); chunkrender.setDaemon(true); chunkrender.start(); chunkrender.setPriority(js); lastStart = System.currentTimeMillis(); while (lastStart + 500 > System.currentTimeMillis()) { } state = 4; renderer = new Thread(this); state = 5; renderer.setPriority(js); renderer.setName("worldRenderingThread"); renderer.setDaemon(true); renderer.start(); renderer.setPriority(js); } private static GameStatistics stats = new GameStatistics(); /** * The graphics statistics for the game. * @return */ public static GameStatistics getStats() { return stats; } BufferedImage loadMotionImage = null; boolean moveStandard = false; /** * Immortal caller. */ public void run() { if (state == 1) { while (gameRunning) { while (!forceUpdate) { ;;; } if (lastw != Settings.currentWidth || lasth != Settings.currentHeight) { lastw = Settings.currentWidth; lasth = Settings.currentHeight; getWindows().$akafre(); } numUpdates += 100; forceUpdate = false; long updateStart = System.currentTimeMillis(); while (getWorld().isLocked()) {} getWorld().lock(); if (needsPumping) { for (int c = 0; c < getWorld().getTotalChunks(); c++) { Chunk chunk = getWorld().getChunk(c); getWorld().getEntityManager().AQms03KampOQ9103nmJMs((chunk.getZ()*2), (chunk.getX()*2), chunk.water00); getWorld().getEntityManager().AQms03KampOQ9103nmJMs((chunk.getZ()*2)+1, (chunk.getX()*2), chunk.water01); getWorld().getEntityManager().AQms03KampOQ9103nmJMs((chunk.getZ()*2), (chunk.getX()*2)+1, chunk.water10); getWorld().getEntityManager().AQms03KampOQ9103nmJMs((chunk.getZ()*2)+1, (chunk.getX()*2)+1, chunk.water11); } needsPumping = false; } getWorld().update(); getWorld().unlock(); TimeManager tim = getWorld().getTimeManager(); if (tim.getState() != lastTime) { lastTime = tim.getState(); if (lastTime == 3) { becomingDay(); } else if (lastTime == 2) { becomingSunrise(); } else if (lastTime == 1) { becomingNight(); } else if (lastTime == 0) { becomingSunset(); } } update(); long updateFinish = System.currentTimeMillis() - updateStart; getStats().SmSK280K99(updateFinish); if (!getStats().isGenerating() && !inStatement) { inStatement = true; try { String name = ""; if (chunkrender != null) name = chunkrender.getName(); chunkrender.interrupt(); chunkrender = null; System.gc(); System.out.println("Thread " + name + " is probably dead."); } catch (Throwable t) { } for (int c = 0; c < 5; c++) { System.gc(); } getWorld().getEntityManager().gameDoneGenerating(); if (isAClient()) { this.getSelfClient().send("Chunk gen has been complete!"); } else { this.getSelfServer().send("Chunk gen has been complete on the server!"); } } } } else if (state == 2) { while (gameRunning && getWorld().hasMoreChunks()) { if (getWorld().hasMoreChunks()) { getWorld().genNextChunk(); long start = System.currentTimeMillis(); while (start + 150 > System.currentTimeMillis()) { ;;; } } else { break; } } for (int c = 0; c < getWorld().getTotalChunks(); c++) { Chunk chunk = getWorld().getChunk(c); getWorld().getEntityManager().AQms03KampOQ9103nmJMs((chunk.getZ()*2), (chunk.getX()*2), chunk.water00); getWorld().getEntityManager().AQms03KampOQ9103nmJMs((chunk.getZ()*2)+1, (chunk.getX()*2), chunk.water01); getWorld().getEntityManager().AQms03KampOQ9103nmJMs((chunk.getZ()*2), (chunk.getX()*2)+1, chunk.water10); getWorld().getEntityManager().AQms03KampOQ9103nmJMs((chunk.getZ()*2)+1, (chunk.getX()*2)+1, chunk.water11); } needsPumping = true; while (needsPumping) { } getWorld().getWorldStatus().NOTOUCH_930202894(0); Game.getStats().SmKdn02nOaP(1); } else if (state == 4) { while (gameRunning) { long start = System.currentTimeMillis(); while (start + 250 > System.currentTimeMillis()) { PavoHelper.threadSleep(); } } } else if (state == 5) { while (gameRunning && Settings.isUsingMultithreadedRenderer) { while (getWorld().isLocked()) { } getWorld().lock(); getWorld().render(); getWorld().unlock(); } } System.out.println("Thread " + Thread.currentThread().getName() + " is prepairing to exit context."); System.gc(); } boolean inStatement = false; public String getGenStatus() { return ""; } /** * Unknown * @return * @deprecated */ public int getGenAmount() { return 1; } int lkw = 0, lkh = 0; /** * Renders the Game. */ public void render() { long sjan = System.currentTimeMillis(); if (lkw != Game.Settings.currentWidth || lkh != Game.Settings.currentHeight) { buffer = new PavoImage(Game.Settings.currentWidth,Game.Settings.currentHeight,BufferedImage.TYPE_3BYTE_BGR); lkw = Game.Settings.currentWidth; lkh = Game.Settings.currentHeight; } Graphics2D g = PavoHelper.createGraphics(buffer); while (getWorld().isLocked()) { } getWorld().lock(); if (!Settings.isUsingMultithreadedRenderer) getWorld().render(); // g.translate(-640,-480); // g.scale(1,0.75f); // g.shear(0.45f,0); g.drawImage(getWorld().getBuffer(),0,0,null); // g.shear(-0.45f,0); // g.scale(1,1.333333333333333f); // g.translate(640,480); g.drawImage(getWorld().getTimeManager().getBuffer(),0,0,null); GameStatistics gs = getStats(); g.setColor(Color.red); g.drawString("Idling (should be low):" + gs.getDrawIdling() + ". Draw time:" + gs.getDrawTime() + " Live chunks:" + gs.getLiveChunks(),12,660); g.drawString("Is generating? " + gs.isGenerating() + ". Total update time:" + gs.getUpdateTime() + ". Last render length:" + gs.getTotalUpdate() + ". Current network state: " + Game.Settings.currentNetworkState, 12,690); getWorld().unlock(); while (getWindows().isLocked()) { } getWindows().lock(); if (gJsiw) g.setXORMode(Color.yellow); for (int c = 0; c < getWindows().size(); c++) { PWindow gw = getWindows().get(c); if (gw instanceof GridWindow && gw.isVisible()) { GridWindow gr = (GridWindow)gw; Location l = gr.getGridLocation(); if (l != null) { Chunk chunk = PavoHelper.convertGridLocationToChunk(getWorld(), l); if (chunk != null && PavoHelper.isChunkVisibleOnScreen(getWorld(), chunk)) { g.setColor(Color.red); int ssx = (getWorld().getScreenX())+(l.getCol()*50)+25; int ssy = (getWorld().getScreenY())+(l.getRow()*50)+25; int midx = gr.getLocX()+(gr.getWidth()/2); int midy = gr.getLocY()+(gr.getHeight()/2); if (Math.sqrt(Math.pow(ssx-midx,2)+Math.pow(ssy-midy,2)) <= gr.getDistanceConstraint()) { Polygon p = new Polygon(); p.addPoint(ssx,ssy); p.addPoint(midx-10,midy-10); p.addPoint(midx+10,midy+10); p.addPoint(ssx,ssy); g.fillPolygon(p); g.setColor(Color.black); g.drawPolygon(p); } } } } } int tol = 20; if (motionEnt != null && motionEnt.readyForMove) { Entity e = motionEnt; if (loadMotionImage == null) { motionDest = PavoHelper.convertLocationToScreen(getWorld(),e.getLocation()); } else { Point p = PavoHelper.convertLocationToScreen(getWorld(),motionDestiny); if ((p.x - tol < motionDest.x && p.x + tol > motionDest.x && p.y - tol < motionDest.y - tol && p.y + tol > motionDest.y) || (motionDest.x < 3 && motionDest.y < 3)) { // its there! motionEnt = null; loadMotionImage = null; motionDest = null; e.moveTo(motionDestiny); e = null; motionDestiny = null; } else { motionDest = movePointTowards(motionDest,p,2); //motionDest = new Point(motionDest.x,motionDest.y+4); } } } if (motionEnt != null && motionEnt.readyForMove) { Entity e = motionEnt; if (e != null) g.drawImage(this.loadMotionImage, motionDest.x,motionDest.y,null); } if (PavoHelper.getCalculatedSystemSpeed() != SystemSpeed.CREEPER && PavoHelper.getCalculatedSystemSpeed() != SystemSpeed.TURTLE) { g.drawImage(shadow,0,0,null); } g.drawImage(getWindows().getBuffer(),0,0,null); g.dispose(); getWindows().unlock(); Game.getStats().sBm3ns02AKa99mqp392(System.currentTimeMillis() - sjan); } Entity motionEnt; float motionSpeed = 2.35f; Point motionDest = new Point(0,0); Location motionDestiny = Location.Unknown; public void onWorldChange() { if (motionEnt != null) { motionEnt.moveTo(motionDestiny); } motionEnt = null; loadMotionImage = null; } public boolean NOTOUCH_primitivesbeinginvoked() { if (motionEnt == null) { return false; } else return true; } public void setAnimatedMotion(Entity motionEntity,Location destiny) { if (motionEnt != null) { motionEnt.moveTo(motionDestiny); motionEnt = null; loadMotionImage = null; } String w6 = motionEntity.imgLocation; if (motionEntity.getCurrentOrientation() == GridedEntityTileOrientation.ORIENTATION_TOPTOBOTTOM) { w6 = w6.replace(".png", "_S.png"); } motionEnt = motionEntity; motionDestiny = destiny; motionDest = PavoHelper.convertLocationToScreen(getWorld(),motionEntity.getLocation()); loadMotionImage = FileUtils.getImage(w6); Graphics g = loadMotionImage.getGraphics(); Color copy = PavoHelper.changeAlpha(PavoHelper.convertByteToColor(motionEnt.getTeamColor()), 100); for (int x = 0; x < loadMotionImage.getWidth(); x++) { for (int y = 0; y < loadMotionImage.getHeight(); y++) { int pixel = loadMotionImage.getRGB(x,y); if((pixel>>24) != 0x00 ) { g.setColor(copy); g.drawLine(x,y,x,y); } } } g.dispose(); } public Point movePointTowards(Point a, Point b, int distance) { /*Point vector = new Point(b.x - a.x, b.y - a.y); int length = (int)Math.sqrt(vector.x * vector.x + vector.y * vector.y); Point unitVector = new Point(vector.x / length, vector.y / length); return new Point(a.x + unitVector.x * distance, a.y + unitVector.y * distance);*/ //nextLocation = a + UnitVector(a, b) * stepSize Point2D.Double vector = new Point2D.Double(b.x - a.x, b.y - a.y); double length = Math.sqrt(vector.x * vector.x + vector.y * vector.y); Point2D.Double unitVector = new Point2D.Double(vector.x / length, vector.y / length); Point move = new Point((int)(a.x + unitVector.x * 3.9),(int)(a.y + unitVector.y * 3.9)); //move.translate(Math.sqrt(Math)); return move; } /** * Gets the active world for the Game. * @return */ public World getWorld() { return world; } /** * Occurs when the game is going into sunset stage. */ public void becomingSunset() { } /** * Occurs when the game is going into sunrise stage. */ public void becomingSunrise() { } /** * Occurs when the game is going into night stage. */ public void becomingNight() { } /** * Occurs when the game is going into day time stage. */ public void becomingDay() { } /** * This method should be called sparingly (which means DO NOT OVER USE). This method is multithreaded, so it puts no stress on the calling thread. * This method is not actually deprecated, but it is called so to ensure that the above message is read. */ public void forceUpdate() { forceUpdate = true; } /** * Occurs when the mouse is moved. * @param me The mouse event for the motion. */ public void mouseMove(MouseEvent me) { if (getWindows().mouseMove(me)) { return; } int chx = (-getWorld().getScreenX()) + me.getX(); int chy = (-getWorld().getScreenY()) + me.getY(); chx /= 50; chy /= 50; if (chx < PavoHelper.getGameWidth(getWorld().getWorldSize()) * 2 && chy < PavoHelper.getGameHeight(getWorld().getWorldSize()) * 2 && chx >= 0 && chy >= 0) { Tile<Entity> e = (getWorld().getEntityManager().getTile(chy,chx)); if (e != null) { int acuratex = (-getWorld().getScreenX()) + me.getX() - (chx*50); int acuratey = (-getWorld().getScreenY()) + me.getY() - (chy*50); Location l = e.getEntity().getLocation(); acuratex += (chx - l.getCol())*50; acuratey += (chy - l.getRow())*50; e.getEntity().onMouseMove(acuratex,acuratey); } } lastmx = me.getX(); lastmy = me.getY(); } public void keyDown(KeyEvent ke) { } public void keyUp(KeyEvent ke) { } public void keyTyped(KeyEvent ke) { } /** * Occurs when the mouse wheel is changed. * @param mwe The mouse event for the * method. */ public void mouseWheelChange(MouseWheelEvent mwe) { } int lastmx = 0,lastmy = 0; int yearf = 0; int yearl = 0; boolean gJsiw = false; public boolean guiUsedMouseDown = false, guiUsedMouseUp = false, guiUsedMouseDrag = false; /** * Occurs when a mouse button is pushed. * @param me The mouse event for the * indicator. */ public void mouseDown(MouseEvent me) { guiUsedMouseDown = false; if (getWindows().mouseDown(me)) { guiUsedMouseDown = true; return; } int chx = (-getWorld().getScreenX()) + lastmx; int chy = (-getWorld().getScreenY()) + lastmy; chx /= 50; chy /= 50; if (chx < PavoHelper.getGameWidth(getWorld().getWorldSize()) * 2 && chy < PavoHelper.getGameHeight(getWorld().getWorldSize()) * 2 && chx >= 0 && chy >= 0) { Tile<Entity> e = getWorld().getEntityManager().getTile(chy,chx); if (e != null) { int acuratex = (-getWorld().getScreenX()) + lastmx - (chx*50); int acuratey = (-getWorld().getScreenY()) + lastmy - (chy*50); Location l = e.getEntity().getLocation(); acuratex += (chx - l.getCol())*50; acuratey += (chy - l.getRow())*50; e.getEntity().onMouseDown(acuratex,acuratey,me.getButton() == MouseEvent.BUTTON1); } } if (chx == yearf && chy == yearl) { gJsiw = !gJsiw; RoketUtils.submitAchievement(RoketGamerData.ACHIEVEMENT_DAVE); } } /** * Occurs when a mouse button is released. * @param me The mouse event for the * indicator. */ public void mouseUp(MouseEvent me) { guiUsedMouseUp = false; if (getWindows().mouseUp(me)) { guiUsedMouseUp = true; return; } } /** * Occurs when the mouse is dragged. * @param me The mouse event for the motion. */ public void mouseDragged(MouseEvent me) { guiUsedMouseDrag = false; if (getWindows().mouseDragged(me)) { guiUsedMouseDrag = true; return; } } /** * Occurs when the Game is shutting down. */ public void onShutdown() { } }