diff --git a/src/main/licenses/assimp_license.txt b/src/main/java/licenses/assimp_license.txt similarity index 100% rename from src/main/licenses/assimp_license.txt rename to src/main/java/licenses/assimp_license.txt diff --git a/src/main/java/licenses/commons_io_license.txt b/src/main/java/licenses/commons_io_license.txt new file mode 100644 index 00000000..6b0b1270 --- /dev/null +++ b/src/main/java/licenses/commons_io_license.txt @@ -0,0 +1,203 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/src/main/java/licenses/commons_io_notice.txt b/src/main/java/licenses/commons_io_notice.txt new file mode 100644 index 00000000..76643f65 --- /dev/null +++ b/src/main/java/licenses/commons_io_notice.txt @@ -0,0 +1,5 @@ +Apache Commons IO +Copyright 2002-2017 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). diff --git a/src/main/licenses/dyncall_license.txt b/src/main/java/licenses/dyncall_license.txt similarity index 100% rename from src/main/licenses/dyncall_license.txt rename to src/main/java/licenses/dyncall_license.txt diff --git a/src/main/licenses/glfw_license.txt b/src/main/java/licenses/glfw_license.txt similarity index 100% rename from src/main/licenses/glfw_license.txt rename to src/main/java/licenses/glfw_license.txt diff --git a/src/main/licenses/khronos_license.txt b/src/main/java/licenses/khronos_license.txt similarity index 100% rename from src/main/licenses/khronos_license.txt rename to src/main/java/licenses/khronos_license.txt diff --git a/src/main/licenses/openal_soft_license.txt b/src/main/java/licenses/openal_soft_license.txt similarity index 100% rename from src/main/licenses/openal_soft_license.txt rename to src/main/java/licenses/openal_soft_license.txt diff --git a/src/main/java/lwjglwindow/LWJGLWindow.java b/src/main/java/lwjglwindow/LWJGLWindow.java index 29de6236..5d8afe87 100755 --- a/src/main/java/lwjglwindow/LWJGLWindow.java +++ b/src/main/java/lwjglwindow/LWJGLWindow.java @@ -39,6 +39,14 @@ public class LWJGLWindow public double colorB; public double colorA; + protected double yaw = 0; + protected double pitch = 0; + protected double roll = 0; + + protected double xOffset = 0; + protected double yOffset = 0; + protected double zOffset = 0; + public ArrayList pressedKeys = new ArrayList(); public ArrayList validPressedKeys = new ArrayList(); @@ -68,6 +76,10 @@ public class LWJGLWindow public IUpdater updater; public IWindowHandler windowHandler; + public SoundPlayer soundPlayer; + + public boolean angled = false; + public LWJGLWindow(String name, int x, int y, int z, IUpdater u, IDrawer d, IWindowHandler w, boolean vsync, boolean showMouse) { this.name = name; @@ -79,6 +91,7 @@ public LWJGLWindow(String name, int x, int y, int z, IUpdater u, IDrawer d, IWin this.vsync = vsync; this.windowHandler = w; this.showMouseOnLaunch = showMouse; + this.soundPlayer = new SoundPlayer(); if (System.getProperties().toString().contains("Mac OS X")) mac = true; @@ -235,9 +248,6 @@ protected void loop() glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - int[] w = new int[1]; int[] h = new int[1]; glfwGetWindowSize(window, w, h); @@ -283,10 +293,11 @@ protected void loop() totalFrequency += frameFrequencies.get(i); } - frameFrequency = totalFrequency / frameFrequencies.size(); + frameFrequency = Math.max(0, totalFrequency / frameFrequencies.size()); } this.windowHandler.onWindowClose(); + this.soundPlayer.exit(); System.exit(0); } @@ -343,6 +354,39 @@ public void fillOval(double x, double y, double z, double sX, double sY, boolean } } + public void fillFacingOval(double x, double y, double z, double sX, double sY, boolean depthTest) + { + if (depthTest) + { + glEnable(GL_DEPTH_TEST); + glDepthMask(false); + } + + x += sX / 2; + y += sY / 2; + + int sides = (int) (sX + sY + 5); + + glTranslated(x, y, z); + this.addAngle(-this.yaw, -this.pitch, -this.roll); + + glBegin(GL_TRIANGLE_FAN); + for (double i = 0; i < Math.PI * 2; i += Math.PI * 2 / sides) + { + glVertex3d(Math.cos(i) * sX / 2, Math.sin(i) * sY / 2, 0); + } + + glEnd(); + + setPerspective(); + + if (depthTest) + { + glDepthMask(true); + glDisable(GL_DEPTH_TEST); + } + } + public void setColor(double r, double g, double b, double a) { glColor4d(r / 255, g / 255, b / 255, a / 255); @@ -675,20 +719,47 @@ protected void createImage(String image) e.printStackTrace(); } } - + + public void setAngles(double y, double p, double r) + { + this.yaw = y; + this.pitch = p; + this.roll = r; + + this.angled = !(this.yaw == 0 && this.pitch == 0 && this.roll == 0); + this.setPerspective(); + } + + public void setOffsets(double x, double y, double z) + { + this.xOffset = x; + this.yOffset = y; + this.zOffset = z; + this.setPerspective(); + } + + public void addAngle(double yaw, double pitch, double roll) + { + glMultMatrixd(new double[]{Math.cos(roll), -Math.sin(roll), 0, 0, Math.sin(roll), Math.cos(roll), 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}); + glMultMatrixd(new double[]{1, 0, 0, 0, 0, Math.cos(pitch), -Math.sin(pitch), 0, 0, Math.sin(pitch), Math.cos(pitch), 0, 0, 0, 0, 1}); + glMultMatrixd(new double[]{Math.cos(yaw), 0, -Math.sin(yaw), 0, 0, 1, 0, 0, Math.sin(yaw), 0, Math.cos(yaw), 0, 0, 0, 0, 1}); + } + public void setPerspective() { + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum(-absoluteWidth / (absoluteDepth * 2.0), absoluteWidth / (absoluteDepth * 2.0), absoluteHeight / (absoluteDepth * 2.0), -absoluteHeight / (absoluteDepth * 2.0), 1, absoluteDepth * 2); - glTranslated(-absoluteWidth / 2, -absoluteHeight / 2, -absoluteDepth); - - //double ang1 = Math.PI / 8; - //glMultMatrixd(new double[]{Math.cos(ang1), -Math.sin(ang1), 0, 0, Math.sin(ang1), Math.cos(ang1), 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}); - //double ang2 = -Math.PI * 2 / 16; - //glMultMatrixd(new double[]{1, 0, 0, 0, 0, Math.cos(ang2), -Math.sin(ang2), 0, 0, Math.sin(ang2), Math.cos(ang2), 0, 0, 0, 0, 1}); + glTranslated(0, 0, -absoluteDepth); + + glMultMatrixd(new double[]{Math.cos(this.roll), -Math.sin(this.roll), 0, 0, Math.sin(this.roll), Math.cos(this.roll), 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}); + glMultMatrixd(new double[]{1, 0, 0, 0, 0, Math.cos(this.pitch), -Math.sin(this.pitch), 0, 0, Math.sin(this.pitch), Math.cos(this.pitch), 0, 0, 0, 0, 1}); + glMultMatrixd(new double[]{Math.cos(this.yaw), 0, -Math.sin(this.yaw), 0, 0, 1, 0, 0, Math.sin(this.yaw), 0, Math.cos(this.yaw), 0, 0, 0, 0, 1}); + + glTranslated(absoluteWidth * (-0.5 + xOffset), absoluteHeight * (-0.5 + yOffset), absoluteDepth * zOffset); - //double ang3 = Math.PI / 8; - //glMultMatrixd(new double[]{Math.cos(ang3), 0, -Math.sin(ang3), 0, 0, 1, 0, 0, Math.sin(ang3), 0, Math.cos(ang3), 0, 0, 0, 0, 1}); //glOrtho(0, absoluteWidth, absoluteHeight, 0, -1, 1); } @@ -698,9 +769,6 @@ public void drawImage(double x, double y, double sX, double sY, double u1, doubl if (!textures.containsKey(image)) createImage(image); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - setPerspective(); glMatrixMode(GL_MODELVIEW); diff --git a/src/main/java/lwjglwindow/SoundPlayer.java b/src/main/java/lwjglwindow/SoundPlayer.java new file mode 100644 index 00000000..f9b7b64c --- /dev/null +++ b/src/main/java/lwjglwindow/SoundPlayer.java @@ -0,0 +1,135 @@ +package lwjglwindow; + +import org.apache.commons.io.IOUtils; +import org.lwjgl.openal.*; +import org.lwjgl.system.*; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.*; +import java.util.ArrayList; +import java.util.HashMap; + +import static org.lwjgl.openal.AL10.*; +import static org.lwjgl.openal.ALC10.*; +import static org.lwjgl.stb.STBVorbis.*; +import static org.lwjgl.system.MemoryStack.*; +import static org.lwjgl.system.libc.LibCStdlib.*; + +public class SoundPlayer +{ + public long context; + public long device; + + public HashMap buffers = new HashMap(); + public ArrayList sources = new ArrayList(); + + public SoundPlayer() + { + String defaultDeviceName = alcGetString(0, ALC_DEFAULT_DEVICE_SPECIFIER); + device = alcOpenDevice(defaultDeviceName); + + int[] attributes = {0}; + context = alcCreateContext(device, attributes); + alcMakeContextCurrent(context); + + ALCCapabilities alcCapabilities = ALC.createCapabilities(device); + ALCapabilities alCapabilities = AL.createCapabilities(alcCapabilities); + } + + public void playSound(String path) + { + playSound(path, 1); + } + + public void playSound(String path, float pitch) + { + playSound(path, pitch, 1); + } + + public void playSound(String path, float pitch, float volume) + { + if (sources.size() >= 256) + alDeleteSources(sources.remove(0)); + + if (this.buffers.get(path) == null) + createSound(path); + + int bufferPointer = this.buffers.get(path); + + int sourcePointer = alGenSources(); + alSourcei(sourcePointer, AL_BUFFER, bufferPointer); + alSourcef(sourcePointer, AL_PITCH, pitch); + alSourcef(sourcePointer, AL_GAIN, volume); + + alSourcePlay(sourcePointer); + + sources.add(sourcePointer); + } + + protected void createSound(String path) + { + ShortBuffer rawAudioBuffer = null; + + int channels = -1; + int sampleRate = -1; + + try (MemoryStack stack = stackPush()) + { + //Allocate space to store return information from the function + IntBuffer channelsBuffer = stack.mallocInt(1); + IntBuffer sampleRateBuffer = stack.mallocInt(1); + + InputStream in = getClass().getResourceAsStream(path); + byte[] bytes = IOUtils.toByteArray(in); + ByteBuffer b = MemoryUtil.memAlloc(bytes.length); + b.put(bytes); + b.flip(); + + rawAudioBuffer = stb_vorbis_decode_memory(b, channelsBuffer, sampleRateBuffer); + in.close(); + + //Retreive the extra information that was stored in the buffers by the function + channels = channelsBuffer.get(0); + sampleRate = sampleRateBuffer.get(0); + } + catch (IOException e) + { + e.printStackTrace(); + } + + //Find the correct OpenAL format + int format = -1; + if (channels == 1) + { + format = AL_FORMAT_MONO16; + } + else if (channels == 2) + { + format = AL_FORMAT_STEREO16; + } + + //Request space for the buffer + int bufferPointer = alGenBuffers(); + + //Send the data to OpenAL + alBufferData(bufferPointer, format, rawAudioBuffer, sampleRate); + + //Free the memory allocated by STB + free(rawAudioBuffer); + + this.buffers.put(path, bufferPointer); + } + + public void exit() + { + alcDestroyContext(context); + alcCloseDevice(device); + + for (String s: this.buffers.keySet()) + { + int i = this.buffers.get(s); + alDeleteBuffers(i); + } + } +} diff --git a/src/main/java/tanks/AreaEffectFreeze.java b/src/main/java/tanks/AreaEffectFreeze.java index af4f5c48..6b8ef6ee 100755 --- a/src/main/java/tanks/AreaEffectFreeze.java +++ b/src/main/java/tanks/AreaEffectFreeze.java @@ -1,6 +1,8 @@ package tanks; import tanks.AttributeModifier.Operation; +import tanks.event.EventCreateFreezeEffect; +import tanks.gui.screen.ScreenPartyLobby; public class AreaEffectFreeze extends AreaEffect { @@ -8,9 +10,14 @@ public class AreaEffectFreeze extends AreaEffect public AreaEffectFreeze(double x, double y) { super(x, y); + this.isRemote = ScreenPartyLobby.isClient; this.constantlyImbue = false; this.imbueEffects(); this.maxAge = 600; + this.drawLevel = 9; + + if (!this.isRemote) + Game.eventsOut.add(new EventCreateFreezeEffect(this)); } @Override @@ -42,7 +49,7 @@ public void imbueEffects() { Movable m = Game.movables.get(i); - if (Movable.distanceBetween(this, m) <= this.size / 2) + if (Movable.distanceBetween(this, m) <= this.size / 2 && !m.destroy) { AttributeModifier a = new AttributeModifier("freeze", "velocity", Operation.multiply, -1); a.duration = 600; @@ -57,11 +64,15 @@ public void imbueEffects() @Override public void draw() { - double size = Math.min(this.size + Game.tank_size / 2, this.age * 8); + double size = Math.min(this.size + Game.tank_size / 2, this.age * 8); for (int i = (int) Math.max(0, size - ((int) (50 * Math.min(100, 600 - this.age) / 100.0))); i < size; i += 2) { Drawing.drawing.setColor(200, 255, 255, 10); - Drawing.drawing.fillOval(this.posX, this.posY, i, i); + + if (Game.enable3d) + Drawing.drawing.fillOval(this.posX, this.posY, (size - i) + Game.tank_size / 4, i, i, true, false); + else + Drawing.drawing.fillOval(this.posX, this.posY, i, i); } } diff --git a/src/main/java/tanks/Crusade.java b/src/main/java/tanks/Crusade.java index 3f2cbf3e..c14b0502 100755 --- a/src/main/java/tanks/Crusade.java +++ b/src/main/java/tanks/Crusade.java @@ -1,8 +1,12 @@ package tanks; +import tanks.event.EventBeginCrusade; +import tanks.event.EventLoadCrusadeHotbar; import tanks.hotbar.Coins; import tanks.hotbar.Item; import tanks.hotbar.ItemBar; +import tanks.tank.TankPlayer; +import tanks.tank.TankPlayerRemote; import java.io.File; import java.io.FileNotFoundException; @@ -20,17 +24,15 @@ public class Crusade public boolean lose = false; public boolean lifeGained = false; - + public int currentLevel = 0; + public ArrayList levels = new ArrayList(); - public int remainingLives = 3; public int bonusLifeFrequency = 3; - + public int startingLives = 3; + public ArrayList crusadeItems = new ArrayList(); - - public ItemBar itemBar = new ItemBar(Panel.panel.hotbar); - public Coins coins = new Coins(); - + public String name = ""; public Crusade(ArrayList levelArray, String name) @@ -61,7 +63,6 @@ public Crusade(File f, String name) { Game.exitToCrash(e); } - } public void initialize(ArrayList levelArray, String name) @@ -91,11 +92,11 @@ public void initialize(ArrayList levelArray, String name) } else if (parsing == 1) { - this.crusadeItems.add(Item.parseItem(s)); + this.crusadeItems.add(Item.parseItem(null, s)); } else if (parsing == 2) { - this.remainingLives = Integer.parseInt(s.split(",")[0]); + this.startingLives = Integer.parseInt(s.split(",")[0]); this.bonusLifeFrequency = Integer.parseInt(s.split(",")[1]); } break; @@ -108,6 +109,45 @@ else if (parsing == 2) if (this.levels.size() <= 0) Game.exitToCrash(new RuntimeException("The crusade " + name + " has no levels!")); + + for (int j = 0; j < Game.players.size(); j++) + { + Game.players.get(j).remainingLives = this.startingLives; + } + } + + public void begin() + { + for (int i = 0; i < Game.players.size(); i++) + { + Game.players.get(i).crusadeItemBar = new ItemBar(Game.players.get(i)); + Game.players.get(i).coins = new Coins(); + } + + Game.player.crusadeItemBar.hotbar = Panel.panel.hotbar; + + Game.eventsOut.add(new EventBeginCrusade()); + + this.loadLevel(); + } + + public void loadLevel() + { + Level l = new Level(this.levels.get(this.currentLevel)); + + Panel.panel.hotbar.enabledItemBar = true; + Panel.panel.hotbar.currentItemBar = Game.player.crusadeItemBar; + Panel.panel.hotbar.enabledCoins = true; + Panel.panel.hotbar.currentCoins = Game.player.coins; + + for (Player player: Game.players) + { + if (player.remainingLives > 0) + l.includedPlayers.add(player); + } + + l.loadLevel(); + Game.eventsOut.add(new EventLoadCrusadeHotbar("Battle " + (this.currentLevel + 1))); } public void levelFinished(boolean win) @@ -116,10 +156,16 @@ public void levelFinished(boolean win) if (!win) { - remainingLives--; - - if (remainingLives <= 0) - this.lose = true; + this.lose = true; + + for (Player player : Game.players) + { + if (player.remainingLives > 0) + { + this.lose = false; + break; + } + } } else { @@ -130,19 +176,26 @@ public void levelFinished(boolean win) else if ((this.currentLevel + 1) % this.bonusLifeFrequency == 0 && !replay) { this.lifeGained = true; - remainingLives++; + + for (Player player : Game.players) + { + player.remainingLives++; + } } } } - - public void loadLevel() + + public boolean finalLife() { - Panel.panel.hotbar.enabledItemBar = true; - Panel.panel.hotbar.currentItemBar = this.itemBar; - Panel.panel.hotbar.enabledCoins = true; - Panel.panel.hotbar.currentCoins = coins; - Level level = new Level(this.levels.get(currentLevel)); - level.loadLevel(); + for (int i = 0; i < Game.movables.size(); i++) + { + if (Game.movables.get(i) instanceof TankPlayer && !Game.movables.get(i).destroy && ((TankPlayer) Game.movables.get(i)).player.remainingLives > 1) + return false; + else if (Game.movables.get(i) instanceof TankPlayerRemote && !Game.movables.get(i).destroy && ((TankPlayerRemote) Game.movables.get(i)).player.remainingLives > 1) + return false; + } + + return true; } public ArrayList getShop() @@ -154,7 +207,6 @@ public ArrayList getShop() Item item = this.crusadeItems.get(i); if (item.levelUnlock <= this.currentLevel) shop.add(item); - } return shop; diff --git a/src/main/java/tanks/Drawing.java b/src/main/java/tanks/Drawing.java index f0e50023..1f046d79 100755 --- a/src/main/java/tanks/Drawing.java +++ b/src/main/java/tanks/Drawing.java @@ -1,4 +1,6 @@ package tanks; +import tanks.event.EventPlaySound; + import java.util.ArrayList; public class Drawing @@ -33,8 +35,6 @@ public class Drawing public int mouseXoffset = 0; public int mouseYoffset = 0; - public ArrayList pendingSounds = new ArrayList(); - public double fontSize = 1; private Drawing() {} @@ -83,10 +83,10 @@ public void fillOval(double x, double y, double sizeX, double sizeY) public void fillOval(double x, double y, double z, double sizeX, double sizeY) { - this.fillOval(x, y, z, sizeX, sizeY, true); + this.fillOval(x, y, z, sizeX, sizeY, true, true); } - public void fillOval(double x, double y, double z, double sizeX, double sizeY, boolean depthTest) + public void fillOval(double x, double y, double z, double sizeX, double sizeY, boolean depthTest, boolean facing) { double drawX = (scale * (x + getPlayerOffsetX() - sizeX / 2) + Math.max(0, Panel.windowWidth - this.sizeX * this.scale) / 2); double drawY = (scale * (y + getPlayerOffsetY() - sizeY / 2) + Math.max(0, Panel.windowHeight - statsHeight - this.sizeY * this.scale) / 2); @@ -97,9 +97,12 @@ public void fillOval(double x, double y, double z, double sizeX, double sizeY, b double drawSizeX = (sizeX * scale); double drawSizeY = (sizeY * scale); - double dZ = z * scale / interfaceScale; + double dZ = z * scale; - Game.game.window.fillOval(drawX, drawY, dZ, drawSizeX, drawSizeY, depthTest); + if (facing && Game.game.window.angled) + Game.game.window.fillFacingOval(drawX, drawY, dZ, drawSizeX, drawSizeY, depthTest); + else + Game.game.window.fillOval(drawX, drawY, dZ, drawSizeX, drawSizeY, depthTest); } public void fillForcedOval(double x, double y, double sizeX, double sizeY) @@ -166,7 +169,7 @@ public void drawImage(String img, double x, double y, double z, double sizeX, do double drawSizeX = (sizeX * scale); double drawSizeY = (sizeY * scale); - double drawZ = z * scale / interfaceScale; + double drawZ = z * scale; Game.game.window.drawImage(drawX, drawY, drawZ, drawSizeX, drawSizeY, img, false); } @@ -203,8 +206,8 @@ public void fillQuadBox(double x1, double y1, double x2, double y2, double x3, d double dY3 = getPointY(y3); double dY4 = getPointY(y4); - double dZ = z * scale / interfaceScale; - double dsZ = sZ * scale / interfaceScale; + double dZ = z * scale; + double dsZ = sZ * scale; Game.game.window.fillQuadBox(dX1, dY1, dX2, dY2, dX3, dY3, dX4, dY4, dZ, dsZ, options); } @@ -277,14 +280,27 @@ public void fillBox(double x, double y, double z, double sizeX, double sizeY, do { double drawX = (scale * (x + getPlayerOffsetX() - sizeX / 2) + Math.max(0, Panel.windowWidth - this.sizeX * scale) / 2); double drawY = (scale * (y + getPlayerOffsetY() - sizeY / 2) + Math.max(0, Panel.windowHeight - statsHeight - this.sizeY * scale) / 2); - double drawZ = z * scale / interfaceScale; + double drawZ = z * scale; if (drawX - 200 * scale > Panel.windowWidth || drawX + 200 * scale < 0 || drawY - 200 * scale > Panel.windowHeight || drawY + 200 * scale < 0) return; double drawSizeX = sizeX * scale; double drawSizeY = sizeY * scale; - double drawSizeZ = sizeZ * scale / interfaceScale; + double drawSizeZ = sizeZ * scale; + + Game.game.window.fillBox(drawX, drawY, drawZ, drawSizeX, drawSizeY, drawSizeZ, options); + } + + public void fillForcedBox(double x, double y, double z, double sizeX, double sizeY, double sizeZ, byte options) + { + double drawX = (scale * (x + getPlayerOffsetX() - sizeX / 2) + Math.max(0, Panel.windowWidth - this.sizeX * scale) / 2); + double drawY = (scale * (y + getPlayerOffsetY() - sizeY / 2) + Math.max(0, Panel.windowHeight - statsHeight - this.sizeY * scale) / 2); + double drawZ = z * scale; + + double drawSizeX = sizeX * scale; + double drawSizeY = sizeY * scale; + double drawSizeZ = sizeZ * scale; Game.game.window.fillBox(drawX, drawY, drawZ, drawSizeX, drawSizeY, drawSizeZ, options); } @@ -381,7 +397,7 @@ public void drawText(double x, double y, double z, String text) double drawX = (scale * (x + getPlayerOffsetX() - sizeX / 2) + Math.max(0, Panel.windowWidth - this.sizeX * scale) / 2); double drawY = (scale * (y + getPlayerOffsetY() - sizeY / 2) + Math.max(0, Panel.windowHeight - statsHeight - this.sizeY * scale) / 2); - double drawZ = z * scale / interfaceScale; + double drawZ = z * scale; Game.game.window.fontRenderer.drawString(drawX, drawY, drawZ, this.fontSize, this.fontSize, text); } @@ -464,9 +480,37 @@ public void drawTooltip(String[] text) public void playSound(String sound) { - pendingSounds.add(sound); + Game.game.window.soundPlayer.playSound("/sounds/" + sound); } - + + public void playGlobalSound(String sound) + { + this.playSound(sound); + Game.eventsOut.add(new EventPlaySound(sound, 1, 1)); + } + + public void playSound(String sound, float pitch) + { + Game.game.window.soundPlayer.playSound("/sounds/" + sound, pitch); + } + + public void playGlobalSound(String sound, float pitch) + { + this.playSound(sound, pitch); + Game.eventsOut.add(new EventPlaySound(sound, pitch, 1)); + } + + public void playSound(String sound, float pitch, float volume) + { + Game.game.window.soundPlayer.playSound("/sounds/" + sound, pitch, volume); + } + + public void playGlobalSound(String sound, float pitch, float volume) + { + this.playSound(sound, pitch, volume); + Game.eventsOut.add(new EventPlaySound(sound, pitch, volume)); + } + public double toGameCoordsX(double x) { double x1 = x; diff --git a/src/main/java/tanks/Effect.java b/src/main/java/tanks/Effect.java index 6320e880..e840177b 100755 --- a/src/main/java/tanks/Effect.java +++ b/src/main/java/tanks/Effect.java @@ -6,7 +6,7 @@ public class Effect extends Movable { - public enum EffectType {fire, smokeTrail, trail, ray, mineExplosion, laser, piece, obstaclePiece, obstaclePiece3d, charge, tread, darkFire, electric, healing, stun} + public enum EffectType {fire, smokeTrail, trail, ray, mineExplosion, laser, piece, obstaclePiece, obstaclePiece3d, charge, tread, darkFire, electric, healing, stun, bushBurn} public EffectType type; double age = 0; public double colR; @@ -120,7 +120,9 @@ else if (type == EffectType.stun) this.distance = Math.random() * 50 + 25; } else if (type == EffectType.healing) - this.maxAge = 21; + this.maxAge = 21; + else if (type == EffectType.bushBurn) + this.maxAge = this.posZ * 2; } protected void refurbish() @@ -324,6 +326,24 @@ else if (this.type == EffectType.healing) else drawing.fillOval(this.posX, this.posY, size, size); } + else if (this.type == EffectType.bushBurn) + { + if (Game.enable3d) + { + Drawing.drawing.setColor(this.colR, this.colG, this.colB); + Drawing.drawing.fillBox(this.posX, this.posY, 0, Obstacle.draw_size, Obstacle.draw_size, this.posZ); + } + else + { + Drawing.drawing.setColor(this.colR, this.colG, this.colB, this.posZ); + Drawing.drawing.fillRect(this.posX, this.posY, Obstacle.draw_size, Obstacle.draw_size); + } + + this.posZ -= Panel.frameFrequency / 2; + this.colR = Math.max(this.colR - Panel.frameFrequency, 0); + this.colG = Math.max(this.colG - Panel.frameFrequency, 0); + this.colB = Math.max(this.colB - Panel.frameFrequency, 0); + } else { Game.exitToCrash(new RuntimeException("Invalid effect type!")); diff --git a/src/main/java/tanks/Game.java b/src/main/java/tanks/Game.java index 0a3ec8a3..8fd49e68 100755 --- a/src/main/java/tanks/Game.java +++ b/src/main/java/tanks/Game.java @@ -1,17 +1,19 @@ package tanks; import lwjglwindow.LWJGLWindow; - import tanks.bullet.Bullet; -import tanks.network.*; import tanks.event.*; -import tanks.tank.*; -import tanks.obstacle.*; -import tanks.registry.*; -import tanks.gui.*; +import tanks.gui.ChatFilter; import tanks.gui.screen.*; -import tanks.hotbar.*; - +import tanks.hotbar.Coins; +import tanks.hotbar.ItemBar; +import tanks.network.Client; +import tanks.network.NetworkEventMap; +import tanks.network.SynchronizedList; +import tanks.obstacle.*; +import tanks.registry.RegistryObstacle; +import tanks.registry.RegistryTank; +import tanks.tank.*; import java.io.*; import java.nio.file.Files; @@ -24,13 +26,15 @@ public class Game { public static final double tank_size = 50; - public static final UUID clientID = UUID.randomUUID(); + public static final int absoluteDepthBase = 1000; public static ArrayList movables = new ArrayList(); public static ArrayList obstacles = new ArrayList(); public static ArrayList effects = new ArrayList(); public static ArrayList belowEffects = new ArrayList(); + public static SynchronizedList players = new SynchronizedList(); + public static Player player; public static ArrayList removeMovables = new ArrayList(); public static ArrayList removeObstacles = new ArrayList(); @@ -42,9 +46,6 @@ public class Game public static final SynchronizedList eventsOut = new SynchronizedList(); public static final SynchronizedList eventsIn = new SynchronizedList(); - //public static Team playerTeam = new Team(new Color(0, 0, 255)); - //public static Team enemyTeam = new Team(new Color(255, 0, 0)); - public static Team playerTeam = new Team("ally"); public static Team enemyTeam = new Team("enemy"); @@ -60,8 +61,8 @@ public class Game public static double[][] tilesDepth = new double[28][18]; - public static final int network_protocol = 8; - public static final String version = "Tanks 0.7.5"; + public static final int network_protocol = 10; + public static final String version = "Tanks 0.7.6"; public static int port = 8080; @@ -69,13 +70,15 @@ public class Game public static double levelSize = 1; - public static Tank player; + public static Tank playerTank; public static boolean bulletLocked = false; public static boolean vsync = true; public static boolean enable3d = true; + public static boolean enable3dBg = true; + public static boolean angledView = false; public static boolean enableChatFilter = true; @@ -83,8 +86,6 @@ public class Game public static Screen screen; - public static String username = ""; - public static String ip = ""; public static boolean fancyGraphics = true; @@ -124,45 +125,61 @@ public class Game private Game() {} public static void initScript() - { + { + player = new Player(clientID, ""); + Game.players.add(player); + Drawing.initialize(); Panel.initialize(); Game.exitToTitle(); - /* 0 */ NetworkEventMap.register(EventSendClientDetails.class); - /* 1 */ NetworkEventMap.register(EventKeepConnectionAlive.class); - /* 2 */ NetworkEventMap.register(EventConnectionSuccess.class); - /* 3 */ NetworkEventMap.register(EventKick.class); - /* 4 */ NetworkEventMap.register(EventAnnounceConnection.class); - /* 5 */ NetworkEventMap.register(EventChat.class); - /* 6 */ NetworkEventMap.register(EventPlayerChat.class); - /* 7 */ NetworkEventMap.register(EventLoadLevel.class); - /* 8 */ NetworkEventMap.register(EventEnterLevel.class); - /* 9 */ NetworkEventMap.register(EventLevelEnd.class); - /* 10*/ NetworkEventMap.register(EventReturnToLobby.class); - /* 11*/ NetworkEventMap.register(EventPlayerReady.class); - /* 12*/ NetworkEventMap.register(EventUpdateReadyCount.class); - /* 13*/ NetworkEventMap.register(EventBeginLevelCountdown.class); - /* 14*/ NetworkEventMap.register(EventTankUpdate.class); - /* 15*/ NetworkEventMap.register(EventTankControllerUpdateS.class); - /* 16*/ NetworkEventMap.register(EventTankControllerUpdateC.class); - /* 17*/ NetworkEventMap.register(EventTankControllerUpdateAmmunition.class); - /* 18*/ NetworkEventMap.register(EventCreatePlayer.class); - /* 19*/ NetworkEventMap.register(EventCreateTank.class); - /* 20*/ NetworkEventMap.register(EventCreateCustomTank.class); - /* 21*/ NetworkEventMap.register(EventTankUpdateHealth.class); - /* 22*/ NetworkEventMap.register(EventShootBullet.class); - /* 23*/ NetworkEventMap.register(EventBulletUpdate.class); - /* 24*/ NetworkEventMap.register(EventBulletDestroyed.class); - /* 25*/ NetworkEventMap.register(EventBulletInstantWaypoint.class); - /* 26*/ NetworkEventMap.register(EventBulletAddAttributeModifier.class); - /* 27*/ NetworkEventMap.register(EventBulletElectricStunEffect.class); - /* 28*/ NetworkEventMap.register(EventLayMine.class); - /* 29*/ NetworkEventMap.register(EventMineExplode.class); - /* 30*/ NetworkEventMap.register(EventTankTeleport.class); - /* 31*/ NetworkEventMap.register(EventTankUpdateVisibility.class); - /* 32*/ NetworkEventMap.register(EventTankRedUpdateCharge.class); - /* 33*/ NetworkEventMap.register(EventTankAddAttributeModifier.class); + NetworkEventMap.register(EventSendClientDetails.class); + NetworkEventMap.register(EventKeepConnectionAlive.class); + NetworkEventMap.register(EventConnectionSuccess.class); + NetworkEventMap.register(EventKick.class); + NetworkEventMap.register(EventAnnounceConnection.class); + NetworkEventMap.register(EventChat.class); + NetworkEventMap.register(EventPlayerChat.class); + NetworkEventMap.register(EventLoadLevel.class); + NetworkEventMap.register(EventEnterLevel.class); + NetworkEventMap.register(EventLevelEnd.class); + NetworkEventMap.register(EventReturnToLobby.class); + NetworkEventMap.register(EventBeginCrusade.class); + NetworkEventMap.register(EventReturnToCrusade.class); + NetworkEventMap.register(EventLoadCrusadeHotbar.class); + NetworkEventMap.register(EventAddShopItem.class); + NetworkEventMap.register(EventSortShopButtons.class); + NetworkEventMap.register(EventPurchaseItem.class); + NetworkEventMap.register(EventSetItem.class); + NetworkEventMap.register(EventSetItemBarSlot.class); + NetworkEventMap.register(EventUpdateCoins.class); + NetworkEventMap.register(EventPlayerReady.class); + NetworkEventMap.register(EventUpdateReadyCount.class); + NetworkEventMap.register(EventUpdateRemainingLives.class); + NetworkEventMap.register(EventBeginLevelCountdown.class); + NetworkEventMap.register(EventTankUpdate.class); + NetworkEventMap.register(EventTankControllerUpdateS.class); + NetworkEventMap.register(EventTankControllerUpdateC.class); + NetworkEventMap.register(EventTankControllerUpdateAmmunition.class); + NetworkEventMap.register(EventCreatePlayer.class); + NetworkEventMap.register(EventCreateTank.class); + NetworkEventMap.register(EventCreateCustomTank.class); + NetworkEventMap.register(EventTankUpdateHealth.class); + NetworkEventMap.register(EventShootBullet.class); + NetworkEventMap.register(EventBulletUpdate.class); + NetworkEventMap.register(EventBulletDestroyed.class); + NetworkEventMap.register(EventBulletInstantWaypoint.class); + NetworkEventMap.register(EventBulletAddAttributeModifier.class); + NetworkEventMap.register(EventBulletElectricStunEffect.class); + NetworkEventMap.register(EventLayMine.class); + NetworkEventMap.register(EventMineExplode.class); + NetworkEventMap.register(EventTankTeleport.class); + NetworkEventMap.register(EventTankUpdateVisibility.class); + NetworkEventMap.register(EventTankRedUpdateCharge.class); + NetworkEventMap.register(EventTankAddAttributeModifier.class); + NetworkEventMap.register(EventCreateFreezeEffect.class); + NetworkEventMap.register(EventObstacleShrubberyBurn.class); + NetworkEventMap.register(EventPlaySound.class); defaultObstacles.add(new RegistryObstacle.DefaultObstacleEntry(Obstacle.class, "normal")); defaultObstacles.add(new RegistryObstacle.DefaultObstacleEntry(ObstacleIndestructible.class, "hard")); @@ -189,7 +206,7 @@ public static void initScript() defaultTanks.add(new RegistryTank.DefaultTankEntry(TankBlack.class, "black", 1.0 / 10)); defaultTanks.add(new RegistryTank.DefaultTankEntry(TankPink.class, "pink", 1.0 / 15)); defaultTanks.add(new RegistryTank.DefaultTankEntry(TankBoss.class, "boss", 1.0 / 25)); - + homedir = System.getProperty("user.home"); if (Files.exists(Paths.get(homedir + "/.tanks.d")) && !Files.exists(Paths.get(homedir + directoryPath))) @@ -253,12 +270,12 @@ public static void initScript() Game.logger = System.err; Game.logger.println(new Date().toString() + " (syswarn) logfile not found despite existence of tanks directory! using stderr instead."); } - + ScreenOptions.loadOptions(homedir); RegistryTank.loadRegistry(homedir); - RegistryObstacle.loadRegistry(homedir); - - if (Game.usernameInvalid(Game.username)) + RegistryObstacle.loadRegistry(homedir); + + if (Game.usernameInvalid(Game.player.username)) Game.screen = new ScreenUsernameInvalid(); } @@ -267,9 +284,9 @@ public static boolean usernameInvalid(String username) if (username.length() > 18) return true; - for (int i = 0; i < Game.username.length(); i++) + for (int i = 0; i < Game.player.username.length(); i++) { - if (!"abcdefghijklmnopqrstuvwxyz1234567890_".contains(Game.username.toLowerCase().substring(i, i+1))) + if (!"abcdefghijklmnopqrstuvwxyz1234567890_".contains(Game.player.username.toLowerCase().substring(i, i+1))) { return true; } @@ -277,19 +294,30 @@ public static boolean usernameInvalid(String username) return false; } + + public static void removePlayer(UUID id) + { + for (int i = 0; i < Game.players.size(); i++) + { + if (Game.players.get(i).clientID.equals(id)) + { + Game.players.remove(i); + i--; + } + } + } public static void main(String[] args) - { + { Game.initScript(); - Game.game.window = new LWJGLWindow("Tanks", 1400, 900 + Drawing.drawing.statsHeight, 1000, new GameUpdater(), new GameDrawer(), new GameWindowHandler(), Game.vsync, !Panel.showMouseTarget); + Game.game.window = new LWJGLWindow("Tanks", 1400, 900 + Drawing.drawing.statsHeight, absoluteDepthBase, new GameUpdater(), new GameDrawer(), new GameWindowHandler(), Game.vsync, !Panel.showMouseTarget); Game.game.window.run(); } public static void reset() { - Tank.currentID = 0; - Tank.freeIDs.clear(); - Tank.idMap.clear(); + resetNetworkIDs(); + obstacles.clear(); belowEffects.clear(); movables.clear(); @@ -305,9 +333,9 @@ public static void reset() public static void exit() { screen = new ScreenInterlevel(); - Tank.currentID = 0; - Tank.freeIDs.clear(); - Tank.idMap.clear(); + + resetNetworkIDs(); + obstacles.clear(); belowEffects.clear(); movables.clear(); @@ -336,18 +364,20 @@ public static void exit(String name) Game.screen = s; } - public static void exitToCrash(Exception e) + public static void exitToCrash(Throwable e) { + System.gc(); + e.printStackTrace(); + ScreenPartyHost.isServer = false; + ScreenPartyLobby.isClient = false; + if (ScreenPartyHost.isServer && ScreenPartyHost.server != null) ScreenPartyHost.server.close("The party has ended because the host crashed"); if (ScreenPartyLobby.isClient) Client.handler.ctx.close(); - - ScreenPartyHost.isServer = false; - ScreenPartyLobby.isClient = false; obstacles.clear(); belowEffects.clear(); @@ -356,7 +386,12 @@ public static void exitToCrash(Exception e) Game.crashMessage = e.toString(); Game.logger.println(new Date().toString() + " (syserr) the game has crashed! below is a crash report, good luck:"); e.printStackTrace(Game.logger); - screen = new ScreenCrashed(); + + if (e instanceof OutOfMemoryError) + screen = new ScreenOutOfMemory(); + else + screen = new ScreenCrashed(); + recycleEffects.clear(); removeEffects.clear(); removeBelowEffects.clear(); @@ -413,19 +448,28 @@ public static void silentCleanUp() removeEffects.clear(); removeBelowEffects.clear(); - Tank.currentID = 0; - Tank.idMap.clear(); - Tank.freeIDs.clear(); - - Bullet.currentID = 0; - Bullet.idMap.clear(); - Bullet.freeIDs.clear(); + resetNetworkIDs(); Panel.panel.hotbar.currentCoins = new Coins(); Panel.panel.hotbar.enabledCoins = false; - Panel.panel.hotbar.currentItemBar = new ItemBar(Panel.panel.hotbar); + Panel.panel.hotbar.currentItemBar = new ItemBar(Game.player, Panel.panel.hotbar); Panel.panel.hotbar.enabledItemBar = false; } + + public static void resetNetworkIDs() + { + Tank.currentID = 0; + Tank.idMap.clear(); + Tank.freeIDs.clear(); + + Bullet.currentID = 0; + Bullet.idMap.clear(); + Bullet.freeIDs.clear(); + + Mine.currentID = 0; + Mine.idMap.clear(); + Mine.freeIDs.clear(); + } public static void loadLevel(File f) { diff --git a/src/main/java/tanks/GameDrawer.java b/src/main/java/tanks/GameDrawer.java index 9c8dcedb..c8a303f4 100755 --- a/src/main/java/tanks/GameDrawer.java +++ b/src/main/java/tanks/GameDrawer.java @@ -11,7 +11,7 @@ public void draw() { Panel.panel.draw(); } - catch(Exception e) + catch (Throwable e) { Game.exitToCrash(e); } diff --git a/src/main/java/tanks/GameUpdater.java b/src/main/java/tanks/GameUpdater.java index 77ca9174..89c60dec 100755 --- a/src/main/java/tanks/GameUpdater.java +++ b/src/main/java/tanks/GameUpdater.java @@ -11,7 +11,7 @@ public void update() { Panel.panel.update(); } - catch(Exception e) + catch (Throwable e) { Game.exitToCrash(e); } diff --git a/src/main/java/tanks/Level.java b/src/main/java/tanks/Level.java index 88b6a7d3..c1ffb49c 100755 --- a/src/main/java/tanks/Level.java +++ b/src/main/java/tanks/Level.java @@ -6,10 +6,8 @@ import tanks.gui.Button; import tanks.gui.screen.ScreenGame; import tanks.gui.screen.ScreenLevelBuilder; -import tanks.gui.screen.ScreenParty; import tanks.gui.screen.ScreenPartyHost; -import tanks.network.Server; -import tanks.network.ServerHandler; +import tanks.gui.screen.ScreenPartyLobby; import tanks.obstacle.Obstacle; import tanks.registry.RegistryObstacle; import tanks.registry.RegistryTank; @@ -52,6 +50,8 @@ public class Level public ArrayList playerSpawnsAngle = new ArrayList(); public ArrayList playerSpawnsTeam = new ArrayList(); + public ArrayList includedPlayers = new ArrayList(); + /** * A level string is structured like this: * (parentheses signify required parameters, and square brackets signify optional parameters. @@ -99,6 +99,11 @@ public void loadLevel(ScreenLevelBuilder s) public void loadLevel(ScreenLevelBuilder s, boolean remote) { + if (ScreenPartyHost.isServer) + ScreenPartyHost.includedPlayers.clear(); + else if (ScreenPartyLobby.isClient) + ScreenPartyLobby.includedPlayers.clear(); + if (s == null) Obstacle.draw_size = 0; else @@ -189,7 +194,7 @@ else if (t.length >= 2) s.dg = dg; s.db = db; s.editable = this.editable; - Game.movables.remove(Game.player); + Game.movables.remove(Game.playerTank); s.colorRed.inputText = r + ""; s.colorGreen.inputText = g + ""; @@ -382,6 +387,13 @@ public void run() if (ScreenPartyHost.isServer && ScreenPartyHost.server != null) playerCount += ScreenPartyHost.server.connections.size(); + if (this.includedPlayers.size() > 0) + playerCount = this.includedPlayers.size(); + else + { + this.includedPlayers.addAll(Game.players); + } + if (s == null) { for (int i = 0; i < playerCount; i++) @@ -403,32 +415,14 @@ public void run() if (ScreenPartyHost.isServer) { - if (i == 0) - { - EventCreatePlayer local = new EventCreatePlayer(Game.clientID, Game.username, x, y, angle, team); - playerEvents.add(local); - Game.eventsOut.add(local); - } - else - { - synchronized (ScreenPartyHost.server.connections) - { - ServerHandler c = ScreenPartyHost.server.connections.get(i - 1); - - EventCreatePlayer e = new EventCreatePlayer(c.clientID, c.rawUsername, x, y, angle, team); - playerEvents.add(e); - Game.eventsOut.add(e); - } - } - - continue; + EventCreatePlayer e = new EventCreatePlayer(this.includedPlayers.get(i), x, y, angle, team); + playerEvents.add(e); + Game.eventsOut.add(e); } - else if (remote) - continue; - else + else if (!remote) { - TankPlayer tank = new TankPlayer(x, y, angle, Game.clientID); - Game.player = tank; + TankPlayer tank = new TankPlayer(x, y, angle); + Game.playerTank = tank; tank.team = team; Game.movables.add(tank); } diff --git a/src/main/java/tanks/Movable.java b/src/main/java/tanks/Movable.java index c268832e..3ae29863 100755 --- a/src/main/java/tanks/Movable.java +++ b/src/main/java/tanks/Movable.java @@ -29,10 +29,9 @@ public abstract class Movable implements IDrawableForInterface public int drawLevel = 3; //public boolean drawBelow = false; //public boolean drawAbove = false; - public boolean canHide = false; public boolean isRemote = false; - public double hiddenTimer = 0; + //public double hiddenTimer = 0; public ArrayList attributes = new ArrayList(); @@ -48,7 +47,7 @@ public void update() { if (!destroy) { - this.hiddenTimer = Math.max(0, this.hiddenTimer - Panel.frameFrequency); + //this.hiddenTimer = Math.max(0, this.hiddenTimer - Panel.frameFrequency); double vX2 = this.vX; double vY2 = this.vY; @@ -86,8 +85,6 @@ public void update() this.posX += this.lastFinalVX * Panel.frameFrequency; this.posY += this.lastFinalVY * Panel.frameFrequency; this.posZ += this.lastFinalVZ * Panel.frameFrequency; - - this.canHide = false; } } diff --git a/src/main/java/tanks/Panel.java b/src/main/java/tanks/Panel.java index 1a277a28..cdbace8e 100755 --- a/src/main/java/tanks/Panel.java +++ b/src/main/java/tanks/Panel.java @@ -2,6 +2,7 @@ import tanks.event.INetworkEvent; import tanks.gui.screen.ScreenGame; +import tanks.gui.screen.ScreenParty; import tanks.gui.screen.ScreenPartyHost; import tanks.gui.screen.ScreenPartyLobby; import tanks.hotbar.Coins; @@ -9,8 +10,7 @@ import tanks.network.ClientHandler; import tanks.tank.Tank; import tanks.tank.TankDummyLoadingScreen; - -import javax.swing.*; +import tanks.tank.TankPlayerRemote; public class Panel { @@ -19,13 +19,13 @@ public class Panel public static double windowWidth = 1400; public static double windowHeight = 900; - public static boolean showMouseTarget = true; public static Panel panel; public static String winlose = ""; public static boolean win = false; + public static boolean levelPassed = false; public static double darkness = 0; @@ -47,7 +47,6 @@ public class Panel public int lastFPS = 0; - public static boolean pausePressed = false; protected static boolean initialized = false; public Tank dummySpin = new TankDummyLoadingScreen(Drawing.drawing.sizeX / 2, Drawing.drawing.sizeY / 2); @@ -67,7 +66,7 @@ private Panel() } public void update() - { + { Panel.frameFrequency = Game.game.window.frameFrequency; double introTime = 1000; @@ -92,6 +91,27 @@ public void update() Game.eventsIn.clear(); } + if (ScreenPartyHost.isServer) + { + synchronized (ScreenPartyHost.disconnectedPlayers) + { + for (int i = 0; i < ScreenPartyHost.disconnectedPlayers.size(); i++) + { + for (int j = 0; j < Game.movables.size(); j++) + { + Movable m = Game.movables.get(j); + if (m instanceof TankPlayerRemote && ((TankPlayerRemote) m).player.clientID.equals(ScreenPartyHost.disconnectedPlayers.get(i))) + ((TankPlayerRemote) m).lives = 0; + } + + ScreenPartyHost.includedPlayers.remove(ScreenPartyHost.disconnectedPlayers.get(i)); + Game.removePlayer(ScreenPartyHost.disconnectedPlayers.get(i)); + } + + ScreenPartyHost.disconnectedPlayers.clear(); + } + } + if (Panel.panel.hotbar.currentCoins.coins < 0) Panel.panel.hotbar.currentCoins.coins = 0; @@ -100,20 +120,21 @@ public void update() Drawing.drawing.scale = Math.min(Panel.windowWidth * 1.0 / Game.currentSizeX, (Panel.windowHeight * 1.0 - Drawing.drawing.statsHeight) / Game.currentSizeY) / 50.0; Drawing.drawing.interfaceScale = Math.min(Panel.windowWidth * 1.0 / 28, (Panel.windowHeight * 1.0 - Drawing.drawing.statsHeight) / 18) / 50.0; + Game.game.window.absoluteDepth = Drawing.drawing.interfaceScale * Game.absoluteDepthBase; Drawing.drawing.unzoomedScale = Drawing.drawing.scale; this.zoomTimer -= 0.02 * Panel.frameFrequency; - if (Game.player != null && !ScreenGame.finished && Drawing.drawing.unzoomedScale < Drawing.drawing.interfaceScale + if (Game.playerTank != null && !ScreenGame.finished && Drawing.drawing.unzoomedScale < Drawing.drawing.interfaceScale && Game.screen instanceof ScreenGame && ((ScreenGame) (Game.screen)).playing) { Drawing.drawing.enableMovingCamera = true; if (Drawing.drawing.movingCamera) { - Drawing.drawing.playerX = Game.player.posX; - Drawing.drawing.playerY = Game.player.posY; + Drawing.drawing.playerX = Game.playerTank.posX; + Drawing.drawing.playerY = Game.playerTank.posY; this.zoomTimer += 0.04 * Panel.frameFrequency; //Drawing.drawing.scale = Drawing.drawing.interfaceScale; @@ -155,8 +176,7 @@ public void update() { INetworkEvent e = Game.eventsOut.get(i); - if (e instanceof INetworkEvent) - ScreenPartyHost.server.connections.get(j).events.add(e); + ScreenPartyHost.server.connections.get(j).events.add(e); } } } @@ -221,12 +241,18 @@ public void draw() this.drawBar(); - this.drawMouseTarget(); + if (Game.screen.showDefaultMouse) + this.drawMouseTarget(); Game.screen.drawPostMouse(); } public void drawMouseTarget() + { + drawMouseTarget(false); + } + + public void drawMouseTarget(boolean force) { double mx = Drawing.drawing.getInterfaceMouseX(); double my = Drawing.drawing.getInterfaceMouseY(); @@ -234,7 +260,7 @@ public void drawMouseTarget() //double mx2 = Drawing.drawing.getMouseX(); //double my2 = Drawing.drawing.getMouseY(); - if (showMouseTarget) + if (showMouseTarget || force) { Drawing.drawing.setColor(0, 0, 0); /*Drawing.drawing.drawInterfaceOval(mx, my, 8, 8); @@ -270,6 +296,15 @@ public void drawBar(double offset) Game.game.window.fontRenderer.drawString(600, offset + (int) (Panel.windowHeight - 40 + 10), 0.6, 0.6, Game.screen.screenHint); + long free = Runtime.getRuntime().freeMemory(); + long total = Runtime.getRuntime().totalMemory(); + long used = total - free; + + if (free < 1048576 * 5) + Drawing.drawing.setColor(255, 127, 0); + + Game.game.window.fontRenderer.drawString(150, offset + (int) (Panel.windowHeight - 40 + 22), 0.4, 0.4, "Memory used: " + used / 1048576 + "/" + total / 1048576 + "MB"); + if (ScreenPartyLobby.isClient) { double[] col = getLatencyColor(ClientHandler.lastLatencyAverage); diff --git a/src/main/java/tanks/Player.java b/src/main/java/tanks/Player.java new file mode 100644 index 00000000..02b2087a --- /dev/null +++ b/src/main/java/tanks/Player.java @@ -0,0 +1,30 @@ +package tanks; + +import tanks.hotbar.Coins; +import tanks.hotbar.ItemBar; +import tanks.tank.Tank; +import tanks.tank.TankPlayer; + +import java.util.UUID; + +public class Player +{ + public int remainingLives; + public ItemBar crusadeItemBar = new ItemBar(this); + public Coins coins = new Coins(); + + public UUID clientID; + public String username; + public Tank tank; + + public Player(UUID clientID, String username) + { + this.clientID = clientID; + this.username = username; + } + + public String toString() + { + return this.username + " (" + this.clientID + ")"; + } +} diff --git a/src/main/java/tanks/bullet/Bullet.java b/src/main/java/tanks/bullet/Bullet.java index ee1ddc3b..9267a0fd 100755 --- a/src/main/java/tanks/bullet/Bullet.java +++ b/src/main/java/tanks/bullet/Bullet.java @@ -1,15 +1,13 @@ package tanks.bullet; import tanks.*; -import tanks.event.EventBulletAddAttributeModifier; -import tanks.event.EventBulletDestroyed; -import tanks.event.EventBulletUpdate; -import tanks.event.EventTankUpdateHealth; +import tanks.event.*; import tanks.hotbar.ItemBullet; import tanks.obstacle.Obstacle; import tanks.tank.Mine; import tanks.tank.Ray; import tanks.tank.Tank; +import tanks.tank.TankPlayerRemote; import java.util.ArrayList; import java.util.HashMap; @@ -30,6 +28,7 @@ public enum BulletEffect {none, fire, darkFire, fireTrail, ice, trail} public boolean enableExternalCollisions = true; public boolean playPopSound = true; + public boolean playBounceSound = true; public double age = 0; public double size; public int bounces; @@ -62,6 +61,8 @@ public enum BulletEffect {none, fire, darkFire, fireTrail, ice, trail} public boolean affectsMaxLiveBullets; + public String itemSound = "shoot.ogg"; + public Bullet(double x, double y, int bounces, Tank t) { this(x, y, bounces, t, true, null); @@ -126,7 +127,7 @@ public Bullet(double x, double y, int bounces, Tank t, boolean affectsMaxLiveBul this.drawLevel = 8; } - public void moveOut(int amount) + public void moveOut(double amount) { this.moveInDirection(vX, vY, amount); } @@ -154,10 +155,23 @@ public void collidedWithTank(Tank t) t.flashAnimation = 0; t.destroy = true; - if (this.tank.equals(Game.player)) + if (this.tank.equals(Game.playerTank)) Panel.panel.hotbar.currentCoins.coins += t.coinValue; + else if (this.tank instanceof TankPlayerRemote && Crusade.crusadeMode) + { + ((TankPlayerRemote) this.tank).player.coins.coins += t.coinValue; + Game.eventsOut.add(new EventUpdateCoins(((TankPlayerRemote) this.tank).player)); + } + } + else if (this.playPopSound) + { + Drawing.drawing.playGlobalSound("bullet_explode.ogg", (float) (bullet_size / size)); } } + else if (this.playPopSound) + { + Drawing.drawing.playGlobalSound("bullet_explode.ogg", (float) (bullet_size / size)); + } } public void collidedWithObject(Movable o) @@ -165,11 +179,17 @@ public void collidedWithObject(Movable o) if (o instanceof Bullet && !((Bullet) o).enableExternalCollisions) return; - if (this.playPopSound) - Drawing.drawing.playSound("/bullet_explode.wav"); + if (o instanceof Bullet) + { + if (this.playPopSound) + Drawing.drawing.playGlobalSound("bullet_explode.ogg", (float) (bullet_size / ((Bullet) o).size)); + } if (!heavy) { + if (this.playPopSound) + Drawing.drawing.playGlobalSound("bullet_explode.ogg", (float) (bullet_size / size)); + this.destroy = true; this.vX = 0; this.vY = 0; @@ -177,6 +197,9 @@ public void collidedWithObject(Movable o) if (heavy && o instanceof Bullet && ((Bullet)o).heavy) { + if (this.playPopSound) + Drawing.drawing.playGlobalSound("bullet_explode.ogg", (float) (bullet_size / size)); + this.destroy = true; this.vX = 0; this.vY = 0; @@ -381,14 +404,14 @@ else if ((o instanceof Bullet || o instanceof Mine) && o != this && !o.destroy & if (this.bounces < 0 || this.bouncyBounces < 0) { if (this.playPopSound) - Drawing.drawing.playSound("/bullet_explode.wav"); + Drawing.drawing.playGlobalSound("bullet_explode.ogg", (float) (bullet_size / size)); this.destroy = true; this.vX = 0; this.vY = 0; } - else - Drawing.drawing.playSound("/bounce.wav"); + else if (this.playBounceSound) + Drawing.drawing.playGlobalSound("bounce.ogg", (float) (bullet_size / size)); Game.eventsOut.add(new EventBulletUpdate(this)); } @@ -424,6 +447,8 @@ public void update() else this.item.liveBullets--; } + + this.onDestroy(); } if (this.destroyTimer <= 0 && Game.fancyGraphics && !(this instanceof BulletFlame)) @@ -554,4 +579,8 @@ public void addUnduplicateAttribute(AttributeModifier m) Game.eventsOut.add(new EventBulletAddAttributeModifier(this, m, true)); } + public void onDestroy() + { + + } } diff --git a/src/main/java/tanks/bullet/BulletElectric.java b/src/main/java/tanks/bullet/BulletElectric.java index 15b02f8e..97601e1f 100755 --- a/src/main/java/tanks/bullet/BulletElectric.java +++ b/src/main/java/tanks/bullet/BulletElectric.java @@ -42,6 +42,7 @@ public BulletElectric(double x, double y, int bounces, Tank t, ArrayList= ScreenPartyHost.includedPlayers.size() && Game.screen instanceof ScreenGame) { - if (ScreenPartyHost.readyPlayers.size() >= ScreenPartyHost.server.connections.size() + 1 && Game.screen instanceof ScreenGame) - { - Game.eventsOut.add(new EventBeginLevelCountdown()); - ((ScreenGame)Game.screen).cancelCountdown = false; - } + Game.eventsOut.add(new EventBeginLevelCountdown()); + ((ScreenGame)Game.screen).cancelCountdown = false; } + } @Override diff --git a/src/main/java/tanks/event/EventPurchaseItem.java b/src/main/java/tanks/event/EventPurchaseItem.java new file mode 100644 index 00000000..fe3c1c47 --- /dev/null +++ b/src/main/java/tanks/event/EventPurchaseItem.java @@ -0,0 +1,58 @@ +package tanks.event; + +import io.netty.buffer.ByteBuf; +import tanks.Game; +import tanks.Panel; +import tanks.Player; +import tanks.gui.screen.ScreenGame; + +public class EventPurchaseItem extends PersonalEvent +{ + public int item; + + public EventPurchaseItem() + { + + } + + public EventPurchaseItem(int item) + { + this.item = item; + } + + @Override + public void write(ByteBuf b) + { + b.writeInt(item); + } + + @Override + public void read(ByteBuf b) + { + item = b.readInt(); + } + + @Override + public void execute() + { + if (this.clientID != null && Game.screen instanceof ScreenGame) + { + ScreenGame s = (ScreenGame) Game.screen; + for (int i = 0; i < Game.players.size(); i++) + { + if (Game.players.get(i).clientID.equals(this.clientID)) + { + Player p = Game.players.get(i); + int pr = s.shop.get(this.item).price; + if (p.coins.coins >= pr) + { + if (p.crusadeItemBar.addItem(s.shop.get(this.item))) + p.coins.coins -= pr; + + Game.eventsOut.add(new EventUpdateCoins(p)); + } + } + } + } + } +} diff --git a/src/main/java/tanks/event/EventReturnToCrusade.java b/src/main/java/tanks/event/EventReturnToCrusade.java new file mode 100755 index 00000000..a9e39de1 --- /dev/null +++ b/src/main/java/tanks/event/EventReturnToCrusade.java @@ -0,0 +1,69 @@ +package tanks.event; + +import io.netty.buffer.ByteBuf; +import tanks.Crusade; +import tanks.Game; +import tanks.Panel; +import tanks.gui.screen.ScreenPartyCrusadeInterlevel; +import tanks.gui.screen.ScreenPartyInterlevel; +import tanks.gui.screen.ScreenPartyLobby; +import tanks.network.NetworkUtils; + +public class EventReturnToCrusade extends PersonalEvent +{ + public String msg1; + public String msg2; + + public EventReturnToCrusade() + { + + } + + public EventReturnToCrusade(Crusade c) + { + if (c.win) + msg1 = "You finished the crusade!"; + else if (c.lose) + msg1 = "Game over!"; + else + { + if (Panel.levelPassed) + msg1 = "Battle cleared!"; + else + msg1 = "Battle failed!"; + } + + if (c.lifeGained) + msg2 = "You gained a life for clearing Battle " + (c.currentLevel + 1) + "!"; + else + msg2 = ""; + } + + @Override + public void execute() + { + if (this.clientID == null) + { + ScreenPartyCrusadeInterlevel s = new ScreenPartyCrusadeInterlevel(); + s.msg1 = this.msg1; + s.msg2 = this.msg2; + Game.screen = s; + + System.gc(); + } + } + + @Override + public void write(ByteBuf b) + { + NetworkUtils.writeString(b, msg1); + NetworkUtils.writeString(b, msg2); + } + + @Override + public void read(ByteBuf b) + { + msg1 = NetworkUtils.readString(b); + msg2 = NetworkUtils.readString(b); + } +} diff --git a/src/main/java/tanks/event/EventReturnToLobby.java b/src/main/java/tanks/event/EventReturnToLobby.java index e3435df8..ec6af1cd 100755 --- a/src/main/java/tanks/event/EventReturnToLobby.java +++ b/src/main/java/tanks/event/EventReturnToLobby.java @@ -19,6 +19,7 @@ public void execute() Game.cleanUp(); Game.screen = new ScreenPartyLobby(); ScreenPartyLobby.readyPlayers = 0; + ScreenPartyLobby.includedPlayers.clear(); System.gc(); } diff --git a/src/main/java/tanks/event/EventSendClientDetails.java b/src/main/java/tanks/event/EventSendClientDetails.java index 97d8c8ca..80df17f7 100644 --- a/src/main/java/tanks/event/EventSendClientDetails.java +++ b/src/main/java/tanks/event/EventSendClientDetails.java @@ -1,7 +1,9 @@ package tanks.event; import io.netty.buffer.ByteBuf; +import tanks.Crusade; import tanks.Game; +import tanks.Player; import tanks.gui.ChatMessage; import tanks.gui.screen.IPartyMenuScreen; import tanks.gui.screen.ScreenPartyHost; @@ -75,7 +77,6 @@ public void execute(ServerHandler s) s.sendEventAndClose(new EventKick("Invalid username!")); return; } - s.clientID = this.clientID; @@ -85,7 +86,7 @@ public void execute(ServerHandler s) s.username = this.username; s.rawUsername = this.username; - + synchronized (s.server.connections) { for (int i = 0; i < s.server.connections.size(); i++) @@ -99,10 +100,24 @@ public void execute(ServerHandler s) s.server.connections.add(s); } - + + synchronized (ScreenPartyHost.disconnectedPlayers) + { + for (int i = 0; i < ScreenPartyHost.disconnectedPlayers.size(); i++) + { + if (ScreenPartyHost.disconnectedPlayers.get(i).equals(this.clientID)) + { + ScreenPartyHost.disconnectedPlayers.remove(i); + i--; + } + } + } + + Game.players.add(new Player(this.clientID, this.username)); + s.sendEvent(new EventConnectionSuccess()); - s.sendEvent(new EventAnnounceConnection(new ConnectedPlayer(Game.clientID, Game.username), true)); + s.sendEvent(new EventAnnounceConnection(new ConnectedPlayer(Game.clientID, Game.player.username), true)); ScreenPartyHost.chat.add(0, new ChatMessage("\u00A7000127255255" + s.username + " has joined the party\u00A7000000000255")); @@ -111,7 +126,11 @@ public void execute(ServerHandler s) for (int i = 0; i < s.server.connections.size(); i++) { ServerHandler h = s.server.connections.get(i); - s.sendEvent(new EventAnnounceConnection(new ConnectedPlayer(h.clientID, h.rawUsername), true)); + + if (h != s) + s.sendEvent(new EventAnnounceConnection(new ConnectedPlayer(h.clientID, h.rawUsername), true)); } + + Game.eventsOut.add(new EventAnnounceConnection(new ConnectedPlayer(s.clientID, s.rawUsername), true)); } } diff --git a/src/main/java/tanks/event/EventSetItem.java b/src/main/java/tanks/event/EventSetItem.java new file mode 100644 index 00000000..995b8f35 --- /dev/null +++ b/src/main/java/tanks/event/EventSetItem.java @@ -0,0 +1,72 @@ +package tanks.event; + +import io.netty.buffer.ByteBuf; +import tanks.Game; +import tanks.Panel; +import tanks.Player; +import tanks.hotbar.Item; +import tanks.hotbar.ItemEmpty; +import tanks.hotbar.ItemRemote; +import tanks.network.NetworkUtils; + +import java.util.UUID; + +public class EventSetItem extends PersonalEvent +{ + public UUID playerID; + public int slot; + public String texture; + public int count; + + public EventSetItem() + { + + } + + public EventSetItem(Player p, int slot, Item item) + { + this.playerID = p.clientID; + this.slot = slot; + + if (item.icon == null) + this.texture = ""; + else + this.texture = item.icon; + + this.count = item.stackSize; + } + + @Override + public void write(ByteBuf b) + { + NetworkUtils.writeString(b, this.playerID.toString()); + b.writeInt(this.slot); + NetworkUtils.writeString(b, this.texture); + b.writeInt(this.count); + } + + @Override + public void read(ByteBuf b) + { + this.playerID = UUID.fromString(NetworkUtils.readString(b)); + this.slot = b.readInt(); + this.texture = NetworkUtils.readString(b); + this.count = b.readInt(); + } + + @Override + public void execute() + { + if (this.clientID == null && this.playerID.equals(Game.clientID)) + { + Item i = new ItemRemote(); + i.stackSize = this.count; + i.icon = this.texture; + + if (i.stackSize == 0) + i = new ItemEmpty(); + + Panel.panel.hotbar.currentItemBar.slots[slot] = i; + } + } +} diff --git a/src/main/java/tanks/event/EventSetItemBarSlot.java b/src/main/java/tanks/event/EventSetItemBarSlot.java new file mode 100644 index 00000000..fe8c81df --- /dev/null +++ b/src/main/java/tanks/event/EventSetItemBarSlot.java @@ -0,0 +1,49 @@ +package tanks.event; + +import io.netty.buffer.ByteBuf; +import tanks.Game; +import tanks.Player; + +public class EventSetItemBarSlot extends PersonalEvent +{ + public int slot; + + public EventSetItemBarSlot() + { + + } + + public EventSetItemBarSlot(int slot) + { + this.slot = slot; + } + + @Override + public void write(ByteBuf b) + { + b.writeInt(this.slot); + } + + @Override + public void read(ByteBuf b) + { + this.slot = b.readInt(); + } + + @Override + public void execute() + { + if (this.clientID != null) + { + for (int i = 0; i < Game.players.size(); i++) + { + Player p = Game.players.get(i); + if (p.clientID.equals(this.clientID)) + { + if (p.crusadeItemBar != null) + p.crusadeItemBar.selected = this.slot; + } + } + } + } +} diff --git a/src/main/java/tanks/event/EventShootBullet.java b/src/main/java/tanks/event/EventShootBullet.java index 5f38c0ed..6f16d0c7 100755 --- a/src/main/java/tanks/event/EventShootBullet.java +++ b/src/main/java/tanks/event/EventShootBullet.java @@ -1,6 +1,7 @@ package tanks.event; import io.netty.buffer.ByteBuf; +import tanks.Drawing; import tanks.Effect; import tanks.Game; import tanks.bullet.*; diff --git a/src/main/java/tanks/event/EventSortShopButtons.java b/src/main/java/tanks/event/EventSortShopButtons.java new file mode 100644 index 00000000..6437a377 --- /dev/null +++ b/src/main/java/tanks/event/EventSortShopButtons.java @@ -0,0 +1,51 @@ +package tanks.event; + +import io.netty.buffer.ByteBuf; +import tanks.Drawing; +import tanks.Game; +import tanks.gui.screen.ScreenGame; + +public class EventSortShopButtons extends PersonalEvent +{ + + @Override + public void write(ByteBuf b) + { + + } + + @Override + public void read(ByteBuf b) + { + + } + + @Override + public void execute() + { + if (Game.screen instanceof ScreenGame && this.clientID == null) + { + ScreenGame s = (ScreenGame) Game.screen; + for (int i = 0; i < s.shopItemButtons.size(); i++) + { + int page = i / (s.rows * 3); + int offset = 0; + + if (page * s.rows * 3 + s.rows < s.shopItemButtons.size()) + offset = -190; + + if (page * s.rows * 3 + s.rows * 2 < s.shopItemButtons.size()) + offset = -380; + + s.shopItemButtons.get(i).posY = Drawing.drawing.interfaceSizeY / 2 + s.yoffset + (i % s.rows) * 60; + + if (i / s.rows % 3 == 0) + s.shopItemButtons.get(i).posX = Drawing.drawing.interfaceSizeX / 2 + offset; + else if (i / s.rows % 3 == 1) + s.shopItemButtons.get(i).posX = Drawing.drawing.interfaceSizeX / 2 + offset + 380; + else + s.shopItemButtons.get(i).posX = Drawing.drawing.interfaceSizeX / 2 + offset + 380 * 2; + } + } + } +} diff --git a/src/main/java/tanks/event/EventTankControllerUpdateAmmunition.java b/src/main/java/tanks/event/EventTankControllerUpdateAmmunition.java index 78b3f77b..ae3c16d9 100644 --- a/src/main/java/tanks/event/EventTankControllerUpdateAmmunition.java +++ b/src/main/java/tanks/event/EventTankControllerUpdateAmmunition.java @@ -54,10 +54,10 @@ public void execute() { if (this.clientID == null && clientIdTarget.equals(Game.clientID)) { - Game.player.liveBullets = action1Live; - Game.player.liveBulletMax = action1Max; - Game.player.liveMines = action2Live; - Game.player.liveMinesMax = action2Max; + Game.playerTank.liveBullets = action1Live; + Game.playerTank.liveBulletMax = action1Max; + Game.playerTank.liveMines = action2Live; + Game.playerTank.liveMinesMax = action2Max; } } } diff --git a/src/main/java/tanks/event/EventTankControllerUpdateC.java b/src/main/java/tanks/event/EventTankControllerUpdateC.java index f453bf60..e69e083a 100644 --- a/src/main/java/tanks/event/EventTankControllerUpdateC.java +++ b/src/main/java/tanks/event/EventTankControllerUpdateC.java @@ -15,6 +15,7 @@ public class EventTankControllerUpdateC extends PersonalEvent public double angle; public boolean action1; public boolean action2; + public long time; public EventTankControllerUpdateC() { @@ -31,6 +32,7 @@ public EventTankControllerUpdateC(TankPlayerController t) this.angle = t.angle; this.action1 = t.action1; this.action2 = t.action2; + this.time = System.currentTimeMillis(); } @Override @@ -44,6 +46,7 @@ public void write(ByteBuf b) b.writeDouble(this.angle); b.writeBoolean(this.action1); b.writeBoolean(this.action2); + b.writeLong(this.time); } @Override @@ -57,6 +60,7 @@ public void read(ByteBuf b) this.angle = b.readDouble(); this.action1 = b.readBoolean(); this.action2 = b.readBoolean(); + this.time = b.readLong(); } @Override @@ -64,9 +68,9 @@ public void execute() { Tank t = Tank.idMap.get(this.tank); - if (t instanceof TankPlayerRemote && ((TankPlayerRemote) t).clientID.equals(this.clientID)) + if (t instanceof TankPlayerRemote && ((TankPlayerRemote) t).player.clientID.equals(this.clientID)) { - ((TankPlayerRemote) t).controllerUpdate(this.posX, this.posY, this.vX, this.vY, this.angle, this.action1, this.action2); + ((TankPlayerRemote) t).controllerUpdate(this.posX, this.posY, this.vX, this.vY, this.angle, this.action1, this.action2, this.frame, this.time); } } diff --git a/src/main/java/tanks/event/EventUpdateCoins.java b/src/main/java/tanks/event/EventUpdateCoins.java new file mode 100644 index 00000000..f4c3e0c5 --- /dev/null +++ b/src/main/java/tanks/event/EventUpdateCoins.java @@ -0,0 +1,48 @@ +package tanks.event; + +import io.netty.buffer.ByteBuf; +import tanks.Game; +import tanks.Player; +import tanks.network.NetworkUtils; + +import java.util.UUID; + +public class EventUpdateCoins extends PersonalEvent +{ + public UUID playerID; + public int coins; + + public EventUpdateCoins() + { + + } + + public EventUpdateCoins(Player p) + { + this.playerID = p.clientID; + this.coins = p.coins.coins; + } + + @Override + public void write(ByteBuf b) + { + NetworkUtils.writeString(b, this.playerID.toString()); + b.writeInt(this.coins); + } + + @Override + public void read(ByteBuf b) + { + this.playerID = UUID.fromString(NetworkUtils.readString(b)); + this.coins = b.readInt(); + } + + @Override + public void execute() + { + if (this.clientID == null && this.playerID.equals(Game.clientID)) + { + Game.player.coins.coins = coins; + } + } +} diff --git a/src/main/java/tanks/event/EventUpdateRemainingLives.java b/src/main/java/tanks/event/EventUpdateRemainingLives.java new file mode 100644 index 00000000..4cbe4f2a --- /dev/null +++ b/src/main/java/tanks/event/EventUpdateRemainingLives.java @@ -0,0 +1,49 @@ +package tanks.event; + +import io.netty.buffer.ByteBuf; +import tanks.Game; +import tanks.Player; +import tanks.gui.screen.ScreenPartyCrusadeInterlevel; +import tanks.network.NetworkUtils; + +import java.util.UUID; + +public class EventUpdateRemainingLives extends PersonalEvent +{ + public UUID playerID; + public int lives; + + public EventUpdateRemainingLives(Player p) + { + this.playerID = p.clientID; + this.lives = p.remainingLives; + } + + public EventUpdateRemainingLives() + { + + } + + @Override + public void write(ByteBuf b) + { + NetworkUtils.writeString(b, playerID.toString()); + b.writeInt(lives); + } + + @Override + public void read(ByteBuf b) + { + playerID = UUID.fromString(NetworkUtils.readString(b)); + lives = b.readInt(); + } + + @Override + public void execute() + { + if (clientID == null && playerID.equals(Game.clientID)) + { + Game.player.remainingLives = lives; + } + } +} diff --git a/src/main/java/tanks/event/PersonalEvent.java b/src/main/java/tanks/event/PersonalEvent.java index a7b9fe4d..bcbfb376 100755 --- a/src/main/java/tanks/event/PersonalEvent.java +++ b/src/main/java/tanks/event/PersonalEvent.java @@ -5,4 +5,5 @@ public abstract class PersonalEvent implements INetworkEvent { public UUID clientID; + public int frame = 0; } diff --git a/src/main/java/tanks/gui/Button.java b/src/main/java/tanks/gui/Button.java index 3b4ff716..4831e74a 100755 --- a/src/main/java/tanks/gui/Button.java +++ b/src/main/java/tanks/gui/Button.java @@ -126,12 +126,14 @@ public void update() double mx = Drawing.drawing.getInterfaceMouseX(); double my = Drawing.drawing.getInterfaceMouseY(); + boolean prevSel = selected; selected = (mx > posX - sizeX/2 && mx < posX + sizeX/2 && my > posY - sizeY/2 && my < posY + sizeY/2); infoSelected = (mx > posX + sizeX/2 - sizeY && mx < posX + sizeX/2 && my > posY - sizeY/2 && my < posY + sizeY/2); if (selected && Game.game.window.validPressedButtons.contains(GLFW.GLFW_MOUSE_BUTTON_1) && !clicked && enabled) { function.run(); + Drawing.drawing.playSound("bullet_explode.ogg", 2f, 0.3f); clicked = true; Game.game.window.validPressedButtons.remove((Integer)GLFW.GLFW_MOUSE_BUTTON_1); } diff --git a/src/main/java/tanks/gui/ChatBox.java b/src/main/java/tanks/gui/ChatBox.java index d8cba5ca..641fad36 100755 --- a/src/main/java/tanks/gui/ChatBox.java +++ b/src/main/java/tanks/gui/ChatBox.java @@ -17,7 +17,7 @@ public ChatBox(double x, double y, double sX, double sY, int key, String default super(x, y, sX, sY, "", f, ""); this.enableCaps = true; this.enablePunctuation = true; - this.maxChars = 84 - Game.username.length(); + this.maxChars = 84 - Game.player.username.length(); this.colorR = 200; this.colorG = 200; @@ -119,7 +119,7 @@ public void draw() drawing.setInterfaceFontSize(24); drawing.drawInterfaceText(this.posX - this.sizeX / 2 + 10, this.posY, - this.defaultTextColor + Game.username + ": \u00a7000000000255" + this.inputText + "\u00a7127127127255_", false); + this.defaultTextColor + Game.player.username + ": \u00a7000000000255" + this.inputText + "\u00a7127127127255_", false); } else if (this.persistent) { diff --git a/src/main/java/tanks/gui/Firework.java b/src/main/java/tanks/gui/Firework.java index 35134820..d1f4072b 100755 --- a/src/main/java/tanks/gui/Firework.java +++ b/src/main/java/tanks/gui/Firework.java @@ -102,7 +102,7 @@ public void drawUpdate() if (this.age >= this.maxAge) { - Drawing.drawing.playSound("/destroy.wav"); + Drawing.drawing.playSound("destroy.ogg"); removeList.add(this); diff --git a/src/main/java/tanks/gui/TextBox.java b/src/main/java/tanks/gui/TextBox.java index a6a0066f..a459af59 100755 --- a/src/main/java/tanks/gui/TextBox.java +++ b/src/main/java/tanks/gui/TextBox.java @@ -12,6 +12,8 @@ public class TextBox public double sizeX; public double sizeY; public String labelText; + + public String previousInputText; public String inputText; public boolean enableHover = false; @@ -67,6 +69,7 @@ public TextBox(double x, double y, double sX, double sY, String text, Runnable f this.labelText = text; this.inputText = defaultText; + this.previousInputText = defaultText; } public TextBox(double x, double y, double sX, double sY, String text, Runnable f, String defaultText, String hoverText) @@ -153,6 +156,7 @@ public void update() { this.inputText = ""; selected = true; + Drawing.drawing.playSound("bounce.ogg", 0.5f, 0.7f); Game.game.window.validPressedButtons.remove((Integer)GLFW.GLFW_MOUSE_BUTTON_1); } @@ -162,7 +166,17 @@ public void update() this.performValueCheck(); function.run(); + this.previousInputText = this.inputText; + Drawing.drawing.playSound("destroy.ogg", 2f); + selected = false; + } + + if (Game.game.window.validPressedKeys.contains(GLFW.GLFW_KEY_ESCAPE) && selected) + { + Game.game.window.validPressedKeys.remove((Integer)GLFW.GLFW_KEY_ESCAPE); selected = false; + this.inputText = this.previousInputText; + Drawing.drawing.playSound("bounce.ogg", 0.25f, 0.7f); } if (selected) @@ -174,7 +188,6 @@ public void update() public void checkKeys() { - boolean caps = false; if (this.enableCaps && (Game.game.window.pressedKeys.contains(GLFW.GLFW_KEY_LEFT_SHIFT) || Game.game.window.pressedKeys.contains(GLFW.GLFW_KEY_RIGHT_SHIFT))) diff --git a/src/main/java/tanks/gui/screen/Screen.java b/src/main/java/tanks/gui/screen/Screen.java index 7d1323e2..2be5495b 100755 --- a/src/main/java/tanks/gui/screen/Screen.java +++ b/src/main/java/tanks/gui/screen/Screen.java @@ -10,6 +10,7 @@ public abstract class Screen { public String screenHint = ""; + public boolean showDefaultMouse = true; public abstract void update(); @@ -43,9 +44,17 @@ public void drawDefaultBackground(double size) if (Game.enable3d) { + double z1 = 0; + if (Game.enable3dBg) + z1 = Game.tilesDepth[i][j]; + + byte o = 61; + if (Game.enable3dBg) + o = 0; + if (Game.tileDrawables[i][j] != null) { - Game.tileDrawables[i][j].drawTile(Game.tilesR[i][j], Game.tilesG[i][j], Game.tilesB[i][j], Game.tilesDepth[i][j]); + Game.tileDrawables[i][j].drawTile(Game.tilesR[i][j], Game.tilesG[i][j], Game.tilesB[i][j], z1); Game.tileDrawables[i][j] = null; } else @@ -54,18 +63,20 @@ public void drawDefaultBackground(double size) Drawing.drawing.fillBox( (i + 0.5) / Game.bgResMultiplier * Obstacle.obstacle_size, (j + 0.5) / Game.bgResMultiplier * Obstacle.obstacle_size, - Math.max(0, 2000 - size * 2000 * (1 + Game.tilesDepth[i][j] / 10)) - Obstacle.obstacle_size + Game.tilesDepth[i][j], + Math.max(0, 2000 - size * 2000 * (1 + Game.tilesDepth[i][j] / 10)) - Obstacle.obstacle_size + z1, Obstacle.obstacle_size / Game.bgResMultiplier, Obstacle.obstacle_size / Game.bgResMultiplier, Obstacle.obstacle_size); else - Drawing.drawing.fillBox( - (i + 0.5) / Game.bgResMultiplier * Obstacle.obstacle_size, + { + Drawing.drawing.fillBox( + (i + 0.5) / Game.bgResMultiplier * Obstacle.obstacle_size, (j + 0.5) / Game.bgResMultiplier * Obstacle.obstacle_size, 0, - Obstacle.obstacle_size / Game.bgResMultiplier, Obstacle.obstacle_size / Game.bgResMultiplier, - Game.tilesDepth[i][j]); + Obstacle.obstacle_size / Game.bgResMultiplier, + z1, o); + } } } else @@ -77,7 +88,7 @@ public void drawDefaultBackground(double size) } } - Drawing.drawing.setColor(0, 0, 0, Math.max(0, (int) Panel.darkness)); + Drawing.drawing.setColor(0, 0, 0, Math.max(0, Panel.darkness)); Drawing.drawing.fillBackgroundRect(Drawing.drawing.sizeX / 2, Drawing.drawing.sizeY / 2, Drawing.drawing.sizeX * 2, Drawing.drawing.sizeY * 2); } else if (Game.enable3d) diff --git a/src/main/java/tanks/gui/screen/ScreenConnecting.java b/src/main/java/tanks/gui/screen/ScreenConnecting.java index 4a2f6fbf..b86be9d6 100755 --- a/src/main/java/tanks/gui/screen/ScreenConnecting.java +++ b/src/main/java/tanks/gui/screen/ScreenConnecting.java @@ -2,13 +2,14 @@ import tanks.Drawing; import tanks.Game; +import tanks.Panel; import tanks.gui.Button; public class ScreenConnecting extends Screen { public String text = "Connecting..."; public String exception = ""; - public boolean showBack = false; + public boolean finished = false; public Thread thread; public ScreenConnecting(Thread t) @@ -30,8 +31,7 @@ public void run() @Override public void update() { - //if (this.showBack) - back.update(); + back.update(); } @Override @@ -40,11 +40,36 @@ public void draw() this.drawDefaultBackground(); Drawing.drawing.setColor(0, 0, 0); Drawing.drawing.setFontSize(24); - Drawing.drawing.drawInterfaceText(Drawing.drawing.interfaceSizeX / 2, Drawing.drawing.interfaceSizeY / 2 - 60, this.text); - Drawing.drawing.drawInterfaceText(Drawing.drawing.interfaceSizeX / 2, Drawing.drawing.interfaceSizeY / 2, this.exception); - - //if (this.showBack) - back.draw(); + + if (!this.finished) + { + Drawing.drawing.drawInterfaceText(Drawing.drawing.interfaceSizeX / 2, Drawing.drawing.interfaceSizeY / 2 - 90, this.text); + + Drawing.drawing.setColor(0, 0, 0); + + drawSpinny(100, 4, 0.3, 45, 1); + drawSpinny(99, 3, 0.5, 30, 0.75); + drawSpinny(100, 2, 0.7, 15, 0.5); + } + else + { + Drawing.drawing.drawInterfaceText(Drawing.drawing.interfaceSizeX / 2, Drawing.drawing.interfaceSizeY / 2 - 60, this.text); + Drawing.drawing.drawInterfaceText(Drawing.drawing.interfaceSizeX / 2, Drawing.drawing.interfaceSizeY / 2, this.exception); + } + + back.draw(); + } + + public void drawSpinny(int max, int parts, double speed, double size, double dotSize) + { + for (int i = 0; i < max; i++) + { + double frac = (System.currentTimeMillis() / 1000.0 * speed + i / 100.0) % 1; + double s = (i % (max * 1.0 / parts)) / 10.0 * parts; + Drawing.drawing.fillOval(Drawing.drawing.interfaceSizeX / 2 + size * Math.cos(frac * Math.PI * 2), + Drawing.drawing.interfaceSizeY / 2 - 25 + size * Math.sin(frac * Math.PI * 2), + s * dotSize, s * dotSize); + } } } diff --git a/src/main/java/tanks/gui/screen/ScreenCrusades.java b/src/main/java/tanks/gui/screen/ScreenCrusades.java index 3ae9d71b..20f675f5 100755 --- a/src/main/java/tanks/gui/screen/ScreenCrusades.java +++ b/src/main/java/tanks/gui/screen/ScreenCrusades.java @@ -99,7 +99,7 @@ public void run() Crusade.currentCrusade = new Crusade(al, "Classic Crusade"); Crusade.crusadeMode = true; - Crusade.currentCrusade.loadLevel(); + Crusade.currentCrusade.begin(); Game.screen = new ScreenGame(Crusade.currentCrusade.getShop()); } } @@ -122,7 +122,7 @@ public void run() Crusade.currentCrusade = new Crusade(al, "Wii Crusade"); Crusade.crusadeMode = true; - Crusade.currentCrusade.loadLevel(); + Crusade.currentCrusade.begin(); Game.screen = new ScreenGame(Crusade.currentCrusade.getShop()); } } @@ -139,7 +139,7 @@ public void run() { Crusade.currentCrusade = new Crusade(l.toFile(), pathSections[pathSections.length - 1].split("\\.")[0]); Crusade.crusadeMode = true; - Crusade.currentCrusade.loadLevel(); + Crusade.currentCrusade.begin(); Game.screen = new ScreenGame(Crusade.currentCrusade.getShop()); } } diff --git a/src/main/java/tanks/gui/screen/ScreenGame.java b/src/main/java/tanks/gui/screen/ScreenGame.java index d279643c..cb386abf 100755 --- a/src/main/java/tanks/gui/screen/ScreenGame.java +++ b/src/main/java/tanks/gui/screen/ScreenGame.java @@ -11,10 +11,8 @@ import tanks.tank.*; import org.lwjgl.glfw.GLFW; -import javax.naming.Name; import java.io.File; import java.util.ArrayList; -import java.util.Arrays; public class ScreenGame extends Screen { @@ -26,6 +24,8 @@ public class ScreenGame extends Screen public int rows = 6; public int yoffset = -150; + public double slant = 0; + public static boolean finished = false; public static double finishTimer = 100; public static double finishTimerMax = 100; @@ -39,6 +39,7 @@ public class ScreenGame extends Screen public boolean ready = false; public static boolean versus = false; + public String title = ""; @SuppressWarnings("unchecked") protected ArrayList[] drawables = (ArrayList[])(new ArrayList[10]); @@ -49,7 +50,7 @@ public class ScreenGame extends Screen public void run() { playing = true; - Game.player.cooldown = 20; + Game.playerTank.cooldown = 20; } } ); @@ -68,7 +69,7 @@ public void run() //synchronized(ScreenPartyHost.server.connections) { - if (ScreenPartyHost.readyPlayers.size() >= ScreenPartyHost.server.connections.size() + 1) + if (ScreenPartyHost.readyPlayers.size() >= ScreenPartyHost.includedPlayers.size()) { Game.eventsOut.add(new EventBeginLevelCountdown()); cancelCountdown = false; @@ -113,7 +114,7 @@ public void run() public void run() { paused = false; - Game.player.cooldown = 20; + Game.playerTank.cooldown = 20; } } ); @@ -124,7 +125,7 @@ public void run() public void run() { paused = false; - Game.player.cooldown = 20; + Game.playerTank.cooldown = 20; } } ); @@ -135,7 +136,7 @@ public void run() public void run() { paused = false; - Game.player.cooldown = 20; + Game.playerTank.cooldown = 20; } } ); @@ -146,7 +147,7 @@ public void run() public void run() { paused = false; - Game.player.cooldown = 20; + Game.playerTank.cooldown = 20; } } ); @@ -160,21 +161,22 @@ public void run() Game.startTime = 400; paused = false; - if (versus) - { - Game.cleanUp(); - new Level(LevelGeneratorVersus.generateLevelString()).loadLevel(); - } - else - Game.reset(); - if (ScreenPartyHost.isServer) { ready = false; readyButton.enabled = true; cancelCountdown = true; ScreenPartyHost.readyPlayers.clear(); + ScreenPartyHost.includedPlayers.clear(); } + + if (versus) + { + Game.cleanUp(); + new Level(LevelGeneratorVersus.generateLevelString()).loadLevel(); + } + else + Game.reset(); } } ); @@ -226,6 +228,7 @@ public void run() if (ScreenPartyHost.isServer) { ScreenPartyHost.readyPlayers.clear(); + ScreenPartyHost.includedPlayers.clear(); Game.eventsOut.add(new EventReturnToLobby()); } } @@ -241,6 +244,7 @@ public void run() System.gc(); Game.screen = ScreenPartyHost.activeScreen; ScreenPartyHost.readyPlayers.clear(); + ScreenPartyHost.includedPlayers.clear(); Game.eventsOut.add(new EventReturnToLobby()); versus = false; } @@ -254,6 +258,7 @@ public void run() { Game.cleanUp(); System.gc(); + ScreenPartyLobby.isClient = false; Game.screen = new ScreenJoinParty(); Client.handler.ctx.close(); ScreenPartyLobby.connections.clear(); @@ -267,7 +272,15 @@ public void run() public void run() { Crusade.crusadeMode = false; - Crusade.currentCrusade.remainingLives--; + + for (int i = 0; i < Game.movables.size(); i++) + { + if (Game.movables.get(i) instanceof TankPlayer && !Game.movables.get(i).destroy) + ((TankPlayer) Game.movables.get(i)).player.remainingLives--; + else if (Game.movables.get(i) instanceof TankPlayerRemote && !Game.movables.get(i).destroy) + ((TankPlayerRemote) Game.movables.get(i)).player.remainingLives--; + } + Game.exitToTitle(); } } @@ -285,6 +298,50 @@ public void run() } , "Note! You will lose a life for quitting---in the middle of a level------Since you do not have any other lives left,---your progress will be lost!"); + Button quitCrusadeParty = new Button(Drawing.drawing.interfaceSizeX / 2, Drawing.drawing.interfaceSizeY / 2 + 30, 350, 40, "Back to party", new Runnable() + { + @Override + public void run() + { + Crusade.crusadeMode = false; + + for (int i = 0; i < Game.movables.size(); i++) + { + if (Game.movables.get(i) instanceof TankPlayer && !Game.movables.get(i).destroy) + ((TankPlayer) Game.movables.get(i)).player.remainingLives--; + else if (Game.movables.get(i) instanceof TankPlayerRemote && !Game.movables.get(i).destroy) + ((TankPlayerRemote) Game.movables.get(i)).player.remainingLives--; + } + + Game.cleanUp(); + System.gc(); + Game.screen = ScreenPartyHost.activeScreen; + ScreenPartyHost.readyPlayers.clear(); + ScreenPartyHost.includedPlayers.clear(); + Game.eventsOut.add(new EventReturnToLobby()); + } + } + , "Note! All players will lose a life for---quitting in the middle of a level."); + + Button quitCrusadePartyFinalLife = new Button(Drawing.drawing.interfaceSizeX / 2, Drawing.drawing.interfaceSizeY / 2 + 30, 350, 40, "Back to party", new Runnable() + { + @Override + public void run() + { + Crusade.crusadeMode = false; + Crusade.currentCrusade = null; + + Game.cleanUp(); + System.gc(); + Game.screen = ScreenPartyHost.activeScreen; + ScreenPartyHost.readyPlayers.clear(); + ScreenPartyHost.includedPlayers.clear(); + Game.eventsOut.add(new EventReturnToLobby()); + } + } + , "Note! All players will lose a life for---quitting in the middle of a level------Since nobody has any other lives left,---the crusade will end!"); + + Button exitShop = new Button(Drawing.drawing.interfaceSizeX / 2, Drawing.drawing.interfaceSizeY / 2 + 300, 350, 40, "Exit shop", new Runnable() { @Override @@ -315,7 +372,7 @@ public void run() } ); - ArrayList