diff --git a/client/src/main/java/agolf/SpriteManager.java b/client/src/main/java/agolf/SpriteManager.java index 9b93944e..d9a80665 100644 --- a/client/src/main/java/agolf/SpriteManager.java +++ b/client/src/main/java/agolf/SpriteManager.java @@ -1,6 +1,5 @@ package agolf; -import agolf.game.GameBackgroundCanvas; import com.aapeli.client.ImageManager; import java.awt.Image; @@ -26,23 +25,6 @@ protected void loadSprites() { this.balls = this.parseSpriteSheet("balls", 8, 4, 13, 13); this.pixelshapeMasks = new int[28][][]; this.specialPixelMasks = new int[28][][]; - this.anIntArrayArray968 = new int[GameBackgroundCanvas.trackAdvertSize][]; - - for (int var1 = 0; var1 < GameBackgroundCanvas.trackAdvertSize; ++var1) { - try { - String var2 = "ad" + var1; - Image var3 = this.imageManager.getImage(var2); - if (var3 != null) { - this.imageManager.unloadImage(var2); - this.anIntArrayArray968[var1] = this.imageManager.getPixels( - var3, - GameBackgroundCanvas.anIntArray78[var1] * 15, - GameBackgroundCanvas.anIntArray79[var1] * 15); - } - } catch (Exception | OutOfMemoryError e) { - this.anIntArrayArray968[var1] = null; - } - } } /** diff --git a/client/src/main/java/agolf/game/GameBackgroundCanvas.java b/client/src/main/java/agolf/game/GameBackgroundCanvas.java index 0df732be..3fff168e 100644 --- a/client/src/main/java/agolf/game/GameBackgroundCanvas.java +++ b/client/src/main/java/agolf/game/GameBackgroundCanvas.java @@ -6,46 +6,28 @@ import java.awt.Color; import java.awt.Graphics; import java.awt.Image; -import java.util.StringTokenizer; +import org.moparforia.shared.tracks.Track; +import org.moparforia.shared.tracks.stats.TrackStats; public class GameBackgroundCanvas extends Canvas { protected static final Color aColor75 = new Color(240, 240, 255); - private static final String mapChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - private static final String defaultTrackSettings = "fttt14"; public static final int[] anIntArray78 = new int[] {3, 5, 8, 49}; public static final int[] anIntArray79 = new int[] {2, 3, 5, 25}; - public static final String[] aStringArray80 = new String[] {"small", "medium", "large", "full"}; - public static final int trackAdvertSize = aStringArray80.length; protected GameContainer gameContainer; private Image backgroundImg; protected Image image; private Graphics graphics; - private String trackAuthor; - private String trackName; - private String trackComment; - private String trackSettings; - private String trackFirstBest; - private String trackLastBest; - private int[] trackStats; - private int[] trackRatings; - protected int[][] trackTiles; - protected byte[][] collisionMap; - private boolean[] trackSpecialSettings; - private int[][] anIntArrayArray97; - private boolean[] aBooleanArray98; + public Track track; + public TrackStats trackStats; + public Map map; + private int trackWidth = 735; + private int trackHeight = 375; protected GameBackgroundCanvas(GameContainer gameContainer, Image backgroundImage) { this.gameContainer = gameContainer; this.backgroundImg = backgroundImage; - this.setSize(735, 375); - this.trackAuthor = this.trackName = null; - this.trackTiles = new int[49][25]; - this.anIntArrayArray97 = new int[trackAdvertSize][2]; - - for (int var3 = 0; var3 < trackAdvertSize; ++var3) { - this.anIntArrayArray97[var3][0] = this.anIntArrayArray97[var3][1] = -1; - } + this.setSize(this.trackWidth, this.trackHeight); } public void addNotify() { @@ -60,28 +42,21 @@ public void paint(Graphics g) { public void update(Graphics g) { if (this.image == null) { g.setColor(GolfGameFrame.colourGameBackground); - g.fillRect(0, 0, 735, 375); + g.fillRect(0, 0, this.trackWidth, this.trackHeight); } else { g.drawImage(this.image, 0, 0, this); } } - protected String[] generateTrackInformation() { - return new String[] {this.trackAuthor, this.trackName, this.trackFirstBest, this.trackLastBest}; - } - - protected int[][] generateTrackStatistics() { - return new int[][] {this.trackStats, this.trackRatings}; - } - // this useless func is called when we get start packet - // iniatilize variables + // initialize variables // draws map as grass // this.gameCanvas.createMap(16777216); // 16777216 == grass - protected void createMap(int var1) { + protected void initializeGameArea() { + int tileCode = 16777216; if (this.image == null) { - this.image = this.createImage(735, 375); + this.image = this.createImage(this.trackWidth, this.trackHeight); if (this.image == null) { this.image = this.backgroundImg; } @@ -90,14 +65,12 @@ protected void createMap(int var1) { } Image var2 = this.gameContainer.imageManager.createImage( - this.gameContainer.spriteManager.getPixelsFromTileCode(var1), 15, 15); + this.gameContainer.spriteManager.getPixelsFromTileCode(tileCode), 15, 15); this.graphics.setColor(aColor75); for (int y = 0; y < 25; ++y) { for (int x = 0; x < 49; ++x) { - - this.trackTiles[x][y] = var1; - if (var1 == 0) { + if (tileCode == 0) { this.graphics.fillRect(x * 15, y * 15, 15, 15); } else { this.graphics.drawImage(var2, x * 15, y * 15, this); @@ -108,460 +81,67 @@ protected void createMap(int var1) { this.repaint(); } - protected boolean parseMapCommands(String map) { - try { - return this.parseMapInstruction(map); - } catch (Exception e) { - return false; - } - } - - protected Image getTileAt(int var1, int var2) { - int[] imageData = this.gameContainer.spriteManager.getPixelsFromTileCode(this.trackTiles[var1][var2]); + protected Image getTileImageAt(int tileX, int tileY) { + int[] imageData = this.gameContainer.spriteManager.getPixelsFromTileCode( + this.map.getTile(tileX, tileY).getCode()); if (this.gameContainer.graphicsQualityIndex >= 2) { - for (int var4 = 0; var4 < 15; ++var4) { - for (int var5 = 0; var5 < 15; ++var5) { - for (int var6 = 1; - var6 <= 7 && var1 * 15 + var5 - var6 > 0 && var2 * 15 + var4 - var6 > 0; - ++var6) { - if (this.castsShadow(var1 * 15 + var5 - var6, var2 * 15 + var4 - var6)) { - this.shiftPixel(imageData, var5, var4, -8, 15); - } - } - - this.shiftPixel(imageData, var5, var4, (int) (Math.random() * 11.0D) - 5, 15); - } - } - } - - Image var7 = this.gameContainer.imageManager.createImage(imageData, 15, 15); - this.graphics.drawImage(var7, var1 * 15, var2 * 15, this); - return var7; - } - - protected void collisionMap(int tileX, int tileY) { - int special = this.trackTiles[tileX][tileY] / 16777216; - int shape = this.trackTiles[tileX][tileY] / 65536 % 256; - int background = this.trackTiles[tileX][tileY] / 256 % 256; - int foreground = this.trackTiles[tileX][tileY] % 256; - int pixel = Integer.MIN_VALUE; - - if (special == 1 && (background == 19 || foreground == 19)) { // IF HAX BLOCK - this.aBooleanArray98[0] = true; - } else if (special == 2 && shape == 2) { - this.aBooleanArray98[1] = true; - } - - int[][] mask = this.gameContainer.spriteManager.getPixelMask(special, shape); - - for (int y = 0; y < 15; ++y) { for (int x = 0; x < 15; ++x) { - - if (special == 1) { - pixel = mask[x][y] == 1 ? background : foreground; - - } else if (special == 2) { - shape += 24; - pixel = mask[x][y] == 1 ? background : shape; - // 24 StartPosition - if (shape == 24) { - pixel = background; - } - // 26 Fake Hole - if (shape == 26) { - pixel = background; - } - // Teleport Exits - if (shape == 33 || shape == 35 || shape == 37 || shape == 39) { - pixel = background; - } - - // Bricks - if (shape >= 40 && shape <= 43) { - pixel = shape; - } - - // magnet - if (shape == 44) { - pixel = background != 12 && background != 13 && background != 14 && background != 15 - ? shape - : background; - } - - // magnet repel - if (shape == 45) { - pixel = background; - } - - shape -= 24; - } - - this.collisionMap[tileX * 15 + x][tileY * 15 + y] = (byte) pixel; - } - } - } - - protected String getTrackComment() { - return this.trackComment; - } - - protected String getTrackSettings() { - return this.trackSettings.equals("fttt14") ? null : this.trackSettings; - } - - protected boolean[] method120() { - return this.aBooleanArray98; - } - - private boolean parseMapInstruction(String map) { - this.trackSettings = defaultTrackSettings; - this.trackFirstBest = null; - this.trackLastBest = null; - this.trackComment = null; - this.trackStats = null; - this.trackRatings = null; - - StringTokenizer tokenizer = new StringTokenizer(map, "\n"); - int requiredLinesParsed = 0; - while (tokenizer.hasMoreTokens()) { - String line = tokenizer.nextToken(); - if (line.startsWith("V ") && Integer.parseInt(line.substring(2)) == 1) { - requiredLinesParsed++; - } else if (line.startsWith("A ")) { - requiredLinesParsed++; - this.trackAuthor = line.substring(2).trim(); - } else if (line.startsWith("N ")) { - requiredLinesParsed++; - this.trackName = line.substring(2).trim(); - } else if (line.startsWith("C ")) { - this.trackComment = line.substring(2).trim(); - } else if (line.startsWith("S ")) { - this.trackSettings = line.substring(2).trim(); - if (trackSettings.length() != 6) { - return false; - } - } else if (line.startsWith("I ")) { - StringTokenizer subtknzr = new StringTokenizer(line.substring(2), ","); - if (subtknzr.countTokens() != 4) { - return false; - } - /* - * 0 = num of completions - * 1 = num of strokes - * 2 = best num of strokes - * 3 = num of players who got best num of strokes - */ - this.trackStats = new int[4]; - for (int i = 0; i < 4; i++) { - this.trackStats[i] = Integer.parseInt(subtknzr.nextToken()); - } - } else if (line.startsWith("B ")) { - this.trackFirstBest = line.substring(2); - } else if (line.startsWith("L ")) { - this.trackLastBest = line.substring(2); - } else if (line.startsWith("R ")) { - StringTokenizer subTokenizer = new StringTokenizer(line.substring(2), ","); - if (subTokenizer.countTokens() != 11) { - return false; - } - this.trackRatings = new int[11]; - for (int i = 0; i < 11; i++) { - this.trackRatings[i] = Integer.parseInt(subTokenizer.nextToken()); - } - } else if (line.startsWith("T ")) { - requiredLinesParsed++; - /* - * - * The below is the map parsing: - * firstly the input map is "expanded", any letter preceeding by a number is duplicated that number times. - * If input letter is A,B,C, the letter + the next three are concatenated into one int (4 * bytes) - * If input letters are D,E,F,G,H,I, the current tile is exactly the same as an adjacent one so - * one is selected, depending on the input letter. - * - * - */ - String mapData = line.substring(2); - - StringTokenizer subTokenizer = new StringTokenizer(mapData, ","); - mapData = this.expandMap(subTokenizer.nextToken()); - int cursorIndex = 0; - - int tileX; - for (int tileY = 0; tileY < 25; ++tileY) { - for (tileX = 0; tileX < 49; ++tileX) { - - int currentMapIndex = mapChars.indexOf(mapData.charAt(cursorIndex)); - - if (currentMapIndex <= 2) { // if input= A,B or C - int mapcursor_one_ahead; - int mapcursor_two_ahead; - int mapcursor_three_ahead; - - if (currentMapIndex == 1) { // if input = B. - mapcursor_one_ahead = mapChars.indexOf(mapData.charAt(cursorIndex + 1)); - mapcursor_two_ahead = mapChars.indexOf(mapData.charAt(cursorIndex + 2)); - mapcursor_three_ahead = mapChars.indexOf(mapData.charAt(cursorIndex + 3)); - cursorIndex += 4; - } else { // if input = A or C - mapcursor_one_ahead = mapChars.indexOf(mapData.charAt(cursorIndex + 1)); - mapcursor_two_ahead = mapChars.indexOf(mapData.charAt(cursorIndex + 2)); - mapcursor_three_ahead = 0; - cursorIndex += 3; - } - - // (currentMapIndex << 24) + (mapcursor_one_ahead << 16) + - // (mapcursor_two_ahead << 8) + mapcursor_three_ahead; - this.trackTiles[tileX][tileY] = currentMapIndex * 256 * 256 * 256 - + mapcursor_one_ahead * 256 * 256 - + mapcursor_two_ahead * 256 - + mapcursor_three_ahead; - } else { - if (currentMapIndex == 3) { // if input = D - this.trackTiles[tileX][tileY] = - this.trackTiles[tileX - 1][tileY]; // tile to west is same as current - } - - if (currentMapIndex == 4) { // if input = E; - this.trackTiles[tileX][tileY] = - this.trackTiles[tileX][tileY - 1]; // tile to the north is same as current - } - - if (currentMapIndex == 5) { // if input = F; - this.trackTiles[tileX][tileY] = - this.trackTiles[tileX - 1][tileY - 1]; // tile to the northwest is same as - // current - } - - if (currentMapIndex == 6) { // if input = G; - this.trackTiles[tileX][tileY] = - this.trackTiles[tileX - 2][tileY]; // 2 tiles west is same as current (skip a - // tile to the left) - } - - if (currentMapIndex == 7) { // if input = H - this.trackTiles[tileX][tileY] = - this.trackTiles[tileX][tileY - 2]; // 2 tiles north is same as current - // (skip the tile above) - } - - if (currentMapIndex == 8) { // if input= I - this.trackTiles[tileX][tileY] = - this.trackTiles[tileX - 2][tileY - 2]; // 2 tiles northwest is same as - // current (skip the diagonal) - } - - ++cursorIndex; + for (int y = 0; y < 15; ++y) { + for (int z = 1; z <= 7 && tileX * 15 + y - z > 0 && tileY * 15 + x - z > 0; ++z) { + if (this.castsShadow(tileX * 15 + y - z, tileY * 15 + x - z)) { + this.shiftPixel(imageData, y, x, -8, 15); } } - } - for (tileX = 0; tileX < trackAdvertSize; ++tileX) { - this.anIntArrayArray97[tileX][0] = this.anIntArrayArray97[tileX][1] = -1; - } - - int var12; - int var14; - if (subTokenizer.hasMoreTokens()) { - mapData = subTokenizer.nextToken(); - if (!mapData.startsWith("Ads:")) { - return false; - } - - mapData = mapData.substring(4); - var12 = mapData.length() / 5; - - for (int var13 = 0; var13 < var12; ++var13) { - var14 = mapChars.indexOf(mapData.charAt(var13 * 5)); - this.anIntArrayArray97[var14][0] = - Integer.parseInt(mapData.substring(var13 * 5 + 1, var13 * 5 + 3)); - this.anIntArrayArray97[var14][1] = - Integer.parseInt(mapData.substring(var13 * 5 + 3, var13 * 5 + 5)); - } + this.shiftPixel(imageData, y, x, (int) (Math.random() * 11.0D) - 5, 15); } } } - if (requiredLinesParsed != 4) { - return false; - } - this.trackSpecialSettings = new boolean[4]; - for (int i = 0; i < 4; i++) { - this.trackSpecialSettings[i] = this.trackSettings.charAt(i) == 't'; - } - /* - * this is default value: - * trackSpecialSettings[0]= false - * trackSpecialSettings[1]= true - * trackSpecialSettings[2]= true - * trackSpecialSettings[3]= true - */ - - this.checkSolids(); - this.drawMap(); - return true; + Image resultImage = this.gameContainer.imageManager.createImage(imageData, 15, 15); + this.graphics.drawImage(resultImage, tileX * 15, tileY * 15, this); + return resultImage; } - private String expandMap(String mapString) { - StringBuffer buffer = new StringBuffer(4900); - int length = mapString.length(); - - for (int var4 = 0; var4 < length; ++var4) { - int var5 = this.method123(mapString, var4); - if (var5 >= 2) { - ++var4; - } - - if (var5 >= 10) { - ++var4; - } - - if (var5 >= 100) { - ++var4; - } - - if (var5 >= 1000) { - ++var4; - } - - char var6 = mapString.charAt(var4); - - buffer.append(String.valueOf(var6).repeat(Math.max(0, var5))); - } - - return buffer.toString(); - } - - private int method123(String var1, int var2) { - String var3 = null; - - while (true) { - char var4 = var1.charAt(var2); - if (var4 < '0' || var4 > '9') { - return var3 == null ? 1 : Integer.parseInt(var3); - } - - if (var3 == null) { - var3 = String.valueOf(var4); - } else { - var3 = var3 + var4; - } - - ++var2; - } - } - - private void checkSolids() { - this.aBooleanArray98 = new boolean[2]; - this.aBooleanArray98[0] = this.aBooleanArray98[1] = false; - this.collisionMap = new byte[735][375]; - - for (int y = 0; y < 25; ++y) { - for (int x = 0; x < 49; ++x) { - this.collisionMap(x, y); - } - } - } - - private void drawMap() { + public void drawMap() { int[] mapPixels = new int[275625]; int[] currentTileImageData = null; - int oldTile = -1; + Tile oldTile = null; boolean trackTestMode = this.gameContainer.synchronizedTrackTestMode.get(); // controls when to draw starting positions - int currentTile; + Tile currentTile; int yPixels; int xPixels; - int var13; + int index; + Map map = this.map; for (int tileY = 0; tileY < 25; ++tileY) { for (int tileX = 0; tileX < 49; ++tileX) { + currentTile = map.getTile(tileX, tileY); + if (!currentTile.equals(oldTile)) { + currentTile = map.getTile(tileX, tileY); - if (this.trackTiles[tileX][tileY] != oldTile) { - currentTile = this.trackTiles[tileX][tileY]; - - int specialStatus = currentTile / 16777216; - - int currentTileSpecialId = currentTile / 65536 % 256 + 24; - int background = currentTile / 256 % 256; - - if (specialStatus == 2) { - // 16777216 == blank tile with grass - // 34144256 == teleport blue exit with grass - // 34078720 == teleport start with grass - - // 0:false => mines invisible 0:true => mines visible - - if (!this.trackSpecialSettings[0] - && (currentTileSpecialId == 28 || currentTileSpecialId == 30)) { - currentTile = 16777216 + background * 256; - } - - // 1:false => magnets invisible 1:true => magnets visible - - if (!this.trackSpecialSettings[1] - && (currentTileSpecialId == 44 || currentTileSpecialId == 45)) { - currentTile = 16777216 + background * 256; - } - - // 2:false => teleport colorless 2:true => normal colors - if (!this.trackSpecialSettings[2]) { - if (currentTileSpecialId == 34 - || currentTileSpecialId == 36 - || currentTileSpecialId == 38) { - currentTile = 34078720 + background * 256; - } - - if (currentTileSpecialId == 35 - || currentTileSpecialId == 37 - || currentTileSpecialId == 39) { - currentTile = 34144256 + background * 256; - } - } - } - - currentTileImageData = this.gameContainer.spriteManager.getPixelsFromTileCode(currentTile); - - oldTile = this.trackTiles[tileX][tileY]; + int currentCode = currentTile.getSpecialsettingCode(this.track.getSpecialSettings()); + currentTileImageData = this.gameContainer.spriteManager.getPixelsFromTileCode(currentCode); // draws debug points on starting positions - if (trackTestMode && specialStatus == 2) { - yPixels = -1; - // Starting Point common - if (currentTileSpecialId == 24) { - yPixels = 16777215; - } - - // Start blue - if (currentTileSpecialId == 48) { - yPixels = 11579647; - } - // Start red - if (currentTileSpecialId == 49) { - yPixels = 16752800; - } - // Start yellow - if (currentTileSpecialId == 50) { - yPixels = 16777088; - } - // Start green - if (currentTileSpecialId == 51) { - yPixels = 9502608; - } - + if (trackTestMode && currentTile.getCode() == 2) { + yPixels = currentTile.getYPixelsFromSpecialId(); if (yPixels != -1) { for (xPixels = 6; xPixels <= 8; ++xPixels) { - for (var13 = 6; var13 <= 8; ++var13) { - currentTileImageData[xPixels * 15 + var13] = yPixels; + for (index = 6; index <= 8; ++index) { + currentTileImageData[xPixels * 15 + index] = yPixels; } } } } + oldTile = map.getTile(tileX, tileY); } - for (currentTile = 0; currentTile < 15; ++currentTile) { + for (xPixels = 0; xPixels < 15; ++xPixels) { for (yPixels = 0; yPixels < 15; ++yPixels) { - mapPixels[(tileY * 15 + currentTile) * 735 + tileX * 15 + yPixels] = - currentTileImageData[currentTile * 15 + yPixels]; + mapPixels[(tileY * 15 + xPixels) * 735 + tileX * 15 + yPixels] = + currentTileImageData[xPixels * 15 + yPixels]; } } } @@ -600,11 +180,11 @@ private void drawMap() { // draws shadow if (this.gameContainer.graphicsQualityIndex >= 2) { - for (var13 = 1; var13 <= 7 && xPixels + var13 < 735 && yPixels + var13 < 375; ++var13) { + for (index = 1; index <= 7 && xPixels + index < 735 && yPixels + index < 375; ++index) { if (!this.castsShadow( - xPixels + var13, yPixels + var13)) { // dont draw shadow on blocks - var14 = xPixels + var13; - var15 = yPixels + var13; + xPixels + index, yPixels + index)) { // dont draw shadow on blocks + var14 = xPixels + index; + var15 = yPixels + index; // shift pixels towards black to create shadow this.shiftPixel(mapPixels, var14, var15, -8, 735); } @@ -613,13 +193,13 @@ private void drawMap() { } // creates light and dark spots to teleport starts - if (this.isTeleportStart(xPixels, yPixels)) { - var25 = this.isTeleportStart(xPixels - 1, yPixels - 1); - var27 = this.isTeleportStart(xPixels + 1, yPixels + 1); + if (map.isTeleportStart(xPixels, yPixels)) { + var25 = map.isTeleportStart(xPixels - 1, yPixels - 1); + var27 = map.isTeleportStart(xPixels + 1, yPixels + 1); if (!var25 && var27 - && !this.isTeleportStart(xPixels, yPixels - 1) - && !this.isTeleportStart(xPixels - 1, yPixels)) { + && !map.isTeleportStart(xPixels, yPixels - 1) + && !map.isTeleportStart(xPixels - 1, yPixels)) { this.shiftPixel(mapPixels, xPixels, yPixels, 16, 735); } else { if (!var25 && var27) { @@ -636,84 +216,23 @@ private void drawMap() { // creates grain effect on tiles if (this.gameContainer.graphicsQualityIndex >= 2) { - var13 = (int) (Math.random() * 11.0D) - 5; - this.shiftPixel(mapPixels, xPixels, yPixels, var13, 735); + index = (int) (Math.random() * 11.0D) - 5; + this.shiftPixel(mapPixels, xPixels, yPixels, index, 735); } } } } - - int[][] var26 = this.gameContainer.spriteManager.method1138(); - currentTile = -1; - - for (yPixels = trackAdvertSize - 2; yPixels >= 0 && currentTile == -1; --yPixels) { - if (this.anIntArrayArray97[yPixels][0] >= 0 - && this.anIntArrayArray97[yPixels][1] >= 0 - && var26[yPixels] != null) { - currentTile = yPixels; - } - } - - if (currentTile == -1 && var26[trackAdvertSize - 1] != null) { - currentTile = trackAdvertSize - 1; - } - - if (currentTile >= 0) { - double var16 = 0.4D - (double) currentTile * 0.05D; - var14 = 0; - var15 = 0; - int var18 = 735; - int var19 = 375; - int var20 = 0; - int var21 = 0; - if (currentTile < trackAdvertSize - 1) { - var14 = this.anIntArrayArray97[currentTile][0] * 15; - var15 = this.anIntArrayArray97[currentTile][1] * 15; - var18 = anIntArray78[currentTile] * 15; - var19 = anIntArray79[currentTile] * 15; - } - - for (int var22 = var15; var22 < var15 + var19; ++var22) { - for (int var23 = var14; var23 < var14 + var18; ++var23) { - if (currentTile < 3 - || currentTile == 3 - && this.collisionMap[var23][var22] >= 0 - && this.collisionMap[var23][var22] <= 15) { - mapPixels[var22 * 735 + var23] = this.method129( - mapPixels[var22 * 735 + var23], var26[currentTile][var21 * var18 + var20], var16); - } - - ++var20; - } - - ++var21; - var20 = 0; - } - } } catch (OutOfMemoryError e) { } - this.graphics.drawImage(this.gameContainer.imageManager.createImage(mapPixels, 735, 375), 0, 0, this); + this.graphics.drawImage( + this.gameContainer.imageManager.createImage(mapPixels, this.trackWidth, this.trackHeight), 0, 0, this); } private boolean castsShadow(int x, int y) { // trackSpecialSettings[3] // 3:false => illusion walls shadowless 3:true => illusion walls shadows - return x >= 0 && x < 735 && y >= 0 && y < 375 - ? this.collisionMap[x][y] >= 16 - && this.collisionMap[x][y] <= 23 - && (this.trackSpecialSettings[3] - || !this.trackSpecialSettings[3] && this.collisionMap[x][y] != 19) - : false; - } - - private boolean isTeleportStart(int x, int y) { - return x >= 0 && x < 735 && y >= 0 && y < 375 - ? this.collisionMap[x][y] == 32 - || this.collisionMap[x][y] == 34 - || this.collisionMap[x][y] == 36 - || this.collisionMap[x][y] == 38 - : false; + return this.map.castShadow(x, y, this.track.getSpecialSettings()); } // adds offset to r,b,g channels of pixels[x][y] then clamps the value to valid range @@ -751,25 +270,4 @@ private void shiftPixel(int[] pixels, int x, int y, int offset, int width) { pixels[y * width + x] = -16777216 + red * 256 * 256 + green * 256 + blue; } - - private int method129(int var1, int var2, double var3) { - long var5 = ((long) var2 & 4278190080L) >> 24; - if (var5 < 255L) { - return var1; - } else { - int var7 = (var1 & 16711680) >> 16; - int var8 = (var1 & 65280) >> 8; - int var9 = var1 & 255; - int var10 = (var2 & 16711680) >> 16; - int var11 = (var2 & 65280) >> 8; - int var12 = var2 & 255; - int var13 = var10 - var7; - int var14 = var11 - var8; - int var15 = var12 - var9; - int var16 = (int) ((double) var7 + (double) var13 * var3 + 0.5D); - int var17 = (int) ((double) var8 + (double) var14 * var3 + 0.5D); - int var18 = (int) ((double) var9 + (double) var15 * var3 + 0.5D); - return (int) (4278190080L + (long) (var16 << 16) + (long) (var17 << 8) + (long) var18); - } - } } diff --git a/client/src/main/java/agolf/game/GameCanvas.java b/client/src/main/java/agolf/game/GameCanvas.java index 87efbb4c..e08c27bf 100644 --- a/client/src/main/java/agolf/game/GameCanvas.java +++ b/client/src/main/java/agolf/game/GameCanvas.java @@ -19,7 +19,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.StringTokenizer; +import org.moparforia.shared.tracks.parsers.VersionedTrackFileParser; public class GameCanvas extends GameBackgroundCanvas implements Runnable, MouseMotionListener, MouseListener, KeyListener { @@ -33,44 +33,17 @@ public class GameCanvas extends GameBackgroundCanvas private static final Color blackColour = Color.black; private static final Color whiteColour = Color.white; private static final Color backgroundColour = new Color(19, 167, 19); - private int gameState; private Image[] ballSprites; - private int playerCount; - private int onShoreSetting; - private int collisionMode; - private int currentPlayerID; private int mouseX; private int mouseY; private int shootingMode; - private int anInt2816; - private double startPositionX; - private double startPositionY; - private double bounciness; - private double somethingSpeedThing; - private double[] resetPositionX; - private double[] resetPositionY; - private List[] teleportStarts; - private List[] teleportExists; - private short[][][] magnetMap; - private double[] playerX; - private double[] playerY; - private double[] speedX; - private double[] speedY; - private boolean[] aBooleanArray2830; - private SynchronizedBool[] onHoleSync; // not sure - private boolean isLocalPlayer; private int playerNamesDisplayMode; // 0 == Hide names, 1 == Show initials, 2 == Show names, 3 == // Name + clan - private boolean[] aBooleanArray2834; - private String aString2835; - private Seed rngSeed; - private static int[] anIntArray2837 = new int[] {Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE}; - private static int anInt2838 = 2; - private int anInt2839; - private Image anImage2840; + private String encodedCoordinates; + private static int[] frameTimeHistory = new int[] {Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE}; + private Image gameArea; private Graphics graphics; - private Thread aThread2842; - private boolean aBoolean2843; + private Thread shotThread; private boolean norandom; // aimbot stuff @@ -79,13 +52,16 @@ public class GameCanvas extends GameBackgroundCanvas private double hackedY = 0; private boolean isCheating = false; + private GameState state; + protected GameCanvas(GameContainer gameContainer, Image image, Cursor c) { super(gameContainer, image); + this.state = new GameState(); this.ballSprites = gameContainer.spriteManager.getBalls(); - this.playerCount = this.currentPlayerID = this.mouseX = this.mouseY = -1; + this.state.playerCount = this.state.currentPlayerId = this.mouseX = this.mouseY = -1; this.playerNamesDisplayMode = 0; - this.gameState = 0; - this.anInt2839 = anInt2838; + this.state.gameState = 0; + this.state.maxPhysicsIterations = 2; this.norandom = Parameters.getBooleanValue(gameContainer.params.getParameter("norandom")); // TODO: would be cool if user can set their own cursor this.cursorCrosshair = c; @@ -93,19 +69,19 @@ protected GameCanvas(GameContainer gameContainer, Image image, Cursor c) { @Override public void update(Graphics g) { - if (this.anImage2840 == null) { - this.anImage2840 = this.createImage(735, 375); - this.graphics = this.anImage2840.getGraphics(); + if (this.gameArea == null) { + this.gameArea = this.createImage(735, 375); + this.graphics = this.gameArea.getGraphics(); } super.update(this.graphics); - if (this.gameState == 1 && this.mouseX > -1 && this.mouseY > -1) { - double[] power = this.getStrokePower(this.currentPlayerID, this.mouseX, this.mouseY); + if (this.state.gameState == 1 && this.mouseX > -1 && this.mouseY > -1) { + double[] power = this.getStrokePower(this.state.currentPlayerId, this.mouseX, this.mouseY); - int x1 = (int) (this.playerX[this.currentPlayerID] + 0.5D); - int y1 = (int) (this.playerY[this.currentPlayerID] + 0.5D); - int x2 = (int) (this.playerX[this.currentPlayerID] + power[0] * 200.0D / 6.5D + 0.5D); - int y2 = (int) (this.playerY[this.currentPlayerID] + power[1] * 200.0D / 6.5D + 0.5D); + int x1 = (int) (this.state.playerX[this.state.currentPlayerId] + 0.5D); + int y1 = (int) (this.state.playerY[this.state.currentPlayerId] + 0.5D); + int x2 = (int) (this.state.playerX[this.state.currentPlayerId] + power[0] * 200.0D / 6.5D + 0.5D); + int y2 = (int) (this.state.playerY[this.state.currentPlayerId] + power[1] * 200.0D / 6.5D + 0.5D); this.graphics.setColor(colourAimLine); if (this.shootingMode == 0) { this.graphics.drawLine(x1, y1, x2, y2); @@ -135,21 +111,22 @@ public void update(Graphics g) { } } - if (this.currentPlayerID > -1) { + if (this.state.currentPlayerId > -1) { this.graphics.setFont(gameFont); this.graphics.setColor(blackColour); - for (int player = 0; player < this.playerCount; ++player) { - if (this.aBooleanArray2830[player] && player != this.currentPlayerID) { - this.drawPlayer(this.graphics, player, this.onHoleSync[player].get() ? 2.1666666666666665D : 0.0D); + for (int player = 0; player < this.state.playerCount; ++player) { + if (this.state.simulatePlayer[player] && player != this.state.currentPlayerId) { + this.drawPlayer( + this.graphics, player, this.state.onHoleSync[player].get() ? 2.1666666666666665D : 0.0D); } } this.graphics.setColor(whiteColour); this.drawPlayer( this.graphics, - this.currentPlayerID, - this.onHoleSync[this.currentPlayerID].get() ? 2.1666666666666665D : 0.0D); + this.state.currentPlayerId, + this.state.onHoleSync[this.state.currentPlayerId].get() ? 2.1666666666666665D : 0.0D); } if (isCheating) { @@ -164,7 +141,7 @@ public void update(Graphics g) { ballSpriteOffset = (x / 5 + y / 5) % 2 * 4; } graphics.drawImage( - this.ballSprites[this.currentPlayerID + ballSpriteOffset], + this.ballSprites[this.state.currentPlayerId + ballSpriteOffset], x, y, x + 13, @@ -176,51 +153,46 @@ public void update(Graphics g) { this); } - g.drawImage(this.anImage2840, 0, 0, this); + g.drawImage(this.gameArea, 0, 0, this); } @Override public void run() { Image ballImage = this.createImage(735, 375); - Image var2 = super.image; + Image gameImage = super.image; Graphics ballGraphic = ballImage.getGraphics(); Graphics canvas = this.getGraphics(); - ballGraphic.drawImage(var2, 0, 0, this); + ballGraphic.drawImage(gameImage, 0, 0, this); canvas.drawImage(ballImage, 0, 0, this); int loopStuckCounter = 0; - int[] magnetStuckCounter = new int[this.playerCount]; - int[] downhillStuckCounter = new int[this.playerCount]; - double[] tempCoordX = new double[this.playerCount]; - double[] tempCoordY = new double[this.playerCount]; - double[] var10 = new double[this.playerCount]; - double[] tempCoord2X = new double[this.playerCount]; - double[] tempCoord2Y = new double[this.playerCount]; - double[] tempCoord3X = new double[this.playerCount]; - double[] tempCoord3Y = new double[this.playerCount]; - boolean[] onHole = new boolean[this.playerCount]; - boolean[] onLiquidOrSwamp = new boolean[this.playerCount]; - boolean[] teleported = new boolean[this.playerCount]; - int[] spinningStuckCounter = new int[this.playerCount]; - - for (int player = 0; player < this.playerCount; ++player) { + int[] magnetStuckCounter = new int[this.state.playerCount]; + int[] downhillStuckCounter = new int[this.state.playerCount]; + double[] tempCoordX = new double[this.state.playerCount]; + double[] tempCoordY = new double[this.state.playerCount]; + double[] onHoleTimer = new double[this.state.playerCount]; + double[] tempCoord2X = new double[this.state.playerCount]; + double[] tempCoord2Y = new double[this.state.playerCount]; + double[] tempCoord3X = new double[this.state.playerCount]; + double[] tempCoord3Y = new double[this.state.playerCount]; + boolean[] onHole = new boolean[this.state.playerCount]; + boolean[] onLiquidOrSwamp = new boolean[this.state.playerCount]; + boolean[] teleported = new boolean[this.state.playerCount]; + int[] spinningStuckCounter = new int[this.state.playerCount]; + + for (int player = 0; player < this.state.playerCount; ++player) { magnetStuckCounter[player] = downhillStuckCounter[player] = 0; - tempCoordX[player] = tempCoord2X[player] = this.playerX[player]; - tempCoordY[player] = tempCoord2Y[player] = this.playerY[player]; + tempCoordX[player] = tempCoord2X[player] = this.state.playerX[player]; + tempCoordY[player] = tempCoord2Y[player] = this.state.playerY[player]; onHole[player] = onLiquidOrSwamp[player] = false; - var10[player] = this.onHoleSync[player].get() ? 2.1666666666666665D : 0.0D; + onHoleTimer[player] = this.state.onHoleSync[player].get() ? 2.1666666666666665D : 0.0D; teleported[player] = false; spinningStuckCounter[player] = 0; } boolean shouldSpinAroundHole = false; boolean onLiquid = false; - boolean var22 = false; - boolean var23 = super.gameContainer.synchronizedTrackTestMode.get(); - if (var23) { - var22 = super.gameContainer.gamePanel.maxFps(); - } - int var24 = -1; + int allPlayersStoppedCounter = -1; byte topleft = 0; byte left = 0; byte bottomleft = 0; @@ -233,83 +205,83 @@ public void run() { int y = 0; int x = 0; double speed = 0.0D; - this.bounciness = this.somethingSpeedThing = 1.0D; - int var38 = 0; + this.state.bounciness = this.state.somethingSpeedThing = 1.0D; + int accumulatedSleepTime = 0; do { long time = System.currentTimeMillis(); - for (int i = 0; i < this.playerCount; ++i) { - tempCoord3X[i] = this.playerX[i]; - tempCoord3Y[i] = this.playerY[i]; + for (int i = 0; i < this.state.playerCount; ++i) { + tempCoord3X[i] = this.state.playerX[i]; + tempCoord3Y[i] = this.state.playerY[i]; } - for (int var42 = 0; var42 < this.anInt2839; ++var42) { - var24 = 0; + for (int physicsIteration = 0; physicsIteration < this.state.maxPhysicsIterations; ++physicsIteration) { + allPlayersStoppedCounter = 0; - for (int i = 0; i < this.playerCount; ++i) { - if (this.aBooleanArray2830[i] && !this.onHoleSync[i].get()) { + for (int i = 0; i < this.state.playerCount; ++i) { + if (this.state.simulatePlayer[i] && !this.state.onHoleSync[i].get()) { for (int j = 0; j < 10; ++j) { // this moves player - this.playerX[i] += this.speedX[i] * 0.1D; - this.playerY[i] += this.speedY[i] * 0.1D; + this.state.playerX[i] += this.state.speedX[i] * 0.1D; + this.state.playerY[i] += this.state.speedY[i] * 0.1D; // check if player is going off the map - if (this.playerX[i] < 6.6D) { - this.playerX[i] = 6.6D; + if (this.state.playerX[i] < 6.6D) { + this.state.playerX[i] = 6.6D; } - if (this.playerX[i] >= 727.9D) { - this.playerX[i] = 727.9D; + if (this.state.playerX[i] >= 727.9D) { + this.state.playerX[i] = 727.9D; } - if (this.playerY[i] < 6.6D) { - this.playerY[i] = 6.6D; + if (this.state.playerY[i] < 6.6D) { + this.state.playerY[i] = 6.6D; } - if (this.playerY[i] >= 367.9D) { - this.playerY[i] = 367.9D; + if (this.state.playerY[i] >= 367.9D) { + this.state.playerY[i] = 367.9D; } // checks player vs player collision int anotherPlayer; - if (this.collisionMode == 1 && !onHole[i] && !onLiquidOrSwamp[i]) { - for (anotherPlayer = 0; anotherPlayer < this.playerCount; ++anotherPlayer) { + if (this.state.collisionMode == 1 && !onHole[i] && !onLiquidOrSwamp[i]) { + for (anotherPlayer = 0; anotherPlayer < this.state.playerCount; ++anotherPlayer) { if (i != anotherPlayer - && this.aBooleanArray2830[anotherPlayer] - && !this.onHoleSync[anotherPlayer].get() + && this.state.simulatePlayer[anotherPlayer] + && !this.state.onHoleSync[anotherPlayer].get() && !onHole[anotherPlayer] && !onLiquidOrSwamp[anotherPlayer] && this.handlePlayerCollisions(i, anotherPlayer)) { // collision is calculated in another function this just // makes it less effective - this.speedX[i] *= 0.75D; - this.speedY[i] *= 0.75D; - this.speedX[anotherPlayer] *= 0.75D; - this.speedY[anotherPlayer] *= 0.75D; - var24 = 0; // players moved so we reset this to make sure + this.state.speedX[i] *= 0.75D; + this.state.speedY[i] *= 0.75D; + this.state.speedX[anotherPlayer] *= 0.75D; + this.state.speedY[anotherPlayer] *= 0.75D; + allPlayersStoppedCounter = 0; // players moved so we reset this to make sure // they move } } } - x = (int) (this.playerX[i] + 0.5D); - y = (int) (this.playerY[i] + 0.5D); - center = super.collisionMap[x][y]; - top = super.collisionMap[x][y - 6]; - topright = super.collisionMap[x + diagOffset][y - diagOffset]; - right = super.collisionMap[x + 6][y]; - bottomright = super.collisionMap[x + diagOffset][y + diagOffset]; - bottom = super.collisionMap[x][y + 6]; - bottomleft = super.collisionMap[x - diagOffset][y + diagOffset]; - left = super.collisionMap[x - 6][y]; - topleft = super.collisionMap[x - diagOffset][y - diagOffset]; + x = (int) (this.state.playerX[i] + 0.5D); + y = (int) (this.state.playerY[i] + 0.5D); + center = this.map.getColMap(x, y); + top = this.map.getColMap(x, y - 6); + topright = this.map.getColMap(x + diagOffset, y - diagOffset); + right = this.map.getColMap(x + 6, y); + bottomright = this.map.getColMap(x + diagOffset, y + diagOffset); + bottom = this.map.getColMap(x, y + 6); + bottomleft = this.map.getColMap(x - diagOffset, y + diagOffset); + left = this.map.getColMap(x - 6, y); + topleft = this.map.getColMap(x - diagOffset, y - diagOffset); if (center != 12 && center != 13) { onLiquid = center == 14 || center == 15; } else { - this.speedX[i] *= 0.97D; - this.speedY[i] *= 0.97D; + this.state.speedX[i] *= 0.97D; + this.state.speedY[i] *= 0.97D; onLiquid = true; } @@ -362,7 +334,7 @@ public void run() { boolean isDownhill = this.handleDownhill(i, center); boolean isAffectedByMagnet = false; - if (this.magnetMap != null && !onLiquid && !onHole[i] && !onLiquidOrSwamp[i]) { + if (this.state.magnetMap != null && !onLiquid && !onHole[i] && !onLiquidOrSwamp[i]) { isAffectedByMagnet = this.handleMagnetForce(i, x, y); } @@ -370,69 +342,69 @@ public void run() { double holeSpeed; // 25 hole if (center == 25 - || super.collisionMap[x][y - 1] == 25 - || super.collisionMap[x + 1][y] == 25 - || super.collisionMap[x][y + 1] == 25 - || super.collisionMap[x - 1][y] == 25) { + || this.map.getColMap(x, y - 1) == 25 + || this.map.getColMap(x + 1, y) == 25 + || this.map.getColMap(x, y + 1) == 25 + || this.map.getColMap(x - 1, y) == 25) { holeSpeed = center == 25 ? 1.0D : 0.5D; shouldSpinAroundHole = true; int holeCounter = 0; if (top == 25) { ++holeCounter; } else { - this.speedY[i] += holeSpeed * 0.03D; + this.state.speedY[i] += holeSpeed * 0.03D; } if (topright == 25) { ++holeCounter; } else { - this.speedY[i] += holeSpeed * 0.03D * magicOffset; - this.speedX[i] -= holeSpeed * 0.03D * magicOffset; + this.state.speedY[i] += holeSpeed * 0.03D * magicOffset; + this.state.speedX[i] -= holeSpeed * 0.03D * magicOffset; } if (right == 25) { ++holeCounter; } else { - this.speedX[i] -= holeSpeed * 0.03D; + this.state.speedX[i] -= holeSpeed * 0.03D; } if (bottomright == 25) { ++holeCounter; } else { - this.speedY[i] -= holeSpeed * 0.03D * magicOffset; - this.speedX[i] -= holeSpeed * 0.03D * magicOffset; + this.state.speedY[i] -= holeSpeed * 0.03D * magicOffset; + this.state.speedX[i] -= holeSpeed * 0.03D * magicOffset; } if (bottom == 25) { ++holeCounter; } else { - this.speedY[i] -= holeSpeed * 0.03D; + this.state.speedY[i] -= holeSpeed * 0.03D; } if (bottomleft == 25) { ++holeCounter; } else { - this.speedY[i] -= holeSpeed * 0.03D * magicOffset; - this.speedX[i] += holeSpeed * 0.03D * magicOffset; + this.state.speedY[i] -= holeSpeed * 0.03D * magicOffset; + this.state.speedX[i] += holeSpeed * 0.03D * magicOffset; } if (left == 25) { ++holeCounter; } else { - this.speedX[i] += holeSpeed * 0.03D; + this.state.speedX[i] += holeSpeed * 0.03D; } if (topleft == 25) { ++holeCounter; } else { - this.speedY[i] += holeSpeed * 0.03D * magicOffset; - this.speedX[i] += holeSpeed * 0.03D * magicOffset; + this.state.speedY[i] += holeSpeed * 0.03D * magicOffset; + this.state.speedX[i] += holeSpeed * 0.03D * magicOffset; } if (holeCounter >= 7) { shouldSpinAroundHole = false; onHole[i] = true; - this.speedX[i] = this.speedY[i] = 0.0D; + this.state.speedX[i] = this.state.speedY[i] = 0.0D; } } @@ -451,26 +423,27 @@ public void run() { && !onHole[i] && !onLiquidOrSwamp[i] && !onLiquid) { - tempCoord2X[i] = this.playerX[i]; - tempCoord2Y[i] = this.playerY[i]; + tempCoord2X[i] = this.state.playerX[i]; + tempCoord2Y[i] = this.state.playerY[i]; } - speed = Math.sqrt(this.speedX[i] * this.speedX[i] + this.speedY[i] * this.speedY[i]); + speed = Math.sqrt(this.state.speedX[i] * this.state.speedX[i] + + this.state.speedY[i] * this.state.speedY[i]); if (speed > 0.0D) { - double var52 = this.calculateFriction(center, speed); - this.speedX[i] *= var52; - this.speedY[i] *= var52; - speed *= var52; + double frictionFactor = Tile.calculateFriction(center, speed); + this.state.speedX[i] *= frictionFactor; + this.state.speedY[i] *= frictionFactor; + speed *= frictionFactor; if (speed > 7.0D) { holeSpeed = 7.0D / speed; - this.speedX[i] *= holeSpeed; - this.speedY[i] *= holeSpeed; + this.state.speedX[i] *= holeSpeed; + this.state.speedY[i] *= holeSpeed; speed *= holeSpeed; } } if (loopStuckCounter > 4000) { - this.bounciness = 0.0D; + this.state.bounciness = 0.0D; if (loopStuckCounter > 7000) { isAffectedByMagnet = false; isDownhill = false; @@ -502,29 +475,32 @@ public void run() { && !shouldSpinAroundHole && !onHole[i] && !onLiquidOrSwamp[i]) { - this.speedX[i] = this.speedY[i] = 0.0D; + this.state.speedX[i] = this.state.speedY[i] = 0.0D; if (center != 12 && center != 14 && center != 13 && center != 15) { - ++var24; + ++allPlayersStoppedCounter; } else { onLiquidOrSwamp[i] = true; } } if (onHole[i] || onLiquidOrSwamp[i]) { - var10[i] += 0.1D; - if (onHole[i] && var10[i] > 2.1666666666666665D || onLiquidOrSwamp[i] && var10[i] > 6.0D) { + onHoleTimer[i] += 0.1D; + if (onHole[i] && onHoleTimer[i] > 2.1666666666666665D + || onLiquidOrSwamp[i] && onHoleTimer[i] > 6.0D) { // 25 hole if (center == 25) { - this.onHoleSync[i].set(true); - if (this.isLocalPlayer && this.playerCount > 1) { + this.state.onHoleSync[i].set(true); + if (this.state.isLocalPlayer && this.state.playerCount > 1) { super.gameContainer.gamePanel.hideSkipButton(); } } else { // water 12 // water swamp 14 if (center == 12 || center == 14) { - this.playerX[i] = this.onShoreSetting == 0 ? tempCoordX[i] : tempCoord2X[i]; - this.playerY[i] = this.onShoreSetting == 0 ? tempCoordY[i] : tempCoord2Y[i]; + this.state.playerX[i] = + this.state.onShoreSetting == 0 ? tempCoordX[i] : tempCoord2X[i]; + this.state.playerY[i] = + this.state.onShoreSetting == 0 ? tempCoordY[i] : tempCoord2Y[i]; } // 13 acid @@ -533,99 +509,97 @@ public void run() { this.resetPosition(i, false); } - var10[i] = 0.0D; + onHoleTimer[i] = 0.0D; } onHole[i] = onLiquidOrSwamp[i] = false; - ++var24; + ++allPlayersStoppedCounter; } } } else { - ++var24; + ++allPlayersStoppedCounter; } } ++loopStuckCounter; - if (var24 >= this.playerCount) { - var42 = this.anInt2839; + if (allPlayersStoppedCounter >= this.state.playerCount) { + physicsIteration = this.state.maxPhysicsIterations; } } - for (int i = 0; i < this.playerCount; ++i) { - if (this.aBooleanArray2830[i]) { + for (int i = 0; i < this.state.playerCount; ++i) { + if (this.state.simulatePlayer[i]) { int x1 = (int) (tempCoord3X[i] - 6.5D + 0.5D); int y1 = (int) (tempCoord3Y[i] - 6.5D + 0.5D); int x2 = x1 + 13; int y2 = y1 + 13; - ballGraphic.drawImage(var2, x1, y1, x2, y2, x1, y1, x2, y2, this); + ballGraphic.drawImage(gameImage, x1, y1, x2, y2, x1, y1, x2, y2, this); - for (int j = 0; j < this.playerCount; ++j) { - if (this.aBooleanArray2830[j] && j != this.currentPlayerID) { - this.drawPlayer(ballGraphic, j, var10[j]); + for (int j = 0; j < this.state.playerCount; ++j) { + if (this.state.simulatePlayer[j] && j != this.state.currentPlayerId) { + this.drawPlayer(ballGraphic, j, onHoleTimer[j]); } } - this.drawPlayer(ballGraphic, this.currentPlayerID, var10[this.currentPlayerID]); - if (this.playerX[i] < tempCoord3X[i]) { - x1 = (int) (this.playerX[i] - 6.5D + 0.5D); + this.drawPlayer(ballGraphic, this.state.currentPlayerId, onHoleTimer[this.state.currentPlayerId]); + if (this.state.playerX[i] < tempCoord3X[i]) { + x1 = (int) (this.state.playerX[i] - 6.5D + 0.5D); } - if (this.playerX[i] > tempCoord3X[i]) { - x2 = (int) (this.playerX[i] - 6.5D + 0.5D) + 13; + if (this.state.playerX[i] > tempCoord3X[i]) { + x2 = (int) (this.state.playerX[i] - 6.5D + 0.5D) + 13; } - if (this.playerY[i] < tempCoord3Y[i]) { - y1 = (int) (this.playerY[i] - 6.5D + 0.5D); + if (this.state.playerY[i] < tempCoord3Y[i]) { + y1 = (int) (this.state.playerY[i] - 6.5D + 0.5D); } - if (this.playerY[i] > tempCoord3Y[i]) { - y2 = (int) (this.playerY[i] - 6.5D + 0.5D) + 13; + if (this.state.playerY[i] > tempCoord3Y[i]) { + y2 = (int) (this.state.playerY[i] - 6.5D + 0.5D) + 13; } canvas.drawImage(ballImage, x1, y1, x2, y2, x1, y1, x2, y2, this); } } - time = System.currentTimeMillis() - time; // time to render - long var58 = (long) (6 * this.anInt2839) - time; // fps cap ? - if (var23) { - if (var22) { - var58 = 0L; - } else if (loopStuckCounter % 100 == 0) { - var22 = super.gameContainer.gamePanel.maxFps(); - } + time = System.currentTimeMillis() - time; // time to run above for loop + long sleepTime = (long) (6 * this.state.maxPhysicsIterations) - time; + // If we want to force fps, set sleepTime to zero so that maxPhysicsIterations + // are not adjusted. gamePanel.maxFps gets status of checkbox, so + // it can change in game. + if (super.gameContainer.synchronizedTrackTestMode.get() && super.gameContainer.gamePanel.maxFps()) { + sleepTime = 0L; } - Tools.sleep(var58); - var38 = (int) ((long) var38 + var58); - } while (var24 < this.playerCount && !this.aBoolean2843); + Tools.sleep(sleepTime); + accumulatedSleepTime += sleepTime; + } while (allPlayersStoppedCounter < this.state.playerCount && !this.state.strokeInterrupted); - if (this.aBoolean2843) { - this.aThread2842 = null; - } else { - this.method164(var38); - super.gameContainer.gamePanel.sendEndStroke(this.currentPlayerID, this.onHoleSync, this.anInt2816); - if (this.anInt2816 >= 0) { - this.onHoleSync[this.anInt2816].set(true); + if (!this.state.strokeInterrupted) { + this.adjustPhysicsIterations(accumulatedSleepTime); + super.gameContainer.gamePanel.sendEndStroke( + this.state.currentPlayerId, this.state.onHoleSync, this.state.isValidPlayerId); + if (this.state.isValidPlayerId >= 0) { + this.state.onHoleSync[this.state.isValidPlayerId].set(true); } - this.aThread2842 = null; this.repaint(); } + this.shotThread = null; } @Override - public void mouseMoved(MouseEvent var1) { - this.mouseX = var1.getX(); - this.mouseY = var1.getY(); + public void mouseMoved(MouseEvent event) { + this.mouseX = event.getX(); + this.mouseY = event.getY(); if (isCheating) { int x = this.mouseX; int y = this.mouseY; - double subtractionX = this.playerX[this.currentPlayerID] - (double) x; - double subtractionY = this.playerY[this.currentPlayerID] - (double) y; + double subtractionX = this.state.playerX[this.state.currentPlayerId] - (double) x; + double subtractionY = this.state.playerY[this.state.currentPlayerId] - (double) y; if (Math.sqrt(subtractionX * subtractionX + subtractionY * subtractionY) >= 6.5D) { - this.doHackedStroke(this.currentPlayerID, true, x, y, this.shootingMode); + // this.doHackedStroke(this.state.currentPlayerId, true, x, y, this.shootingMode); this.repaint(); } } @@ -649,14 +623,14 @@ public void mouseExited(MouseEvent event) { @Override public synchronized void mousePressed(MouseEvent event) { - if (this.gameState == 1) { + if (this.state.gameState == 1) { if (event.getButton() == MouseEvent.BUTTON1) { int x = event.getX(); int y = event.getY(); this.mouseX = x; this.mouseY = y; - double subtractionX = this.playerX[this.currentPlayerID] - (double) x; - double subtractionY = this.playerY[this.currentPlayerID] - (double) y; + double subtractionX = this.state.playerX[this.state.currentPlayerId] - (double) x; + double subtractionY = this.state.playerY[this.state.currentPlayerId] - (double) y; // checks if mouse is on own ball if (Math.sqrt(subtractionX * subtractionX + subtractionY * subtractionY) >= 6.5D) { this.removeMouseMotionListener(this); @@ -664,9 +638,10 @@ public synchronized void mousePressed(MouseEvent event) { this.removeKeyListener(this); this.setCursor(cursorDefault); if (super.gameContainer.gamePanel.tryStroke(false)) { - super.gameContainer.gamePanel.setBeginStroke(this.currentPlayerID, x, y, this.shootingMode); - // this.doHackedStroke(this.currentPlayerID, true, x, y, this.keyCountMod4); - this.doStroke(this.currentPlayerID, true, x, y, this.shootingMode); + super.gameContainer.gamePanel.setBeginStroke( + this.state.currentPlayerId, x, y, this.shootingMode); + // this.doHackedStroke(this.state.currentPlayerId, true, x, y, this.keyCountMod4); + this.doStroke(this.state.currentPlayerId, true, x, y, this.shootingMode); } } } else { @@ -678,7 +653,7 @@ public synchronized void mousePressed(MouseEvent event) { @Override public void mouseReleased(MouseEvent event) { - if (this.gameState == 1) { + if (this.state.gameState == 1) { event.consume(); } } @@ -700,81 +675,73 @@ public synchronized void keyPressed(KeyEvent event) { public void keyReleased(KeyEvent event) {} @Override - public void keyTyped(KeyEvent var1) {} + public void keyTyped(KeyEvent event) {} protected void init(int playerCount, int waterMode, int collisionMode) { - this.playerCount = playerCount; - this.onShoreSetting = waterMode; - this.collisionMode = collisionMode; - this.playerX = new double[playerCount]; - this.playerY = new double[playerCount]; - this.speedX = new double[playerCount]; - this.speedY = new double[playerCount]; - this.onHoleSync = new SynchronizedBool[playerCount]; + this.state.playerCount = playerCount; + this.state.onShoreSetting = waterMode; + this.state.collisionMode = collisionMode; + this.state.playerX = new double[playerCount]; + this.state.playerY = new double[playerCount]; + this.state.speedX = new double[playerCount]; + this.state.speedY = new double[playerCount]; + this.state.onHoleSync = new SynchronizedBool[playerCount]; for (int i = 0; i < playerCount; ++i) { - this.onHoleSync[i] = new SynchronizedBool(); + this.state.onHoleSync[i] = new SynchronizedBool(); } - this.aBooleanArray2830 = new boolean[playerCount]; - this.aBooleanArray2834 = new boolean[playerCount]; + this.state.simulatePlayer = new boolean[playerCount]; + this.state.playerActive = new boolean[playerCount]; this.playerNamesDisplayMode = playerCount <= 2 ? 0 : 3; } @Override - protected void createMap(int var1) { - super.createMap(var1); - this.currentPlayerID = this.mouseX = this.mouseY = -1; - this.gameState = 0; + protected void initializeGameArea() { + super.initializeGameArea(); + this.state.currentPlayerId = this.mouseX = this.mouseY = -1; + this.state.gameState = 0; this.repaint(); } protected boolean init(String commandLines, String playerStatuses, int gameId) { - boolean parseSuccessful = super.parseMapCommands(commandLines); - - this.aString2835 = null; - StringTokenizer commandTokens = new StringTokenizer(commandLines, "\n"); - - while (commandTokens.hasMoreTokens()) { - String currentCommand = commandTokens.nextToken(); - char commandType = currentCommand.charAt(0); - - if (commandType == 'B' || commandType == 'L') { - - int recordHolderName = currentCommand.indexOf(','); - int recordTimestamp = currentCommand.indexOf(',', recordHolderName + 1); - int var10 = currentCommand.indexOf(',', recordTimestamp + 1); - currentCommand = currentCommand.substring(var10 + 1); - int var11 = currentCommand.indexOf('='); - if (var11 > -1) { - gameId = Integer.parseInt(currentCommand.substring(0, var11)); - this.aString2835 = currentCommand.substring(var11 + 1); - } - } + boolean parseSuccessful = false; + VersionedTrackFileParser parser = new VersionedTrackFileParser(1); + try { + this.track = parser.parseTrackFromString(commandLines); + this.map = new Map(49, 25, track.getMap()); + this.trackStats = parser.parseStatsFromString(commandLines); + } catch (Exception e) { + System.out.println("Error while parsing track & map: " + e.getMessage()); + return false; } + this.map.checkSolids(this.gameContainer.spriteManager); + super.drawMap(); + + this.encodedCoordinates = null; List startPositions = new ArrayList<>(); - this.resetPositionX = new double[4]; - this.resetPositionY = new double[4]; - this.teleportExists = new ArrayList[4]; - this.teleportStarts = new ArrayList[4]; + this.state.resetPositionX = new double[4]; + this.state.resetPositionY = new double[4]; + this.state.teleportExits = new ArrayList[4]; + this.state.teleportStarts = new ArrayList[4]; List magnets = new ArrayList<>(); for (int i = 0; i < 4; ++i) { - this.resetPositionX[i] = this.resetPositionY[i] = -1.0D; - this.teleportExists[i] = new ArrayList<>(); - this.teleportStarts[i] = new ArrayList<>(); + this.state.resetPositionX[i] = this.state.resetPositionY[i] = -1.0D; + this.state.teleportExits[i] = new ArrayList<>(); + this.state.teleportStarts[i] = new ArrayList<>(); } // Iterates over the 49*25 map for (int y = 0; y < 25; ++y) { for (int x = 0; x < 49; ++x) { - if (super.trackTiles[x][y] / 16777216 == 2) { - int tile = super.trackTiles[x][y] / 65536 % 256 + 24; + if (this.map.getTile(x, y).getSpecial() == 2) { + int shape = this.map.getTile(x, y).getShape(); double screenX = (double) (x * 15) + 7.5D; double screenY = (double) (y * 15) + 7.5D; // 24 Start Position Common - if (tile == 24) { + if (shape == 24) { double[] startPosition = new double[] {screenX, screenY}; startPositions.add(startPosition); } @@ -782,9 +749,9 @@ protected boolean init(String commandLines, String playerStatuses, int gameId) { // 49 Start Position Red // 50 Start Positiono Yellow // 51 Start Position Green - if (tile >= 48 && tile <= 51) { - this.resetPositionX[tile - 48] = screenX; - this.resetPositionY[tile - 48] = screenY; + if (shape >= 48 && shape <= 51) { + this.state.resetPositionX[shape - 48] = screenX; + this.state.resetPositionY[shape - 48] = screenY; } int teleportIndex; @@ -792,26 +759,26 @@ protected boolean init(String commandLines, String playerStatuses, int gameId) { // 35 Teleport Exit Red // 37 Teleport Exit Yellow // 39 Teleport Exit Green - if (tile == 33 || tile == 35 || tile == 37 || tile == 39) { - teleportIndex = (tile - 33) / 2; + if (shape == 33 || shape == 35 || shape == 37 || shape == 39) { + teleportIndex = (shape - 33) / 2; double[] teleporter = new double[] {screenX, screenY}; - this.teleportExists[teleportIndex].add(teleporter); + this.state.teleportExits[teleportIndex].add(teleporter); } // 33 Teleport Start Blue // 35 Teleport Start Red // 37 Teleport Start Yellow // 39 Teleport Start Green - if (tile == 32 || tile == 34 || tile == 36 || tile == 38) { - teleportIndex = (tile - 32) / 2; + if (shape == 32 || shape == 34 || shape == 36 || shape == 38) { + teleportIndex = (shape - 32) / 2; double[] teleporter = new double[] {screenX, screenY}; - this.teleportStarts[teleportIndex].add(teleporter); + this.state.teleportStarts[teleportIndex].add(teleporter); } // 44 magnet attract // 45 magnet repel - if (tile == 44 || tile == 45) { - int[] magnet = new int[] {(int) (screenX + 0.5D), (int) (screenY + 0.5D), tile}; + if (shape == 44 || shape == 45) { + int[] magnet = new int[] {(int) (screenX + 0.5D), (int) (screenY + 0.5D), shape}; magnets.add(magnet); } } @@ -820,18 +787,18 @@ protected boolean init(String commandLines, String playerStatuses, int gameId) { int startPositionsCount = startPositions.size(); if (startPositionsCount == 0) { - this.startPositionX = this.startPositionY = -1.0D; + this.state.startPositionX = this.state.startPositionY = -1.0D; } else { double[] startPosition = startPositions.get(gameId % startPositionsCount); - this.startPositionX = startPosition[0]; - this.startPositionY = startPosition[1]; + this.state.startPositionX = startPosition[0]; + this.state.startPositionY = startPosition[1]; } int magnetVecLen = magnets.size(); if (magnetVecLen == 0) { - this.magnetMap = null; + this.state.magnetMap = null; } else { - this.magnetMap = new short[147][75][2]; + this.state.magnetMap = new short[147][75][2]; // magnet map is 5times smaller than real one for (int magnetLoopY = 2; magnetLoopY < 375; magnetLoopY += 5) { @@ -846,10 +813,10 @@ protected boolean init(String commandLines, String playerStatuses, int gameId) { double forcetemp2Y = magnet[1] - magnetLoopY; double force = Math.sqrt(forceTemp2X * forceTemp2X + forcetemp2Y * forcetemp2Y); if (force <= 127.0D) { - double var35 = Math.abs(forceTemp2X) / force; + double modifier = Math.abs(forceTemp2X) / force; force = 127.0D - force; - forceTemp2X = (forceTemp2X < 0.0D ? -1.0D : 1.0D) * force * var35; - forcetemp2Y = (forcetemp2Y < 0.0D ? -1.0D : 1.0D) * force * (1.0D - var35); + forceTemp2X = (forceTemp2X < 0.0D ? -1.0D : 1.0D) * force * modifier; + forcetemp2Y = (forcetemp2Y < 0.0D ? -1.0D : 1.0D) * force * (1.0D - modifier); // 45 Magnet Repel if (magnet[2] == 45) { forceTemp2X = -forceTemp2X; @@ -880,53 +847,53 @@ protected boolean init(String commandLines, String playerStatuses, int gameId) { forceY = 0x7ff; } - this.magnetMap[magnetLoopX / 5][magnetLoopY / 5][0] = (short) forceX; - this.magnetMap[magnetLoopX / 5][magnetLoopY / 5][1] = (short) forceY; + this.state.magnetMap[magnetLoopX / 5][magnetLoopY / 5][0] = (short) forceX; + this.state.magnetMap[magnetLoopX / 5][magnetLoopY / 5][1] = (short) forceY; } } } - for (int i = 0; i < this.playerCount; ++i) { - this.aBooleanArray2834[i] = true; + for (int i = 0; i < this.state.playerCount; ++i) { + this.state.playerActive[i] = true; this.resetPosition(i, true); - this.onHoleSync[i].set(false); - this.aBooleanArray2830[i] = playerStatuses.charAt(i) == 't'; + this.state.onHoleSync[i].set(false); + this.state.simulatePlayer[i] = playerStatuses.charAt(i) == 't'; } - this.rngSeed = new Seed(gameId); + this.state.seed = new Seed(gameId); this.repaint(); return parseSuccessful; } - protected boolean method134() { - return this.aString2835 != null; + protected boolean hasCoordinates() { + return this.encodedCoordinates != null; } protected void startTurn(int playerId, boolean canLocalPlayerPlay, boolean requestFocus) { - this.currentPlayerID = playerId; - this.aBooleanArray2834[playerId] = true; + this.state.currentPlayerId = playerId; + this.state.playerActive[playerId] = true; this.mouseX = this.mouseY = -1; this.shootingMode = 0; if (canLocalPlayerPlay) { this.setStrokeListeners(requestFocus); - this.gameState = 1; + this.state.gameState = 1; } else { - this.gameState = 0; + this.state.gameState = 0; } this.repaint(); } protected void decodeCoords(int playerId, boolean isLocalPlayer, String encoded) { - int var4 = Integer.parseInt(encoded, 36); - int x = var4 / 1500; - int y = var4 % 1500 / 4; - int shootingMode = var4 % 4; + int shotData = Integer.parseInt(encoded, 36); + int x = shotData / 1500; + int y = shotData % 1500 / 4; + int shootingMode = shotData % 4; this.doStroke(playerId, isLocalPlayer, x, y, shootingMode); } protected boolean method137() { - return this.gameState == 1; + return this.state.gameState == 1; } protected void endGame() { @@ -934,7 +901,7 @@ protected void endGame() { this.removeMouseListener(this); this.removeKeyListener(this); this.setCursor(cursorDefault); - this.gameState = 0; + this.state.gameState = 0; this.repaint(); } @@ -944,7 +911,7 @@ protected void setPlayerNamesDisplayMode(int mode) { } protected boolean getSynchronizedBool(int index) { - return this.onHoleSync[index].get(); + return this.state.onHoleSync[index].get(); } protected void restartGame() { @@ -952,27 +919,27 @@ protected void restartGame() { this.removeMouseListener(this); this.removeKeyListener(this); this.setCursor(cursorDefault); - if (this.aThread2842 != null) { - this.aBoolean2843 = true; + if (this.shotThread != null) { + this.state.strokeInterrupted = true; - while (this.aThread2842 != null) { + while (this.shotThread != null) { Tools.sleep(100L); } } - this.gameState = 0; + this.state.gameState = 0; this.repaint(); } - protected String method142() { - if (this.gameState != 1) { + protected String encodeCoordinates() { + if (this.state.gameState != 1) { return null; } else { try { - String var1 = this.aString2835.substring(0, 4); - this.aString2835 = this.aString2835.substring(4); - return var1; - } catch (StringIndexOutOfBoundsException var2) { + String coords = this.encodedCoordinates.substring(0, 4); + this.encodedCoordinates = this.encodedCoordinates.substring(4); + return coords; + } catch (StringIndexOutOfBoundsException e) { return null; } } @@ -983,56 +950,57 @@ protected void doZeroLengthStroke() { this.removeMouseListener(this); this.removeKeyListener(this); this.setCursor(cursorDefault); - int x = (int) this.playerX[this.currentPlayerID]; - int y = (int) this.playerY[this.currentPlayerID]; - super.gameContainer.gamePanel.setBeginStroke(this.currentPlayerID, x, y, 0); - this.doStroke(this.currentPlayerID, true, x, y, 0); + int x = (int) this.state.playerX[this.state.currentPlayerId]; + int y = (int) this.state.playerY[this.state.currentPlayerId]; + super.gameContainer.gamePanel.setBeginStroke(this.state.currentPlayerId, x, y, 0); + this.doStroke(this.state.currentPlayerId, true, x, y, 0); } private void doStroke(int playerId, boolean isLocalPlayer, int mouseX, int mouseY, int shootingMode) { - this.anInt2816 = super.gameContainer.gamePanel.isValidPlayerID(playerId) ? playerId : -1; + this.state.isValidPlayerId = super.gameContainer.gamePanel.isValidPlayerID(playerId) ? playerId : -1; double[] power = this.getStrokePower(playerId, mouseX, mouseY); - this.speedX[playerId] = power[0]; - this.speedY[playerId] = power[1]; + this.state.speedX[playerId] = power[0]; + this.state.speedY[playerId] = power[1]; if (shootingMode == 1) { - this.speedX[playerId] = -this.speedX[playerId]; - this.speedY[playerId] = -this.speedY[playerId]; + this.state.speedX[playerId] = -this.state.speedX[playerId]; + this.state.speedY[playerId] = -this.state.speedY[playerId]; } double temp; if (shootingMode == 2) { - temp = this.speedX[playerId]; - this.speedX[playerId] = this.speedY[playerId]; - this.speedY[playerId] = -temp; + temp = this.state.speedX[playerId]; + this.state.speedX[playerId] = this.state.speedY[playerId]; + this.state.speedY[playerId] = -temp; } if (shootingMode == 3) { - temp = this.speedX[playerId]; - this.speedX[playerId] = -this.speedY[playerId]; - this.speedY[playerId] = temp; + temp = this.state.speedX[playerId]; + this.state.speedX[playerId] = -this.state.speedY[playerId]; + this.state.speedY[playerId] = temp; } - temp = Math.sqrt(this.speedX[playerId] * this.speedX[playerId] + this.speedY[playerId] * this.speedY[playerId]); + temp = Math.sqrt(this.state.speedX[playerId] * this.state.speedX[playerId] + + this.state.speedY[playerId] * this.state.speedY[playerId]); double speed = temp / 6.5D; speed *= speed; if (!this.norandom) { - this.speedX[playerId] += speed * ((double) (this.rngSeed.next() % 50001) / 100000.0D - 0.25D); - this.speedY[playerId] += speed * ((double) (this.rngSeed.next() % 50001) / 100000.0D - 0.25D); + this.state.speedX[playerId] += speed * ((double) (this.state.seed.next() % 50001) / 100000.0D - 0.25D); + this.state.speedY[playerId] += speed * ((double) (this.state.seed.next() % 50001) / 100000.0D - 0.25D); } - this.isLocalPlayer = isLocalPlayer; - this.gameState = 2; - this.aBoolean2843 = false; + this.state.isLocalPlayer = isLocalPlayer; + this.state.gameState = 2; + this.state.strokeInterrupted = false; - this.aThread2842 = new Thread(this); - this.aThread2842.start(); + this.shotThread = new Thread(this); + this.shotThread.start(); } private void doHackedStroke(int playerId, boolean isLocalPlayer, int mouseX, int mouseY, int mod) { - double[] temp_aDoubleArray2828 = Arrays.copyOf(speedX, speedX.length); - double[] temp_aDoubleArray2829 = Arrays.copyOf(speedY, speedY.length); - boolean temp_aBoolean2832 = this.isLocalPlayer; - boolean temp_aBoolean2843 = this.aBoolean2843; - Seed temp_aSeed_2836 = rngSeed.clone(); + double[] temp_aDoubleArray2828 = Arrays.copyOf(this.state.speedX, this.state.speedX.length); + double[] temp_aDoubleArray2829 = Arrays.copyOf(this.state.speedY, this.state.speedY.length); + boolean temp_aBoolean2832 = this.state.isLocalPlayer; + boolean temp_aBoolean2843 = this.state.strokeInterrupted; + Seed temp_aSeed_2836 = this.state.seed.clone(); // int temp_anInt2816 = super.gameContainer.gamePanel.isValidPlayerID(playerId) // ? playerId : // -1; @@ -1066,37 +1034,37 @@ private void doHackedStroke(int playerId, boolean isLocalPlayer, int mouseX, int temp_aDoubleArray2828[playerId] += var9 * ((double) (temp_aSeed_2836.next() % 50001) / 100000.0D - 0.25D); temp_aDoubleArray2829[playerId] += var9 * ((double) (temp_aSeed_2836.next() % 50001) / 100000.0D - 0.25D); temp_aBoolean2832 = isLocalPlayer; - // this.gameState = 2; + // this.state.gameState = 2; temp_aBoolean2843 = false; HackedShot hs = new HackedShot( - playerCount, - onShoreSetting, - collisionMode, - currentPlayerID, + this.state.playerCount, + this.state.onShoreSetting, + this.state.collisionMode, + state.currentPlayerId, temp_anInt2816, - startPositionX, - startPositionY, - bounciness, - somethingSpeedThing, - resetPositionX, - resetPositionY, - teleportStarts, - teleportExists, - magnetMap, - playerX, - playerY, + this.state.startPositionX, + this.state.startPositionY, + this.state.bounciness, + this.state.somethingSpeedThing, + this.state.resetPositionX, + this.state.resetPositionY, + this.state.teleportStarts, + this.state.teleportExits, + this.state.magnetMap, + this.state.playerX, + this.state.playerY, temp_aDoubleArray2828, temp_aDoubleArray2829, - aBooleanArray2830, - onHoleSync, + this.state.simulatePlayer, + this.state.onHoleSync, temp_aBoolean2832, - aBooleanArray2834, + this.state.playerActive, temp_aSeed_2836, - anInt2839, + this.state.maxPhysicsIterations, temp_aBoolean2843, - super.collisionMap, - super.trackTiles); + this.map.getColMap(), + this.map.getTileCodeArray()); Thread hack = new Thread(hs); hack.start(); try { @@ -1110,60 +1078,61 @@ private void doHackedStroke(int playerId, boolean isLocalPlayer, int mouseX, int } private void resetPosition(int playerId, boolean gameStart) { - if (this.resetPositionX[playerId] >= 0.0D && this.resetPositionX[playerId] >= 0.0D) { - this.playerX[playerId] = this.resetPositionX[playerId]; - this.playerY[playerId] = this.resetPositionY[playerId]; - } else if (this.startPositionX >= 0.0D && this.startPositionY >= 0.0D) { - this.playerX[playerId] = this.startPositionX; - this.playerY[playerId] = this.startPositionY; + if (this.state.resetPositionX[playerId] >= 0.0D && this.state.resetPositionX[playerId] >= 0.0D) { + this.state.playerX[playerId] = this.state.resetPositionX[playerId]; + this.state.playerY[playerId] = this.state.resetPositionY[playerId]; + } else if (this.state.startPositionX >= 0.0D && this.state.startPositionY >= 0.0D) { + this.state.playerX[playerId] = this.state.startPositionX; + this.state.playerY[playerId] = this.state.startPositionY; if (gameStart) { - this.aBooleanArray2834[playerId] = false; + this.state.playerActive[playerId] = false; } } else { - this.playerX[playerId] = 367.5D; - this.playerY[playerId] = 187.5D; + this.state.playerX[playerId] = 367.5D; + this.state.playerY[playerId] = 187.5D; } } private double[] getStrokePower(int playerId, int mouseX, int mouseY) { - double subX = this.playerX[playerId] - (double) mouseX; - double subY = this.playerY[playerId] - (double) mouseY; - double sqrtXY = Math.sqrt(subX * subX + subY * subY); - double var10 = (sqrtXY - 5.0D) / 30.0D; - if (var10 < 0.075D) { - var10 = 0.075D; + double deltaX = this.state.playerX[playerId] - (double) mouseX; + double deltaY = this.state.playerY[playerId] - (double) mouseY; + double distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); + double magnitude = (distance - 5.0D) / 30.0D; + if (magnitude < 0.075D) { + magnitude = 0.075D; } - if (var10 > 6.5D) { - var10 = 6.5D; + if (magnitude > 6.5D) { + magnitude = 6.5D; } - double var12 = var10 / sqrtXY; + double scaleFactor = magnitude / distance; double[] power = new double[] { - ((double) mouseX - this.playerX[playerId]) * var12, ((double) mouseY - this.playerY[playerId]) * var12 + ((double) mouseX - this.state.playerX[playerId]) * scaleFactor, + ((double) mouseY - this.state.playerY[playerId]) * scaleFactor }; return power; } private boolean handlePlayerCollisions(int player1, int player2) { - double x = this.playerX[player2] - this.playerX[player1]; - double y = this.playerY[player2] - this.playerY[player1]; + double x = this.state.playerX[player2] - this.state.playerX[player1]; + double y = this.state.playerY[player2] - this.state.playerY[player1]; double distance = Math.sqrt(x * x + y * y); if (distance != 0.0D && distance <= 13.0D) { double forceX = x / distance; double forceY = y / distance; - double p1Speed = this.speedX[player1] * forceX + this.speedY[player1] * forceY; - double p2Speed = this.speedX[player2] * forceX + this.speedY[player2] * forceY; + double p1Speed = this.state.speedX[player1] * forceX + this.state.speedY[player1] * forceY; + double p2Speed = this.state.speedX[player2] * forceX + this.state.speedY[player2] * forceY; if (p1Speed - p2Speed <= 0.0D) { return false; } else { - double var17 = -this.speedX[player1] * forceY + this.speedY[player1] * forceX; - double var19 = -this.speedX[player2] * forceY + this.speedY[player2] * forceX; - this.speedX[player1] = p2Speed * forceX - var17 * forceY; - this.speedY[player1] = p2Speed * forceY + var17 * forceX; - this.speedX[player2] = p1Speed * forceX - var19 * forceY; - this.speedY[player2] = p1Speed * forceY + var19 * forceX; + double p1PerpSpeed = -this.state.speedX[player1] * forceY + this.state.speedY[player1] * forceX; + double p2PerpSpeed = -this.state.speedX[player2] * forceY + this.state.speedY[player2] * forceX; + this.state.speedX[player1] = p2Speed * forceX - p1PerpSpeed * forceY; + this.state.speedY[player1] = p2Speed * forceY + p1PerpSpeed * forceX; + this.state.speedX[player2] = p1Speed * forceX - p2PerpSpeed * forceY; + this.state.speedY[player2] = p1Speed * forceY + p2PerpSpeed * forceX; return true; } } else { @@ -1171,42 +1140,42 @@ private boolean handlePlayerCollisions(int player1, int player2) { } } - private boolean handleDownhill(int var1, int var2) { - if (var2 >= 4 && var2 <= 11) { - if (var2 == 4) { - this.speedY[var1] -= 0.025D; + private boolean handleDownhill(int playerId, int elementId) { + if (elementId >= 4 && elementId <= 11) { + if (elementId == 4) { + this.state.speedY[playerId] -= 0.025D; } - if (var2 == 5) { - this.speedY[var1] -= 0.025D * magicOffset; - this.speedX[var1] += 0.025D * magicOffset; + if (elementId == 5) { + this.state.speedY[playerId] -= 0.025D * magicOffset; + this.state.speedX[playerId] += 0.025D * magicOffset; } - if (var2 == 6) { - this.speedX[var1] += 0.025D; + if (elementId == 6) { + this.state.speedX[playerId] += 0.025D; } - if (var2 == 7) { - this.speedY[var1] += 0.025D * magicOffset; - this.speedX[var1] += 0.025D * magicOffset; + if (elementId == 7) { + this.state.speedY[playerId] += 0.025D * magicOffset; + this.state.speedX[playerId] += 0.025D * magicOffset; } - if (var2 == 8) { - this.speedY[var1] += 0.025D; + if (elementId == 8) { + this.state.speedY[playerId] += 0.025D; } - if (var2 == 9) { - this.speedY[var1] += 0.025D * magicOffset; - this.speedX[var1] -= 0.025D * magicOffset; + if (elementId == 9) { + this.state.speedY[playerId] += 0.025D * magicOffset; + this.state.speedX[playerId] -= 0.025D * magicOffset; } - if (var2 == 10) { - this.speedX[var1] -= 0.025D; + if (elementId == 10) { + this.state.speedX[playerId] -= 0.025D; } - if (var2 == 11) { - this.speedY[var1] -= 0.025D * magicOffset; - this.speedX[var1] -= 0.025D * magicOffset; + if (elementId == 11) { + this.state.speedY[playerId] -= 0.025D * magicOffset; + this.state.speedX[playerId] -= 0.025D * magicOffset; } return true; @@ -1218,52 +1187,21 @@ private boolean handleDownhill(int var1, int var2) { private boolean handleMagnetForce(int playerId, int mapX, int mapY) { int magnetX = mapX / 5; int magnetY = mapY / 5; - short forceX = this.magnetMap[magnetX][magnetY][0]; - short forceY = this.magnetMap[magnetX][magnetY][1]; + short forceX = this.state.magnetMap[magnetX][magnetY][0]; + short forceY = this.state.magnetMap[magnetX][magnetY][1]; if (forceX == 0 && forceY == 0) { return false; } else { - if (this.somethingSpeedThing > 0.0D) { - this.somethingSpeedThing -= 1.0E-4D; + if (this.state.somethingSpeedThing > 0.0D) { + this.state.somethingSpeedThing -= 1.0E-4D; } - this.speedX[playerId] += this.somethingSpeedThing * (double) forceX * 5.0E-4D; - this.speedY[playerId] += this.somethingSpeedThing * (double) forceY * 5.0E-4D; + this.state.speedX[playerId] += this.state.somethingSpeedThing * (double) forceX * 5.0E-4D; + this.state.speedY[playerId] += this.state.somethingSpeedThing * (double) forceY * 5.0E-4D; return true; } } - private double calculateFriction(int tile, double speed) { - double friction = this.getFriction(tile); - double var6 = 0.75D * speed / 6.5D; - double var8 = 1.0D - friction; - return friction + var8 * var6; - } - - private double getFriction(int var1) { - return var1 != 0 && (var1 < 4 || var1 > 11) && var1 != 19 && var1 != 47 - ? (var1 == 1 - ? 0.92D - : (var1 == 2 - ? 0.8D - : (var1 != 3 && var1 != 32 && var1 != 34 && var1 != 36 && var1 != 38 - ? (var1 != 12 && var1 != 13 - ? (var1 != 14 && var1 != 15 - ? (var1 >= 20 && var1 <= 23 - ? 0.995D - : (var1 == 25 - ? 0.96D - : (var1 != 28 && var1 != 30 - ? (var1 != 29 && var1 != 31 - ? (var1 == 44 ? 0.9D : 1.0D) - : 0.9D) - : 1.0D))) - : 0.95D) - : 0.0D) - : 0.9975D))) - : 0.9935D; - } - private void handleWallCollision( int playerId, int top, @@ -1285,7 +1223,7 @@ private void handleWallCollision( || topright == 46; boolean rightCollide = right >= 16 && right <= 23 && right != 19 || right == 27 || right >= 40 && right <= 43 || right == 46; - boolean var17 = bottomright >= 16 && bottomright <= 23 && bottomright != 19 + boolean bottomrightCollide = bottomright >= 16 && bottomright <= 23 && bottomright != 19 || bottomright == 27 || bottomright >= 40 && bottomright <= 43 || bottomright == 46; @@ -1331,8 +1269,8 @@ private void handleWallCollision( toprightCollide = false; } - if (var17 && bottomright == 21) { - var17 = false; + if (bottomrightCollide && bottomright == 21) { + bottomrightCollide = false; } if (topCollide && top == 21) { @@ -1347,8 +1285,8 @@ private void handleWallCollision( bottomCollide = false; } - if (var17 && bottomright == 22) { - var17 = false; + if (bottomrightCollide && bottomright == 22) { + bottomrightCollide = false; } if (bottomleftCollide && bottomleft == 22) { @@ -1394,7 +1332,7 @@ private void handleWallCollision( } if (rightCollide - && var17 + && bottomrightCollide && bottomCollide && (right < 20 || right > 23) && (bottomright < 20 || bottomright > 23) @@ -1427,86 +1365,86 @@ private void handleWallCollision( if (!topCollide && !rightCollide && !bottomCollide && !leftcollide) { double temp; if (toprightCollide - && (this.speedX[playerId] > 0.0D && this.speedY[playerId] < 0.0D - || this.speedX[playerId] < 0.0D - && this.speedY[playerId] < 0.0D - && -this.speedY[playerId] > -this.speedX[playerId] - || this.speedX[playerId] > 0.0D - && this.speedY[playerId] > 0.0D - && this.speedX[playerId] > this.speedY[playerId])) { + && (this.state.speedX[playerId] > 0.0D && this.state.speedY[playerId] < 0.0D + || this.state.speedX[playerId] < 0.0D + && this.state.speedY[playerId] < 0.0D + && -this.state.speedY[playerId] > -this.state.speedX[playerId] + || this.state.speedX[playerId] > 0.0D + && this.state.speedY[playerId] > 0.0D + && this.state.speedX[playerId] > this.state.speedY[playerId])) { speedEffect = this.getSpeedEffect(topright, playerId, x + diagOffset, y - diagOffset, ball, canvas, 1, -1); - temp = this.speedX[playerId]; - this.speedX[playerId] = this.speedY[playerId] * speedEffect; - this.speedY[playerId] = temp * speedEffect; + temp = this.state.speedX[playerId]; + this.state.speedX[playerId] = this.state.speedY[playerId] * speedEffect; + this.state.speedY[playerId] = temp * speedEffect; } - if (var17 - && (this.speedX[playerId] > 0.0D && this.speedY[playerId] > 0.0D - || this.speedX[playerId] > 0.0D - && this.speedY[playerId] < 0.0D - && this.speedX[playerId] > -this.speedY[playerId] - || this.speedX[playerId] < 0.0D - && this.speedY[playerId] > 0.0D - && this.speedY[playerId] > -this.speedX[playerId])) { + if (bottomrightCollide + && (this.state.speedX[playerId] > 0.0D && this.state.speedY[playerId] > 0.0D + || this.state.speedX[playerId] > 0.0D + && this.state.speedY[playerId] < 0.0D + && this.state.speedX[playerId] > -this.state.speedY[playerId] + || this.state.speedX[playerId] < 0.0D + && this.state.speedY[playerId] > 0.0D + && this.state.speedY[playerId] > -this.state.speedX[playerId])) { speedEffect = this.getSpeedEffect(bottomright, playerId, x + diagOffset, y + diagOffset, ball, canvas, 1, 1); - temp = this.speedX[playerId]; - this.speedX[playerId] = -this.speedY[playerId] * speedEffect; - this.speedY[playerId] = -temp * speedEffect; + temp = this.state.speedX[playerId]; + this.state.speedX[playerId] = -this.state.speedY[playerId] * speedEffect; + this.state.speedY[playerId] = -temp * speedEffect; } if (bottomleftCollide - && (this.speedX[playerId] < 0.0D && this.speedY[playerId] > 0.0D - || this.speedX[playerId] > 0.0D - && this.speedY[playerId] > 0.0D - && this.speedY[playerId] > this.speedX[playerId] - || this.speedX[playerId] < 0.0D - && this.speedY[playerId] < 0.0D - && -this.speedX[playerId] > -this.speedY[playerId])) { + && (this.state.speedX[playerId] < 0.0D && this.state.speedY[playerId] > 0.0D + || this.state.speedX[playerId] > 0.0D + && this.state.speedY[playerId] > 0.0D + && this.state.speedY[playerId] > this.state.speedX[playerId] + || this.state.speedX[playerId] < 0.0D + && this.state.speedY[playerId] < 0.0D + && -this.state.speedX[playerId] > -this.state.speedY[playerId])) { speedEffect = this.getSpeedEffect(bottomleft, playerId, x - diagOffset, y + diagOffset, ball, canvas, -1, 1); - temp = this.speedX[playerId]; - this.speedX[playerId] = this.speedY[playerId] * speedEffect; - this.speedY[playerId] = temp * speedEffect; + temp = this.state.speedX[playerId]; + this.state.speedX[playerId] = this.state.speedY[playerId] * speedEffect; + this.state.speedY[playerId] = temp * speedEffect; } if (topleftCollide - && (this.speedX[playerId] < 0.0D && this.speedY[playerId] < 0.0D - || this.speedX[playerId] < 0.0D - && this.speedY[playerId] > 0.0D - && -this.speedX[playerId] > this.speedY[playerId] - || this.speedX[playerId] > 0.0D - && this.speedY[playerId] < 0.0D - && -this.speedY[playerId] > this.speedX[playerId])) { + && (this.state.speedX[playerId] < 0.0D && this.state.speedY[playerId] < 0.0D + || this.state.speedX[playerId] < 0.0D + && this.state.speedY[playerId] > 0.0D + && -this.state.speedX[playerId] > this.state.speedY[playerId] + || this.state.speedX[playerId] > 0.0D + && this.state.speedY[playerId] < 0.0D + && -this.state.speedY[playerId] > this.state.speedX[playerId])) { speedEffect = this.getSpeedEffect(topleft, playerId, x - diagOffset, y - diagOffset, ball, canvas, -1, -1); - temp = this.speedX[playerId]; - this.speedX[playerId] = -this.speedY[playerId] * speedEffect; - this.speedY[playerId] = -temp * speedEffect; + temp = this.state.speedX[playerId]; + this.state.speedX[playerId] = -this.state.speedY[playerId] * speedEffect; + this.state.speedY[playerId] = -temp * speedEffect; } } else { - if (topCollide && this.speedY[playerId] < 0.0D) { + if (topCollide && this.state.speedY[playerId] < 0.0D) { speedEffect = this.getSpeedEffect(top, playerId, x, y - 6, ball, canvas, 0, -1); - this.speedX[playerId] *= speedEffect; - this.speedY[playerId] *= -speedEffect; - } else if (bottomCollide && this.speedY[playerId] > 0.0D) { + this.state.speedX[playerId] *= speedEffect; + this.state.speedY[playerId] *= -speedEffect; + } else if (bottomCollide && this.state.speedY[playerId] > 0.0D) { speedEffect = this.getSpeedEffect(bottom, playerId, x, y + 6, ball, canvas, 0, 1); - this.speedX[playerId] *= speedEffect; - this.speedY[playerId] *= -speedEffect; + this.state.speedX[playerId] *= speedEffect; + this.state.speedY[playerId] *= -speedEffect; } - if (rightCollide && this.speedX[playerId] > 0.0D) { + if (rightCollide && this.state.speedX[playerId] > 0.0D) { speedEffect = this.getSpeedEffect(right, playerId, x + 6, y, ball, canvas, 1, 0); - this.speedX[playerId] *= -speedEffect; - this.speedY[playerId] *= speedEffect; + this.state.speedX[playerId] *= -speedEffect; + this.state.speedY[playerId] *= speedEffect; return; } - if (leftcollide && this.speedX[playerId] < 0.0D) { + if (leftcollide && this.state.speedX[playerId] < 0.0D) { speedEffect = this.getSpeedEffect(left, playerId, x - 6, y, ball, canvas, -1, 0); - this.speedX[playerId] *= -speedEffect; - this.speedY[playerId] *= speedEffect; + this.state.speedX[playerId] *= -speedEffect; + this.state.speedY[playerId] *= speedEffect; return; } } @@ -1522,13 +1460,13 @@ private double getSpeedEffect( return 0.05D; // 18 Bouncy Block } else if (tileId == 18) { - if (this.bounciness <= 0.0D) { + if (this.state.bounciness <= 0.0D) { return 0.84D; } else { - this.bounciness -= 0.01D; - double speed = Math.sqrt( - this.speedX[playerId] * this.speedX[playerId] + this.speedY[playerId] * this.speedY[playerId]); - return this.bounciness * 6.5D / speed; + this.state.bounciness -= 0.01D; + double speed = Math.sqrt(this.state.speedX[playerId] * this.state.speedX[playerId] + + this.state.speedY[playerId] * this.state.speedY[playerId]); + return this.state.bounciness * 6.5D / speed; } // 20 Oneway North // 21 Oneway East @@ -1557,35 +1495,35 @@ private double getSpeedEffect( } private void handleTeleport(int teleportId, int playerId, int x, int y) { - int exitLen = this.teleportExists[teleportId].size(); + int exitLen = this.state.teleportExits[teleportId].size(); int startLen; int random; double[] teleportPos; - int var13; + int selectedTeleportId; if (exitLen > 0) { - var13 = teleportId; + selectedTeleportId = teleportId; startLen = exitLen - 1; - random = this.rngSeed.next() % (startLen + 1); + random = this.state.seed.next() % (startLen + 1); } else { - startLen = this.teleportStarts[teleportId].size(); + startLen = this.state.teleportStarts[teleportId].size(); int i; if (startLen >= 2) { - int var14 = 0; + int attemptCount = 0; // ????? do { i = startLen - 1; - random = this.rngSeed.next() % (i + 1); - teleportPos = this.teleportStarts[teleportId].get(random); + random = this.state.seed.next() % (i + 1); + teleportPos = this.state.teleportStarts[teleportId].get(random); if (Math.abs(teleportPos[0] - (double) x) >= 15.0D || Math.abs(teleportPos[1] - (double) y) >= 15.0D) { - this.playerX[playerId] = teleportPos[0]; - this.playerY[playerId] = teleportPos[1]; + this.state.playerX[playerId] = teleportPos[0]; + this.state.playerY[playerId] = teleportPos[1]; return; } - ++var14; - } while (var14 < 100); + ++attemptCount; + } while (attemptCount < 100); return; } @@ -1593,7 +1531,7 @@ private void handleTeleport(int teleportId, int playerId, int x, int y) { boolean haveExit = false; for (i = 0; i < 4 && !haveExit; ++i) { - if (this.teleportExists[i].size() > 0) { + if (this.state.teleportExits[i].size() > 0) { haveExit = true; } } @@ -1603,35 +1541,35 @@ private void handleTeleport(int teleportId, int playerId, int x, int y) { } do { - var13 = this.rngSeed.next() % 4; - exitLen = this.teleportExists[var13].size(); + selectedTeleportId = this.state.seed.next() % 4; + exitLen = this.state.teleportExits[selectedTeleportId].size(); } while (exitLen == 0); - int var12 = exitLen - 1; - random = this.rngSeed.next() % (var12 + 1); + random = this.state.seed.next() % (exitLen); } // finally move player to exit position - teleportPos = this.teleportExists[var13].get(random); - this.playerX[playerId] = teleportPos[0]; - this.playerY[playerId] = teleportPos[1]; + teleportPos = this.state.teleportExits[selectedTeleportId].get(random); + this.state.playerX[playerId] = teleportPos[0]; + this.state.playerY[playerId] = teleportPos[1]; } private void handleMines( - boolean isBigMine, int playerId, int screenX, int screenY, Graphics var5, Graphics canvas) { + boolean isBigMine, int playerId, int screenX, int screenY, Graphics ballCanvas, Graphics canvas) { int mapX = screenX / 15; int mapY = screenY / 15; - int special = super.trackTiles[mapX][mapY] / 16777216; - int shape = super.trackTiles[mapX][mapY] / 65536 % 256 + 24; - int foreground = super.trackTiles[mapX][mapY] / 256 % 256; - int background = super.trackTiles[mapX][mapY] % 256; + Tile tile = this.map.getTile(mapX, mapY); + int special = tile.getSpecial(); + int shape = tile.getShape(); + int foreground = tile.getForeground(); + int background = tile.getBackground(); // 28 Mine // 30 Big Mine if (special == 2 && (shape == 28 || shape == 30)) { ++shape; - super.trackTiles[mapX][mapY] = - special * 256 * 256 * 256 + (shape - 24) * 256 * 256 + foreground * 256 + background; - this.drawTile(mapX, mapY, var5, canvas); + this.map.updateTile( + mapX, mapY, special * 256 * 256 * 256 + (shape - 24) * 256 * 256 + foreground * 256 + background); + this.drawTile(mapX, mapY, ballCanvas, canvas); // Big Mine will dig a hole around mine if (isBigMine) { @@ -1646,9 +1584,10 @@ private void handleMines( && y >= 0 && y < 25 && (y != mapY || x != mapX) - && super.trackTiles[x][y] == 16777216) { - super.trackTiles[x][y] = downhills[tileIndex]; - this.drawTile(x, y, var5, canvas); + && this.map.getTile(x, y).getCode() == 16777216) { + // super.map.setTile(x, y, downhills[tileIndex]); + this.map.updateTile(x, y, downhills[tileIndex]); + this.drawTile(x, y, ballCanvas, canvas); } ++tileIndex; @@ -1659,53 +1598,63 @@ private void handleMines( double speed; do { do { - this.speedX[playerId] = (double) (-65 + this.rngSeed.next() % 131) / 10.0D; - this.speedY[playerId] = (double) (-65 + this.rngSeed.next() % 131) / 10.0D; - speed = Math.sqrt(this.speedX[playerId] * this.speedX[playerId] - + this.speedY[playerId] * this.speedY[playerId]); + this.state.speedX[playerId] = (double) (-65 + this.state.seed.next() % 131) / 10.0D; + this.state.speedY[playerId] = (double) (-65 + this.state.seed.next() % 131) / 10.0D; + speed = Math.sqrt(this.state.speedX[playerId] * this.state.speedX[playerId] + + this.state.speedY[playerId] * this.state.speedY[playerId]); } while (speed < 5.2D); } while (speed > 6.5D); if (!isBigMine) { - this.speedX[playerId] *= 0.8D; - this.speedY[playerId] *= 0.8D; + this.state.speedX[playerId] *= 0.8D; + this.state.speedY[playerId] *= 0.8D; } } } private boolean handleMovableBlock( - int screenX, int screenY, Graphics var3, Graphics canvas, int offsetX, int offsetY, boolean nonSunkable) { + int screenX, + int screenY, + Graphics ballGraphics, + Graphics canvas, + int offsetX, + int offsetY, + boolean nonSunkable) { int mapX = screenX / 15; int mapY = screenY / 15; - int special = super.trackTiles[mapX][mapY] / 16777216; - int shape = super.trackTiles[mapX][mapY] / 65536 % 256 + 24; - int background = super.trackTiles[mapX][mapY] / 256 % 256; + Tile tile = this.map.getTile(mapX, mapY); + int special = tile.getSpecial(); + int shape = tile.getShape(); + int background = tile.getBackground(); if (special == 2 && (shape == 27 || shape == 46)) { // where we want to move the block int x1 = mapX + offsetX; int y1 = mapY + offsetY; - int canMove = this.canMovableBlockMove(x1, y1); + int canMove = this.map.canMovableBlockMove( + x1, y1, this.state.playerX, this.state.playerY, this.state.playerCount); if (canMove == -1) { return false; } else { // 16777216 == special:1 shape:0 fg:0 bg:0 - super.trackTiles[mapX][mapY] = 16777216 + background * 256; - this.drawTile(mapX, mapY, var3, canvas); + this.map.updateTile(mapX, mapY, 16777216 + background * 256); + this.drawTile(mapX, mapY, ballGraphics, canvas); // [x,y,background id] - int[] tileWithCoords = this.calculateMovableBlockEndPosition( - mapX, mapY, x1, y1, background, canMove, var3, canvas, nonSunkable, 0); + int[] tileWithCoords = + this.calculateMovableBlockEndPosition(mapX, mapY, x1, y1, background, canMove, nonSunkable, 0); // 12 Water // 13 Acid if (!nonSunkable && (tileWithCoords[2] == 12 || tileWithCoords[2] == 13)) { // Sunked Movable Block with old background - super.trackTiles[tileWithCoords[0]][tileWithCoords[1]] = 35061760 + tileWithCoords[2] * 256; + this.map.updateTile(tileWithCoords[0], tileWithCoords[1], 35061760 + tileWithCoords[2] * 256); } else { // Movable Block with old background - super.trackTiles[tileWithCoords[0]][tileWithCoords[1]] = - 33554432 + ((nonSunkable ? 27 : 46) - 24) * 256 * 256 + tileWithCoords[2] * 256; + this.map.updateTile( + tileWithCoords[0], + tileWithCoords[1], + 33554432 + ((nonSunkable ? 27 : 46) - 24) * 256 * 256 + tileWithCoords[2] * 256); } - this.drawTile(tileWithCoords[0], tileWithCoords[1], var3, canvas); + this.drawTile(tileWithCoords[0], tileWithCoords[1], ballGraphics, canvas); return true; } } else { @@ -1713,43 +1662,16 @@ private boolean handleMovableBlock( } } - private int canMovableBlockMove(int x, int y) { - if (x >= 0 && x < 49 && y >= 0 && y < 25) { - int special = super.trackTiles[x][y] / 16777216; - int shape = super.trackTiles[x][y] / 65536 % 256; - int background = super.trackTiles[x][y] / 256 % 256; - if (special == 1 && shape == 0 && background <= 15) { - for (int i = 0; i < this.playerCount; ++i) { - if (this.playerX[i] > (double) (x * 15) - && this.playerX[i] < (double) (x * 15 + 15 - 1) - && this.playerY[i] > (double) (y * 15) - && this.playerY[i] < (double) (y * 15 + 15 - 1)) { - return -1; - } - } - - return background; - } else { - return -1; - } - } else { - return -1; - } - } - + // Block in coordinates (x, y) with background 'background' + // Destination (x1, y1) with background 'background1' + // calculates the end position (if the block moves more than once) + // + // Returns an array of three: (x, y) of the block end position and the + // background of that tile. private int[] calculateMovableBlockEndPosition( - int x, - int y, - int x1, - int y1, - int background, - int background1, - Graphics var7, - Graphics var8, - boolean var9, - int i) { + int x, int y, int x1, int y1, int background, int background1, boolean nonSunkable, int i) { int[] xytile = new int[] {x1, y1, background1}; - if (!var9 && background1 >= 4 && background1 <= 11 && i < 1078) { + if (!nonSunkable && background1 >= 4 && background1 <= 11 && i < 1078) { x = x1; y = y1; background = background1; @@ -1771,51 +1693,55 @@ private int[] calculateMovableBlockEndPosition( --x1; } - background1 = this.canMovableBlockMove(x1, y1); + background1 = this.map.canMovableBlockMove( + x1, y1, this.state.playerX, this.state.playerY, this.state.playerCount); if (background1 >= 0) { xytile = this.calculateMovableBlockEndPosition( - x, y, x1, y1, background, background1, var7, var8, var9, i + 1); + x, y, x1, y1, background, background1, nonSunkable, i + 1); } } return xytile; } - private void handleBreakableBlock(int screenX, int screenY, Graphics var3, Graphics canvas) { + private void handleBreakableBlock(int screenX, int screenY, Graphics ballGraphics, Graphics canvas) { int mapX = screenX / 15; int mapY = screenY / 15; - int special = super.trackTiles[mapX][mapY] / 16777216; - int shape = super.trackTiles[mapX][mapY] / 65536 % 256 + 24; - int background = super.trackTiles[mapX][mapY] / 256 % 256; - int foreground = super.trackTiles[mapX][mapY] % 256; + Tile tile = this.map.getTile(mapX, mapY); + int special = tile.getSpecial(); + int shape = tile.getShape(); + int background = tile.getBackground(); + int foreground = tile.getForeground(); if (special == 2 && shape >= 40 && shape <= 43) { ++shape; if (shape <= 43) { - super.trackTiles[mapX][mapY] = - special * 256 * 256 * 256 + (shape - 24) * 256 * 256 + background * 256 + foreground; + this.map.updateTile( + mapX, + mapY, + special * 256 * 256 * 256 + (shape - 24) * 256 * 256 + background * 256 + foreground); } else { - super.trackTiles[mapX][mapY] = 16777216 + background * 256 + background; + this.map.updateTile(mapX, mapY, 16777216 + background * 256 + background); } - this.drawTile(mapX, mapY, var3, canvas); + this.drawTile(mapX, mapY, ballGraphics, canvas); } } - private void drawTile(int tileX, int tileY, Graphics var3, Graphics var4) { - Image tile = super.getTileAt(tileX, tileY); - super.collisionMap(tileX, tileY); - var3.drawImage(tile, tileX * 15, tileY * 15, this); - var4.drawImage(tile, tileX * 15, tileY * 15, this); + private void drawTile(int tileX, int tileY, Graphics ballGraphics, Graphics canvas) { + Image tile = super.getTileImageAt(tileX, tileY); + super.map.collisionMap(tileX, tileY, super.gameContainer.spriteManager); + ballGraphics.drawImage(tile, tileX * 15, tileY * 15, this); + canvas.drawImage(tile, tileX * 15, tileY * 15, this); } - private void drawPlayer(Graphics g, int playerid, double var3) { - int x = (int) (this.playerX[playerid] - 6.5D + 0.5D); - int y = (int) (this.playerY[playerid] - 6.5D + 0.5D); - int var7 = 13; - if (var3 > 0.0D) { - x = (int) ((double) x + var3); - y = (int) ((double) y + var3); - var7 = (int) ((double) var7 - var3 * 2.0D); + private void drawPlayer(Graphics g, int playerid, double shrinkAmount) { + int x = (int) (this.state.playerX[playerid] - 6.5D + 0.5D); + int y = (int) (this.state.playerY[playerid] - 6.5D + 0.5D); + int ballSize = 13; + if (shrinkAmount > 0.0D) { + x = (int) ((double) x + shrinkAmount); + y = (int) ((double) y + shrinkAmount); + ballSize = (int) ((double) ballSize - shrinkAmount * 2.0D); } int ballSpriteOffset = 0; @@ -1823,12 +1749,12 @@ private void drawPlayer(Graphics g, int playerid, double var3) { ballSpriteOffset = (x / 5 + y / 5) % 2 * 4; } - if (var3 == 0.0D) { + if (shrinkAmount == 0.0D) { g.drawImage(this.ballSprites[playerid + ballSpriteOffset], x, y, this); if (this.playerNamesDisplayMode > 0 - && this.aBooleanArray2834[playerid] - && this.gameState != 2 - && this.playerCount > 1) { + && this.state.playerActive[playerid] + && this.state.gameState != 2 + && this.state.playerCount > 1) { String[] playerName = super.gameContainer.gamePanel.getPlayerName(playerid); if (this.playerNamesDisplayMode == 1) { StringDraw.drawString(g, playerName[0].substring(0, 1), x + 6, y + 13 - 3, 0); @@ -1840,14 +1766,15 @@ private void drawPlayer(Graphics g, int playerid, double var3) { if (this.playerNamesDisplayMode != 2 && playerName[1] != null) { String clanName = "[" + playerName[1] + "]"; int clanWidth = StringDraw.getStringWidth(g, clanName); - byte var14 = -1; + byte textAlignment = -1; if (textX + nameWidth >= 733 || textX + clanWidth >= 733) { textX = x - 2; - var14 = 1; + textAlignment = 1; } - StringDraw.drawOutlinedString(g, backgroundColour, playerName[0], textX, y + 13 - 3 - 6, var14); - StringDraw.drawOutlinedString(g, backgroundColour, clanName, textX, y + 13 - 3 + 7, var14); + StringDraw.drawOutlinedString( + g, backgroundColour, playerName[0], textX, y + 13 - 3 - 6, textAlignment); + StringDraw.drawOutlinedString(g, backgroundColour, clanName, textX, y + 13 - 3 + 7, textAlignment); return; } @@ -1858,7 +1785,17 @@ private void drawPlayer(Graphics g, int playerid, double var3) { StringDraw.drawOutlinedString(g, backgroundColour, playerName[0], textX, y + 13 - 3, -1); } } else { - g.drawImage(this.ballSprites[playerid + ballSpriteOffset], x, y, x + var7, y + var7, 0, 0, 13, 13, this); + g.drawImage( + this.ballSprites[playerid + ballSpriteOffset], + x, + y, + x + ballSize, + y + ballSize, + 0, + 0, + 13, + 13, + this); } } @@ -1872,46 +1809,55 @@ private void setStrokeListeners(boolean requestFocus) { } } - private void drawDashedLine(Graphics var1, int var2, int var3, int var4, int var5) { - int var6 = var4 >= 0 ? var4 : -var4; - int var7 = var5 >= 0 ? var5 : -var5; - int var8 = Math.max(var6, var7) / 10; - double var9 = var2; - double var11 = var3; - double var13 = (double) var4 / ((double) var8 * 2.0D); - double var15 = (double) var5 / ((double) var8 * 2.0D); - var9 += var13; - var11 += var15; - - for (int var17 = 0; var17 < var8; ++var17) { - var1.drawLine((int) var9, (int) var11, (int) (var9 + var13), (int) (var11 + var15)); - var9 += var13 * 2.0D; - var11 += var15 * 2.0D; + private void drawDashedLine(Graphics g, int x, int y, int deltaX, int deltaY) { + int absDeltaX = Math.abs(deltaX); + int absDeltaY = Math.abs(deltaY); + int dashCount = Math.max(absDeltaX, absDeltaY) / 10; + + double currentX = x; + double currentY = y; + + double stepX = (double) deltaX / (dashCount * 2.0D); + double stepY = (double) deltaY / (dashCount * 2.0D); + + currentX += stepX; + currentY += stepY; + + for (int i = 0; i < dashCount; ++i) { + g.drawLine((int) currentX, (int) currentY, (int) (currentX + stepX), (int) (currentY + stepY)); + + currentX += stepX * 2.0D; + currentY += stepY * 2.0D; } } - private void method164(int var1) { - anIntArray2837[0] = anIntArray2837[1]; - anIntArray2837[1] = anIntArray2837[2]; - if (anIntArray2837[1] < var1) { - var1 = anIntArray2837[1]; + // Possibly changes the value of maxPhysicsiterations. + // Running the physics loop takes few milliseconds, and it runs inside + // a while loop, so the accumulatedSleepTime can get value of several + // thousands (at least on my pc). I assume that on a slow machine running + // the loop can then take over 12ms and then the accumulatedSleepTime will + // get negative value. + private void adjustPhysicsIterations(int frameTime) { + frameTimeHistory[0] = frameTimeHistory[1]; + frameTimeHistory[1] = frameTimeHistory[2]; + if (frameTimeHistory[1] < frameTime) { + frameTime = frameTimeHistory[1]; } - if (anIntArray2837[0] < var1) { - var1 = anIntArray2837[0]; + if (frameTimeHistory[0] < frameTime) { + frameTime = frameTimeHistory[0]; } - while (var1 > 700 && this.anInt2839 > 1) { - var1 -= 700; - --this.anInt2839; + while (frameTime > 700 && this.state.maxPhysicsIterations > 1) { + frameTime -= 700; + --this.state.maxPhysicsIterations; } - while (var1 < -2000 && this.anInt2839 < 6) { - var1 += 2000; - ++this.anInt2839; + while (frameTime < -2000 && this.state.maxPhysicsIterations < 6) { + frameTime += 2000; + ++this.state.maxPhysicsIterations; } - anIntArray2837[2] = var1; - anInt2838 = this.anInt2839; + frameTimeHistory[2] = frameTime; } } diff --git a/client/src/main/java/agolf/game/GamePanel.java b/client/src/main/java/agolf/game/GamePanel.java index 4b4385eb..bb7b4c7f 100644 --- a/client/src/main/java/agolf/game/GamePanel.java +++ b/client/src/main/java/agolf/game/GamePanel.java @@ -249,7 +249,7 @@ public void handlePacket(String[] args) { } this.aBoolean363 = false; - this.gameCanvas.createMap(16777216); + this.gameCanvas.initializeGameArea(); this.playerInfoPanel.reset(); this.trackInfoPanel.resetCurrentTrack(); this.setState(1); @@ -336,8 +336,8 @@ public void handlePacket(String[] args) { var15[1][2]= number of ratings: 2 var15[1][3]= number of ratings: 3 */ - String[] trackInformation = this.gameCanvas.generateTrackInformation(); - int[][] trackStats = this.gameCanvas.generateTrackStatistics(); + String[] trackInformation = this.gameCanvas.trackStats.generateTrackInformation(); + int[][] trackStats = this.gameCanvas.trackStats.generateTrackStatistics(); this.trackInfoPanel.parseTrackInfoStats( trackInformation[0], @@ -348,7 +348,7 @@ public void handlePacket(String[] args) { trackInformation[3], trackTestMode1, trackTestMode2, - this.gameCanvas.method134()); + this.gameCanvas.hasCoordinates()); int trackScoreMultiplier = this.playerInfoPanel.startNextTrack(); if (trackScoreMultiplier > 1) { @@ -360,9 +360,11 @@ public void handlePacket(String[] args) { if (this.gameContainer.synchronizedTrackTestMode.get()) { this.chatPanel.printSpecialSettingstoTextArea( - this.gameCanvas.getTrackComment(), - this.gameCanvas.getTrackSettings(), - this.gameCanvas.method120()); + // First arg should be comment, but v2 tracks don't + // have comments + this.gameCanvas.track.getAuthor(), + this.gameCanvas.track.getSettings(), + this.gameCanvas.map.getLatestTileSpeciality()); } } case "startturn" -> { @@ -447,12 +449,12 @@ protected void setBeginStroke(int playerId, int x, int y, int shootingMode) { } protected void method336() { - String var1 = this.gameCanvas.method142(); - if (var1 != null) { + String coords = this.gameCanvas.encodeCoordinates(); + if (coords != null) { this.playerInfoPanel.strokeStartedOrEnded(0, false); - String var2 = "beginstroke\t" + var1; + String var2 = "beginstroke\t" + coords; this.gameContainer.connection.writeData("game\t" + var2); - this.gameCanvas.decodeCoords(0, true, var1); + this.gameCanvas.decodeCoords(0, true, coords); } } diff --git a/client/src/main/java/agolf/game/GameState.java b/client/src/main/java/agolf/game/GameState.java new file mode 100644 index 00000000..dab2ebfc --- /dev/null +++ b/client/src/main/java/agolf/game/GameState.java @@ -0,0 +1,48 @@ +package agolf.game; + +import agolf.Seed; +import agolf.SynchronizedBool; +import java.util.List; + +public class GameState { + + // Constants + private static final double MAGIC_OFFSET = Math.sqrt(2.0) / 2.0; + private static final int DIAG_OFFSET = (int) (6.0 * MAGIC_OFFSET + 0.5); + private static final int[] FRAME_TIME_HISTORY = new int[] {Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE}; + + // Game state variables + public int playerCount; + public int onShoreSetting; + public int collisionMode; + public int currentPlayerId; + public int isValidPlayerId; + public int gameState; + + public double startPositionX; + public double startPositionY; + public double bounciness; + public double somethingSpeedThing; + + public double[] resetPositionX; + public double[] resetPositionY; + + public List[] teleportStarts; + public List[] teleportExits; + + public short[][][] magnetMap; + + public double[] playerX; + public double[] playerY; + public double[] speedX; + public double[] speedY; + + public boolean[] simulatePlayer; + public SynchronizedBool[] onHoleSync; + public boolean isLocalPlayer; + public boolean[] playerActive; + + public Seed seed; + public int maxPhysicsIterations; + public boolean strokeInterrupted; +} diff --git a/client/src/main/java/agolf/game/HackedShot.java b/client/src/main/java/agolf/game/HackedShot.java index 5ef8cffd..180b84a5 100644 --- a/client/src/main/java/agolf/game/HackedShot.java +++ b/client/src/main/java/agolf/game/HackedShot.java @@ -8,101 +8,100 @@ public class HackedShot implements Runnable { - private static final double aDouble2798 = Math.sqrt(2.0D) / 2.0D; - private static final int anInt2799 = (int) (6.0D * aDouble2798 + 0.5D); - private static int[] anIntArray2837 = new int[] {Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE}; + private static final double magicOffset = Math.sqrt(2.0D) / 2.0D; + private static final int diagOffset = (int) (6.0D * magicOffset + 0.5D); + private static int[] frameTimeHistory = new int[] {Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE}; - private int anInt2809; - private int anInt2810; - private int anInt2811; + private int playerCount; + private int onShoreSetting; + private int collisionMode; private int currentPlayerID; private int anInt2816; - private double aDouble2817; - private double aDouble2818; - private double aDouble2819; - private double aDouble2820; - private double[] aDoubleArray2821; - private double[] aDoubleArray2822; + private double startPositionX; + private double startPositionY; + private double bounciness; + private double somethingSpeedThing; + private double[] resetPositionX; + private double[] resetPositionY; private List[] teleportStarts; private List[] teleportExits; - private short[][][] aShortArrayArrayArray2825; + private short[][][] magnetMap; private double[] playerX; private double[] playerY; - private double[] aDoubleArray2828; - private double[] aDoubleArray2829; - private boolean[] aBooleanArray2830; - private SynchronizedBool[] aSynchronizedBoolArray2831; - private boolean aBoolean2832; - private boolean[] aBooleanArray2834; - private Seed aSeed_2836; - private int anInt2839; - private boolean aBoolean2843; + private double[] speedX; + private double[] speedY; + private boolean[] simulatePlayer; + private SynchronizedBool[] onHoleSync; + private boolean isLocalPlayer; + private boolean[] playerActive; + private Seed seed; + private int maxPhysicsIterations; + private boolean strokeInterrupted; // from superclass - protected byte[][] isSolidArrayIThink; + protected byte[][] collisionMap; protected int[][] mapTiles; // this actually scares me, but its for science. public HackedShot( - int anInt2809, - int anInt2810, - int anInt2811, + int playerCount, + int onShoreSetting, + int collisionMode, int currentPlayerID, - int anInt2816, - double aDouble2817, - double aDouble2818, - double aDouble2819, - double aDouble2820, - double[] aDoubleArray2821, - double[] aDoubleArray2822, + int playerId, + double startPositionX, + double startPositionY, + double bounciness, + double somethingSpeedThing, + double[] resetPositionX, + double[] resetPositionY, List[] teleportStarts, List[] teleportExits, - short[][][] aShortArrayArrayArray2825, + short[][][] magnetMap, double[] playerX, double[] playerY, double[] aDoubleArray2828, double[] aDoubleArray2829, - boolean[] aBooleanArray2830, - SynchronizedBool[] aSynchronizedBoolArray2831, + boolean[] simulatePlayer, + SynchronizedBool[] onHoleSync, boolean aBoolean2832, - boolean[] aBooleanArray2834, - Seed aSeed_2836, - int anInt2839, + boolean[] playerActive, + Seed seed, + int maxPhysicsIterations, boolean aBoolean2843, - byte[][] isSolidArrayIThink, + byte[][] collisionMap, int[][] mapTiles) { - this.anInt2809 = anInt2809; - this.anInt2810 = anInt2810; - this.anInt2811 = anInt2811; + this.playerCount = playerCount; + this.onShoreSetting = onShoreSetting; + this.collisionMode = collisionMode; this.currentPlayerID = currentPlayerID; - this.anInt2816 = anInt2816; - this.aDouble2817 = aDouble2817; - this.aDouble2818 = aDouble2818; - this.aDouble2819 = aDouble2819; - this.aDouble2820 = aDouble2820; - this.aDoubleArray2821 = Arrays.copyOf(aDoubleArray2821, aDoubleArray2821.length); - this.aDoubleArray2822 = Arrays.copyOf(aDoubleArray2822, aDoubleArray2822.length); + this.anInt2816 = playerId; + this.startPositionX = startPositionX; + this.startPositionY = startPositionY; + this.bounciness = bounciness; + this.somethingSpeedThing = somethingSpeedThing; + this.resetPositionX = Arrays.copyOf(resetPositionX, resetPositionX.length); + this.resetPositionY = Arrays.copyOf(resetPositionY, resetPositionY.length); this.teleportStarts = Arrays.copyOf(teleportStarts, teleportStarts.length); this.teleportExits = Arrays.copyOf(teleportExits, teleportExits.length); - if (aShortArrayArrayArray2825 != null) { - this.aShortArrayArrayArray2825 = Arrays.copyOf(aShortArrayArrayArray2825, aShortArrayArrayArray2825.length); + if (magnetMap != null) { + this.magnetMap = Arrays.copyOf(magnetMap, magnetMap.length); } else { - this.aShortArrayArrayArray2825 = null; + this.magnetMap = null; } this.playerX = Arrays.copyOf(playerX, playerX.length); this.playerY = Arrays.copyOf(playerY, playerY.length); - this.aDoubleArray2828 = Arrays.copyOf(aDoubleArray2828, aDoubleArray2828.length); - this.aDoubleArray2829 = Arrays.copyOf(aDoubleArray2829, aDoubleArray2829.length); - this.aBooleanArray2830 = Arrays.copyOf(aBooleanArray2830, aBooleanArray2830.length); - this.aSynchronizedBoolArray2831 = - Arrays.copyOf(aSynchronizedBoolArray2831, aSynchronizedBoolArray2831.length); // unsure bout thsione - this.aBoolean2832 = aBoolean2832; - this.aBooleanArray2834 = Arrays.copyOf(aBooleanArray2834, aBooleanArray2834.length); - this.aSeed_2836 = aSeed_2836.clone(); - this.anInt2839 = anInt2839; - this.aBoolean2843 = aBoolean2843; - this.isSolidArrayIThink = Arrays.copyOf(isSolidArrayIThink, isSolidArrayIThink.length); + this.speedX = Arrays.copyOf(aDoubleArray2828, aDoubleArray2828.length); + this.speedY = Arrays.copyOf(aDoubleArray2829, aDoubleArray2829.length); + this.simulatePlayer = Arrays.copyOf(simulatePlayer, simulatePlayer.length); + this.onHoleSync = Arrays.copyOf(onHoleSync, onHoleSync.length); // unsure bout thsione + this.isLocalPlayer = aBoolean2832; + this.playerActive = Arrays.copyOf(playerActive, playerActive.length); + this.seed = seed.clone(); + this.maxPhysicsIterations = maxPhysicsIterations; + this.strokeInterrupted = aBoolean2843; + this.collisionMap = Arrays.copyOf(collisionMap, collisionMap.length); this.mapTiles = Arrays.copyOf(mapTiles, mapTiles.length); } @@ -116,26 +115,26 @@ public void run() { */ int var5 = 0; - int[] var6 = new int[this.anInt2809]; - int[] var7 = new int[this.anInt2809]; - double[] var8 = new double[this.anInt2809]; - double[] var9 = new double[this.anInt2809]; - double[] var10 = new double[this.anInt2809]; - double[] var11 = new double[this.anInt2809]; - double[] var12 = new double[this.anInt2809]; - double[] var13 = new double[this.anInt2809]; - double[] var14 = new double[this.anInt2809]; - boolean[] var15 = new boolean[this.anInt2809]; - boolean[] var16 = new boolean[this.anInt2809]; - boolean[] var17 = new boolean[this.anInt2809]; - int[] var18 = new int[this.anInt2809]; - - for (int var19 = 0; var19 < this.anInt2809; ++var19) { + int[] var6 = new int[this.playerCount]; + int[] var7 = new int[this.playerCount]; + double[] var8 = new double[this.playerCount]; + double[] var9 = new double[this.playerCount]; + double[] var10 = new double[this.playerCount]; + double[] var11 = new double[this.playerCount]; + double[] var12 = new double[this.playerCount]; + double[] var13 = new double[this.playerCount]; + double[] var14 = new double[this.playerCount]; + boolean[] var15 = new boolean[this.playerCount]; + boolean[] var16 = new boolean[this.playerCount]; + boolean[] var17 = new boolean[this.playerCount]; + int[] var18 = new int[this.playerCount]; + + for (int var19 = 0; var19 < this.playerCount; ++var19) { var6[var19] = var7[var19] = 0; var8[var19] = var11[var19] = this.playerX[var19]; var9[var19] = var12[var19] = this.playerY[var19]; var15[var19] = var16[var19] = false; - var10[var19] = this.aSynchronizedBoolArray2831[var19].get() ? 2.1666666666666665D : 0.0D; + var10[var19] = this.onHoleSync[var19].get() ? 2.1666666666666665D : 0.0D; var17[var19] = false; var18[var19] = 0; } @@ -145,7 +144,7 @@ public void run() { boolean var22 = true; boolean var23 = true; - int var24 = -1; + int allPlayersStoppedCounter = -1; byte var25 = 0; byte var26 = 0; byte var27 = 0; @@ -158,27 +157,27 @@ public void run() { int var34 = 0; int var35 = 0; double var36 = 0.0D; - this.aDouble2819 = this.aDouble2820 = 1.0D; + this.bounciness = this.somethingSpeedThing = 1.0D; int var38 = 0; do { long var39 = System.currentTimeMillis(); - for (int var41 = 0; var41 < this.anInt2809; ++var41) { + for (int var41 = 0; var41 < this.playerCount; ++var41) { var13[var41] = this.playerX[var41]; var14[var41] = this.playerY[var41]; } int var43; int var44; - for (int var42 = 0; var42 < this.anInt2839; ++var42) { - var24 = 0; + for (int var42 = 0; var42 < this.maxPhysicsIterations; ++var42) { + allPlayersStoppedCounter = 0; - for (var43 = 0; var43 < this.anInt2809; ++var43) { - if (this.aBooleanArray2830[var43] && !this.aSynchronizedBoolArray2831[var43].get()) { + for (var43 = 0; var43 < this.playerCount; ++var43) { + if (this.simulatePlayer[var43] && !this.onHoleSync[var43].get()) { for (var44 = 0; var44 < 10; ++var44) { - this.playerX[var43] += this.aDoubleArray2828[var43] * 0.1D; - this.playerY[var43] += this.aDoubleArray2829[var43] * 0.1D; + this.playerX[var43] += this.speedX[var43] * 0.1D; + this.playerY[var43] += this.speedY[var43] * 0.1D; if (this.playerX[var43] < 6.6D) { this.playerX[var43] = 6.6D; } @@ -196,39 +195,39 @@ public void run() { } int var45; - if (this.anInt2811 == 1 && !var15[var43] && !var16[var43]) { - for (var45 = 0; var45 < this.anInt2809; ++var45) { + if (this.collisionMode == 1 && !var15[var43] && !var16[var43]) { + for (var45 = 0; var45 < this.playerCount; ++var45) { if (var43 != var45 - && this.aBooleanArray2830[var45] - && !this.aSynchronizedBoolArray2831[var45].get() + && this.simulatePlayer[var45] + && !this.onHoleSync[var45].get() && !var15[var45] && !var16[var45] - && this.method147(var43, var45)) { - this.aDoubleArray2828[var43] *= 0.75D; - this.aDoubleArray2829[var43] *= 0.75D; - this.aDoubleArray2828[var45] *= 0.75D; - this.aDoubleArray2829[var45] *= 0.75D; - var24 = 0; + && this.handlePlayerCollisions(var43, var45)) { + this.speedX[var43] *= 0.75D; + this.speedY[var43] *= 0.75D; + this.speedX[var45] *= 0.75D; + this.speedY[var45] *= 0.75D; + allPlayersStoppedCounter = 0; } } } var35 = (int) (this.playerX[var43] + 0.5D); var34 = (int) (this.playerY[var43] + 0.5D); - var33 = isSolidArrayIThink[var35][var34]; - var32 = isSolidArrayIThink[var35][var34 - 6]; - var31 = isSolidArrayIThink[var35 + anInt2799][var34 - anInt2799]; - var30 = isSolidArrayIThink[var35 + 6][var34]; - var29 = isSolidArrayIThink[var35 + anInt2799][var34 + anInt2799]; - var28 = isSolidArrayIThink[var35][var34 + 6]; - var27 = isSolidArrayIThink[var35 - anInt2799][var34 + anInt2799]; - var26 = isSolidArrayIThink[var35 - 6][var34]; - var25 = isSolidArrayIThink[var35 - anInt2799][var34 - anInt2799]; + var33 = collisionMap[var35][var34]; + var32 = collisionMap[var35][var34 - 6]; + var31 = collisionMap[var35 + diagOffset][var34 - diagOffset]; + var30 = collisionMap[var35 + 6][var34]; + var29 = collisionMap[var35 + diagOffset][var34 + diagOffset]; + var28 = collisionMap[var35][var34 + 6]; + var27 = collisionMap[var35 - diagOffset][var34 + diagOffset]; + var26 = collisionMap[var35 - 6][var34]; + var25 = collisionMap[var35 - diagOffset][var34 - diagOffset]; if (var33 != 12 && var33 != 13) { var21 = var33 == 14 || var33 == 15; } else { - this.aDoubleArray2828[var43] *= 0.97D; - this.aDoubleArray2829[var43] *= 0.97D; + this.speedX[var43] *= 0.97D; + this.speedY[var43] *= 0.97D; var21 = true; } @@ -245,7 +244,7 @@ public void run() { || var25 == var46) { ++var45; if (!var17[var43]) { - this.method154((var46 - 32) / 2, var43, var35, var34); + this.handleTeleport((var46 - 32) / 2, var43, var35, var34); var17[var43] = true; } } @@ -256,84 +255,85 @@ public void run() { } if (var33 == 28 || var33 == 30) { - this.method155(var33 == 30, var43, var35, var34); + this.handleMines(var33 == 30, var43, var35, var34); } - this.method152(var43, var32, var31, var30, var29, var28, var27, var26, var25, var35, var34); + this.handleWallCollision( + var43, var32, var31, var30, var29, var28, var27, var26, var25, var35, var34); } - boolean var47 = this.method148(var43, var33); + boolean var47 = this.handleDownhill(var43, var33); boolean var48 = false; - if (this.aShortArrayArrayArray2825 != null && !var21 && !var15[var43] && !var16[var43]) { - var48 = this.method149(var43, var35, var34); + if (this.magnetMap != null && !var21 && !var15[var43] && !var16[var43]) { + var48 = this.handleMagnetForce(var43, var35, var34); } var20 = false; double var49; if (var33 == 25 - || isSolidArrayIThink[var35][var34 - 1] == 25 - || isSolidArrayIThink[var35 + 1][var34] == 25 - || isSolidArrayIThink[var35][var34 + 1] == 25 - || isSolidArrayIThink[var35 - 1][var34] == 25) { + || collisionMap[var35][var34 - 1] == 25 + || collisionMap[var35 + 1][var34] == 25 + || collisionMap[var35][var34 + 1] == 25 + || collisionMap[var35 - 1][var34] == 25) { var49 = var33 == 25 ? 1.0D : 0.5D; var20 = true; int var51 = 0; if (var32 == 25) { ++var51; } else { - this.aDoubleArray2829[var43] += var49 * 0.03D; + this.speedY[var43] += var49 * 0.03D; } if (var31 == 25) { ++var51; } else { - this.aDoubleArray2829[var43] += var49 * 0.03D * aDouble2798; - this.aDoubleArray2828[var43] -= var49 * 0.03D * aDouble2798; + this.speedY[var43] += var49 * 0.03D * magicOffset; + this.speedX[var43] -= var49 * 0.03D * magicOffset; } if (var30 == 25) { ++var51; } else { - this.aDoubleArray2828[var43] -= var49 * 0.03D; + this.speedX[var43] -= var49 * 0.03D; } if (var29 == 25) { ++var51; } else { - this.aDoubleArray2829[var43] -= var49 * 0.03D * aDouble2798; - this.aDoubleArray2828[var43] -= var49 * 0.03D * aDouble2798; + this.speedY[var43] -= var49 * 0.03D * magicOffset; + this.speedX[var43] -= var49 * 0.03D * magicOffset; } if (var28 == 25) { ++var51; } else { - this.aDoubleArray2829[var43] -= var49 * 0.03D; + this.speedY[var43] -= var49 * 0.03D; } if (var27 == 25) { ++var51; } else { - this.aDoubleArray2829[var43] -= var49 * 0.03D * aDouble2798; - this.aDoubleArray2828[var43] += var49 * 0.03D * aDouble2798; + this.speedY[var43] -= var49 * 0.03D * magicOffset; + this.speedX[var43] += var49 * 0.03D * magicOffset; } if (var26 == 25) { ++var51; } else { - this.aDoubleArray2828[var43] += var49 * 0.03D; + this.speedX[var43] += var49 * 0.03D; } if (var25 == 25) { ++var51; } else { - this.aDoubleArray2829[var43] += var49 * 0.03D * aDouble2798; - this.aDoubleArray2828[var43] += var49 * 0.03D * aDouble2798; + this.speedY[var43] += var49 * 0.03D * magicOffset; + this.speedX[var43] += var49 * 0.03D * magicOffset; } if (var51 >= 7) { var20 = false; var15[var43] = true; - this.aDoubleArray2828[var43] = this.aDoubleArray2829[var43] = 0.0D; + this.speedX[var43] = this.speedY[var43] = 0.0D; } } @@ -351,23 +351,23 @@ public void run() { var12[var43] = this.playerY[var43]; } - var36 = Math.sqrt(this.aDoubleArray2828[var43] * this.aDoubleArray2828[var43] - + this.aDoubleArray2829[var43] * this.aDoubleArray2829[var43]); + var36 = Math.sqrt( + this.speedX[var43] * this.speedX[var43] + this.speedY[var43] * this.speedY[var43]); if (var36 > 0.0D) { - double var52 = this.method150(var33, var36); - this.aDoubleArray2828[var43] *= var52; - this.aDoubleArray2829[var43] *= var52; + double var52 = this.calculateFriction(var33, var36); + this.speedX[var43] *= var52; + this.speedY[var43] *= var52; var36 *= var52; if (var36 > 7.0D) { var49 = 7.0D / var36; - this.aDoubleArray2828[var43] *= var49; - this.aDoubleArray2829[var43] *= var49; + this.speedX[var43] *= var49; + this.speedY[var43] *= var49; var36 *= var49; } } if (var5 > 4000) { - this.aDouble2819 = 0.0D; + this.bounciness = 0.0D; if (var5 > 7000) { var48 = false; var47 = false; @@ -394,9 +394,9 @@ public void run() { } if (var36 < 0.075D && !var47 && !var48 && !var20 && !var15[var43] && !var16[var43]) { - this.aDoubleArray2828[var43] = this.aDoubleArray2829[var43] = 0.0D; + this.speedX[var43] = this.speedY[var43] = 0.0D; if (var33 != 12 && var33 != 14 && var33 != 13 && var33 != 15) { - ++var24; + ++allPlayersStoppedCounter; } else { var16[var43] = true; } @@ -407,40 +407,40 @@ public void run() { if (var15[var43] && var10[var43] > 2.1666666666666665D || var16[var43] && var10[var43] > 6.0D) { if (var33 == 25) { - this.aSynchronizedBoolArray2831[var43].set(true); - if (this.aBoolean2832 && this.anInt2809 > 1) { + this.onHoleSync[var43].set(true); + if (this.isLocalPlayer && this.playerCount > 1) { // gameContainer.gamePanel.hideSkipButton(); } } else { if (var33 == 12 || var33 == 14) { - this.playerX[var43] = this.anInt2810 == 0 ? var8[var43] : var11[var43]; - this.playerY[var43] = this.anInt2810 == 0 ? var9[var43] : var12[var43]; + this.playerX[var43] = this.onShoreSetting == 0 ? var8[var43] : var11[var43]; + this.playerY[var43] = this.onShoreSetting == 0 ? var9[var43] : var12[var43]; } if (var33 == 13 || var33 == 15) { - this.method145(var43, false); + this.resetposition(var43, false); } var10[var43] = 0.0D; } var15[var43] = var16[var43] = false; - ++var24; + ++allPlayersStoppedCounter; } } } else { - ++var24; + ++allPlayersStoppedCounter; } } ++var5; - if (var24 >= this.anInt2809) { - var42 = this.anInt2839; + if (allPlayersStoppedCounter >= this.playerCount) { + var42 = this.maxPhysicsIterations; } } - for (var43 = 0; var43 < this.anInt2809; ++var43) { - if (this.aBooleanArray2830[var43]) { + for (var43 = 0; var43 < this.playerCount; ++var43) { + if (this.simulatePlayer[var43]) { int var54 = (int) (var13[var43] - 6.5D + 0.5D); int var55 = (int) (var14[var43] - 6.5D + 0.5D); int var56 = var54 + 13; @@ -448,8 +448,8 @@ public void run() { // var3.drawImage(var2, var54, var55, var56, var57, var54, var55, var56, var57, // this); - for (var44 = 0; var44 < this.anInt2809; ++var44) { - if (this.aBooleanArray2830[var44] && var44 != this.currentPlayerID) { + for (var44 = 0; var44 < this.playerCount; ++var44) { + if (this.simulatePlayer[var44] && var44 != this.currentPlayerID) { // this.method161(var3, var44, var10[var44]); } } @@ -482,13 +482,13 @@ public void run() { Tools.sleep(var58); var38 = (int) ((long) var38 + var58); - } while (var24 < this.anInt2809 && !this.aBoolean2843); + } while (allPlayersStoppedCounter < this.playerCount && !this.strokeInterrupted); - if (this.aBoolean2843) { + if (this.strokeInterrupted) { // this.aThread2842 = null; } else { - this.method164(var38); - this.aSynchronizedBoolArray2831[this.anInt2816].set(false); // FUCKING IMPORTANT OR IT BORKS + this.adjustPhysicsIterations(var38); + this.onHoleSync[this.anInt2816].set(false); // FUCKING IMPORTANT OR IT BORKS // gameContainer.gamePanel.sendEndStroke(this.currentPlayerID, // this.aSynchronizedBoolArray2831, this.anInt2816); @@ -509,7 +509,7 @@ public double[] getHackedCoordintes() { return result; } - private void method154(int var1, int var2, int var3, int var4) { + private void handleTeleport(int var1, int var2, int var3, int var4) { boolean var5 = true; int var6 = this.teleportExits[var1].size(); int var7; @@ -519,7 +519,7 @@ private void method154(int var1, int var2, int var3, int var4) { if (var6 > 0) { var13 = var1; var7 = var6 - 1; - var8 = this.aSeed_2836.next() % (var7 + 1); + var8 = this.seed.next() % (var7 + 1); } else { var7 = this.teleportStarts[var1].size(); int var10; @@ -528,7 +528,7 @@ private void method154(int var1, int var2, int var3, int var4) { do { var10 = var7 - 1; - var8 = this.aSeed_2836.next() % (var10 + 1); + var8 = this.seed.next() % (var10 + 1); var11 = this.teleportStarts[var1].get(var8); if (Math.abs(var11[0] - (double) var3) >= 15.0D || Math.abs(var11[1] - (double) var4) >= 15.0D) { this.playerX[var2] = var11[0]; @@ -555,12 +555,12 @@ private void method154(int var1, int var2, int var3, int var4) { } do { - var13 = this.aSeed_2836.next() % 4; + var13 = this.seed.next() % 4; var6 = this.teleportExits[var13].size(); } while (var6 == 0); int var12 = var6 - 1; - var8 = this.aSeed_2836.next() % (var12 + 1); + var8 = this.seed.next() % (var12 + 1); } var11 = this.teleportExits[var13].get(var8); @@ -568,24 +568,24 @@ private void method154(int var1, int var2, int var3, int var4) { this.playerY[var2] = var11[1]; } - private boolean method147(int var1, int var2) { + private boolean handlePlayerCollisions(int var1, int var2) { double var3 = this.playerX[var2] - this.playerX[var1]; double var5 = this.playerY[var2] - this.playerY[var1]; double var7 = Math.sqrt(var3 * var3 + var5 * var5); if (var7 != 0.0D && var7 <= 13.0D) { double var9 = var3 / var7; double var11 = var5 / var7; - double var13 = this.aDoubleArray2828[var1] * var9 + this.aDoubleArray2829[var1] * var11; - double var15 = this.aDoubleArray2828[var2] * var9 + this.aDoubleArray2829[var2] * var11; + double var13 = this.speedX[var1] * var9 + this.speedY[var1] * var11; + double var15 = this.speedX[var2] * var9 + this.speedY[var2] * var11; if (var13 - var15 <= 0.0D) { return false; } else { - double var17 = -this.aDoubleArray2828[var1] * var11 + this.aDoubleArray2829[var1] * var9; - double var19 = -this.aDoubleArray2828[var2] * var11 + this.aDoubleArray2829[var2] * var9; - this.aDoubleArray2828[var1] = var15 * var9 - var17 * var11; - this.aDoubleArray2829[var1] = var15 * var11 + var17 * var9; - this.aDoubleArray2828[var2] = var13 * var9 - var19 * var11; - this.aDoubleArray2829[var2] = var13 * var11 + var19 * var9; + double var17 = -this.speedX[var1] * var11 + this.speedY[var1] * var9; + double var19 = -this.speedX[var2] * var11 + this.speedY[var2] * var9; + this.speedX[var1] = var15 * var9 - var17 * var11; + this.speedY[var1] = var15 * var11 + var17 * var9; + this.speedX[var2] = var13 * var9 - var19 * var11; + this.speedY[var2] = var13 * var11 + var19 * var9; return true; } } else { @@ -593,7 +593,7 @@ private boolean method147(int var1, int var2) { } } - private void method155(boolean var1, int var2, int var3, int var4) { + private void handleMines(boolean var1, int var2, int var3, int var4) { int var7 = var3 / 15; int var8 = var4 / 15; int var9 = mapTiles[var7][var8] / 16777216; @@ -629,21 +629,20 @@ private void method155(boolean var1, int var2, int var3, int var4) { double var17; do { do { - this.aDoubleArray2828[var2] = (double) (-65 + this.aSeed_2836.next() % 131) / 10.0D; - this.aDoubleArray2829[var2] = (double) (-65 + this.aSeed_2836.next() % 131) / 10.0D; - var17 = Math.sqrt(this.aDoubleArray2828[var2] * this.aDoubleArray2828[var2] - + this.aDoubleArray2829[var2] * this.aDoubleArray2829[var2]); + this.speedX[var2] = (double) (-65 + this.seed.next() % 131) / 10.0D; + this.speedY[var2] = (double) (-65 + this.seed.next() % 131) / 10.0D; + var17 = Math.sqrt(this.speedX[var2] * this.speedX[var2] + this.speedY[var2] * this.speedY[var2]); } while (var17 < 5.2D); } while (var17 > 6.5D); if (!var1) { - this.aDoubleArray2828[var2] *= 0.8D; - this.aDoubleArray2829[var2] *= 0.8D; + this.speedX[var2] *= 0.8D; + this.speedY[var2] *= 0.8D; } } } - private void method152( + private void handleWallCollision( int var1, int var2, int var3, @@ -787,118 +786,117 @@ private void method152( if (!var14 && !var16 && !var18 && !var20) { double var24; if (var15 - && (this.aDoubleArray2828[var1] > 0.0D && this.aDoubleArray2829[var1] < 0.0D - || this.aDoubleArray2828[var1] < 0.0D - && this.aDoubleArray2829[var1] < 0.0D - && -this.aDoubleArray2829[var1] > -this.aDoubleArray2828[var1] - || this.aDoubleArray2828[var1] > 0.0D - && this.aDoubleArray2829[var1] > 0.0D - && this.aDoubleArray2828[var1] > this.aDoubleArray2829[var1])) { - var22 = this.method153(var3, var1, var10 + anInt2799, var11 - anInt2799, 1, -1); - var24 = this.aDoubleArray2828[var1]; - this.aDoubleArray2828[var1] = this.aDoubleArray2829[var1] * var22; - this.aDoubleArray2829[var1] = var24 * var22; + && (this.speedX[var1] > 0.0D && this.speedY[var1] < 0.0D + || this.speedX[var1] < 0.0D + && this.speedY[var1] < 0.0D + && -this.speedY[var1] > -this.speedX[var1] + || this.speedX[var1] > 0.0D + && this.speedY[var1] > 0.0D + && this.speedX[var1] > this.speedY[var1])) { + var22 = this.getSpeedEffect(var3, var1, var10 + diagOffset, var11 - diagOffset, 1, -1); + var24 = this.speedX[var1]; + this.speedX[var1] = this.speedY[var1] * var22; + this.speedY[var1] = var24 * var22; } if (var17 - && (this.aDoubleArray2828[var1] > 0.0D && this.aDoubleArray2829[var1] > 0.0D - || this.aDoubleArray2828[var1] > 0.0D - && this.aDoubleArray2829[var1] < 0.0D - && this.aDoubleArray2828[var1] > -this.aDoubleArray2829[var1] - || this.aDoubleArray2828[var1] < 0.0D - && this.aDoubleArray2829[var1] > 0.0D - && this.aDoubleArray2829[var1] > -this.aDoubleArray2828[var1])) { - var22 = this.method153(var5, var1, var10 + anInt2799, var11 + anInt2799, 1, 1); - var24 = this.aDoubleArray2828[var1]; - this.aDoubleArray2828[var1] = -this.aDoubleArray2829[var1] * var22; - this.aDoubleArray2829[var1] = -var24 * var22; + && (this.speedX[var1] > 0.0D && this.speedY[var1] > 0.0D + || this.speedX[var1] > 0.0D + && this.speedY[var1] < 0.0D + && this.speedX[var1] > -this.speedY[var1] + || this.speedX[var1] < 0.0D + && this.speedY[var1] > 0.0D + && this.speedY[var1] > -this.speedX[var1])) { + var22 = this.getSpeedEffect(var5, var1, var10 + diagOffset, var11 + diagOffset, 1, 1); + var24 = this.speedX[var1]; + this.speedX[var1] = -this.speedY[var1] * var22; + this.speedY[var1] = -var24 * var22; } if (var19 - && (this.aDoubleArray2828[var1] < 0.0D && this.aDoubleArray2829[var1] > 0.0D - || this.aDoubleArray2828[var1] > 0.0D - && this.aDoubleArray2829[var1] > 0.0D - && this.aDoubleArray2829[var1] > this.aDoubleArray2828[var1] - || this.aDoubleArray2828[var1] < 0.0D - && this.aDoubleArray2829[var1] < 0.0D - && -this.aDoubleArray2828[var1] > -this.aDoubleArray2829[var1])) { - var22 = this.method153(var7, var1, var10 - anInt2799, var11 + anInt2799, -1, 1); - var24 = this.aDoubleArray2828[var1]; - this.aDoubleArray2828[var1] = this.aDoubleArray2829[var1] * var22; - this.aDoubleArray2829[var1] = var24 * var22; + && (this.speedX[var1] < 0.0D && this.speedY[var1] > 0.0D + || this.speedX[var1] > 0.0D + && this.speedY[var1] > 0.0D + && this.speedY[var1] > this.speedX[var1] + || this.speedX[var1] < 0.0D + && this.speedY[var1] < 0.0D + && -this.speedX[var1] > -this.speedY[var1])) { + var22 = this.getSpeedEffect(var7, var1, var10 - diagOffset, var11 + diagOffset, -1, 1); + var24 = this.speedX[var1]; + this.speedX[var1] = this.speedY[var1] * var22; + this.speedY[var1] = var24 * var22; } if (var21 - && (this.aDoubleArray2828[var1] < 0.0D && this.aDoubleArray2829[var1] < 0.0D - || this.aDoubleArray2828[var1] < 0.0D - && this.aDoubleArray2829[var1] > 0.0D - && -this.aDoubleArray2828[var1] > this.aDoubleArray2829[var1] - || this.aDoubleArray2828[var1] > 0.0D - && this.aDoubleArray2829[var1] < 0.0D - && -this.aDoubleArray2829[var1] > this.aDoubleArray2828[var1])) { - var22 = this.method153(var9, var1, var10 - anInt2799, var11 - anInt2799, -1, -1); - var24 = this.aDoubleArray2828[var1]; - this.aDoubleArray2828[var1] = -this.aDoubleArray2829[var1] * var22; - this.aDoubleArray2829[var1] = -var24 * var22; + && (this.speedX[var1] < 0.0D && this.speedY[var1] < 0.0D + || this.speedX[var1] < 0.0D + && this.speedY[var1] > 0.0D + && -this.speedX[var1] > this.speedY[var1] + || this.speedX[var1] > 0.0D + && this.speedY[var1] < 0.0D + && -this.speedY[var1] > this.speedX[var1])) { + var22 = this.getSpeedEffect(var9, var1, var10 - diagOffset, var11 - diagOffset, -1, -1); + var24 = this.speedX[var1]; + this.speedX[var1] = -this.speedY[var1] * var22; + this.speedY[var1] = -var24 * var22; } } else { - if (var14 && this.aDoubleArray2829[var1] < 0.0D) { - var22 = this.method153(var2, var1, var10, var11 - 6, 0, -1); - this.aDoubleArray2828[var1] *= var22; - this.aDoubleArray2829[var1] *= -var22; - } else if (var18 && this.aDoubleArray2829[var1] > 0.0D) { - var22 = this.method153(var6, var1, var10, var11 + 6, 0, 1); - this.aDoubleArray2828[var1] *= var22; - this.aDoubleArray2829[var1] *= -var22; + if (var14 && this.speedY[var1] < 0.0D) { + var22 = this.getSpeedEffect(var2, var1, var10, var11 - 6, 0, -1); + this.speedX[var1] *= var22; + this.speedY[var1] *= -var22; + } else if (var18 && this.speedY[var1] > 0.0D) { + var22 = this.getSpeedEffect(var6, var1, var10, var11 + 6, 0, 1); + this.speedX[var1] *= var22; + this.speedY[var1] *= -var22; } - if (var16 && this.aDoubleArray2828[var1] > 0.0D) { - var22 = this.method153(var4, var1, var10 + 6, var11, 1, 0); - this.aDoubleArray2828[var1] *= -var22; - this.aDoubleArray2829[var1] *= var22; + if (var16 && this.speedX[var1] > 0.0D) { + var22 = this.getSpeedEffect(var4, var1, var10 + 6, var11, 1, 0); + this.speedX[var1] *= -var22; + this.speedY[var1] *= var22; return; } - if (var20 && this.aDoubleArray2828[var1] < 0.0D) { - var22 = this.method153(var8, var1, var10 - 6, var11, -1, 0); - this.aDoubleArray2828[var1] *= -var22; - this.aDoubleArray2829[var1] *= var22; + if (var20 && this.speedX[var1] < 0.0D) { + var22 = this.getSpeedEffect(var8, var1, var10 - 6, var11, -1, 0); + this.speedX[var1] *= -var22; + this.speedY[var1] *= var22; return; } } } - private double method153(int var1, int var2, int var3, int var4, int var7, int var8) { + private double getSpeedEffect(int var1, int var2, int var3, int var4, int var7, int var8) { if (var1 == 16) { return 0.81D; } else if (var1 == 17) { return 0.05D; } else if (var1 == 18) { - if (this.aDouble2819 <= 0.0D) { + if (this.bounciness <= 0.0D) { return 0.84D; } else { - this.aDouble2819 -= 0.01D; - double var9 = Math.sqrt(this.aDoubleArray2828[var2] * this.aDoubleArray2828[var2] - + this.aDoubleArray2829[var2] * this.aDoubleArray2829[var2]); - return this.aDouble2819 * 6.5D / var9; + this.bounciness -= 0.01D; + double var9 = Math.sqrt(this.speedX[var2] * this.speedX[var2] + this.speedY[var2] * this.speedY[var2]); + return this.bounciness * 6.5D / var9; } } else if (var1 != 20 && var1 != 21 && var1 != 22 && var1 != 23) { if (var1 != 27 && var1 != 46) { if (var1 != 40 && var1 != 41 && var1 != 42 && var1 != 43) { return 1.0D; } else { - this.method159(var3, var4); + this.handleBreakableBlock(var3, var4); return 0.9D; } } else { - return this.method156(var3, var4, var7, var8, var1 == 27) ? 0.325D : 0.8D; + return this.handleMovableBlock(var3, var4, var7, var8, var1 == 27) ? 0.325D : 0.8D; } } else { return 0.82D; } } - private boolean method156(int var1, int var2, int var5, int var6, boolean var7) { + private boolean handleMovableBlock(int var1, int var2, int var5, int var6, boolean var7) { int var8 = var1 / 15; int var9 = var2 / 15; int var10 = mapTiles[var8][var9] / 16777216; @@ -907,13 +905,13 @@ private boolean method156(int var1, int var2, int var5, int var6, boolean var7) if (var10 == 2 && (var11 == 27 || var11 == 46)) { int var13 = var8 + var5; int var14 = var9 + var6; - int var15 = this.method157(var13, var14); + int var15 = this.canMovableBlockMove(var13, var14); if (var15 == -1) { return false; } else { mapTiles[var8][var9] = 16777216 + var12 * 256; // this.drawTile(var8, var9, var3, var4); - int[] var16 = this.method158(var8, var9, var13, var14, var12, var15, var7, 0); + int[] var16 = this.calculateMovableBlockEndPosition(var8, var9, var13, var14, var12, var15, var7, 0); if (!var7 && (var16[2] == 12 || var16[2] == 13)) { mapTiles[var16[0]][var16[1]] = 35061760 + var16[2] * 256; } else { @@ -928,13 +926,13 @@ private boolean method156(int var1, int var2, int var5, int var6, boolean var7) } } - private int method157(int var1, int var2) { + private int canMovableBlockMove(int var1, int var2) { if (var1 >= 0 && var1 < 49 && var2 >= 0 && var2 < 25) { int var3 = mapTiles[var1][var2] / 16777216; int var4 = mapTiles[var1][var2] / 65536 % 256; int var5 = mapTiles[var1][var2] / 256 % 256; if (var3 == 1 && var4 == 0 && var5 <= 15) { - for (int var6 = 0; var6 < this.anInt2809; ++var6) { + for (int var6 = 0; var6 < this.playerCount; ++var6) { if (this.playerX[var6] > (double) (var1 * 15) && this.playerX[var6] < (double) (var1 * 15 + 15 - 1) && this.playerY[var6] > (double) (var2 * 15) @@ -952,7 +950,8 @@ private int method157(int var1, int var2) { } } - private int[] method158(int var1, int var2, int var3, int var4, int var5, int var6, boolean var9, int var10) { + private int[] calculateMovableBlockEndPosition( + int var1, int var2, int var3, int var4, int var5, int var6, boolean var9, int var10) { int[] var11 = new int[] {var3, var4, var6}; if (!var9 && var6 >= 4 && var6 <= 11 && var10 < 1078) { var1 = var3; @@ -974,16 +973,16 @@ private int[] method158(int var1, int var2, int var3, int var4, int var5, int va --var3; } - var6 = this.method157(var3, var4); + var6 = this.canMovableBlockMove(var3, var4); if (var6 >= 0) { - var11 = this.method158(var1, var2, var3, var4, var5, var6, var9, var10 + 1); + var11 = this.calculateMovableBlockEndPosition(var1, var2, var3, var4, var5, var6, var9, var10 + 1); } } return var11; } - private void method159(int var1, int var2) { + private void handleBreakableBlock(int var1, int var2) { int var5 = var1 / 15; int var6 = var2 / 15; int var7 = mapTiles[var5][var6] / 16777216; @@ -1002,42 +1001,42 @@ private void method159(int var1, int var2) { } } - private boolean method148(int var1, int var2) { + private boolean handleDownhill(int var1, int var2) { if (var2 >= 4 && var2 <= 11) { if (var2 == 4) { - this.aDoubleArray2829[var1] -= 0.025D; + this.speedY[var1] -= 0.025D; } if (var2 == 5) { - this.aDoubleArray2829[var1] -= 0.025D * aDouble2798; - this.aDoubleArray2828[var1] += 0.025D * aDouble2798; + this.speedY[var1] -= 0.025D * magicOffset; + this.speedX[var1] += 0.025D * magicOffset; } if (var2 == 6) { - this.aDoubleArray2828[var1] += 0.025D; + this.speedX[var1] += 0.025D; } if (var2 == 7) { - this.aDoubleArray2829[var1] += 0.025D * aDouble2798; - this.aDoubleArray2828[var1] += 0.025D * aDouble2798; + this.speedY[var1] += 0.025D * magicOffset; + this.speedX[var1] += 0.025D * magicOffset; } if (var2 == 8) { - this.aDoubleArray2829[var1] += 0.025D; + this.speedY[var1] += 0.025D; } if (var2 == 9) { - this.aDoubleArray2829[var1] += 0.025D * aDouble2798; - this.aDoubleArray2828[var1] -= 0.025D * aDouble2798; + this.speedY[var1] += 0.025D * magicOffset; + this.speedX[var1] -= 0.025D * magicOffset; } if (var2 == 10) { - this.aDoubleArray2828[var1] -= 0.025D; + this.speedX[var1] -= 0.025D; } if (var2 == 11) { - this.aDoubleArray2829[var1] -= 0.025D * aDouble2798; - this.aDoubleArray2828[var1] -= 0.025D * aDouble2798; + this.speedY[var1] -= 0.025D * magicOffset; + this.speedX[var1] -= 0.025D * magicOffset; } return true; @@ -1046,32 +1045,32 @@ private boolean method148(int var1, int var2) { } } - private boolean method149(int var1, int var2, int var3) { + private boolean handleMagnetForce(int var1, int var2, int var3) { int var4 = var2 / 5; int var5 = var3 / 5; - short var6 = this.aShortArrayArrayArray2825[var4][var5][0]; - short var7 = this.aShortArrayArrayArray2825[var4][var5][1]; + short var6 = this.magnetMap[var4][var5][0]; + short var7 = this.magnetMap[var4][var5][1]; if (var6 == 0 && var7 == 0) { return false; } else { - if (this.aDouble2820 > 0.0D) { - this.aDouble2820 -= 1.0E-4D; + if (this.somethingSpeedThing > 0.0D) { + this.somethingSpeedThing -= 1.0E-4D; } - this.aDoubleArray2828[var1] += this.aDouble2820 * (double) var6 * 5.0E-4D; - this.aDoubleArray2829[var1] += this.aDouble2820 * (double) var7 * 5.0E-4D; + this.speedX[var1] += this.somethingSpeedThing * (double) var6 * 5.0E-4D; + this.speedY[var1] += this.somethingSpeedThing * (double) var7 * 5.0E-4D; return true; } } - private double method150(int var1, double var2) { - double var4 = this.method151(var1); + private double calculateFriction(int var1, double var2) { + double var4 = this.getFriction(var1); double var6 = 0.75D * var2 / 6.5D; double var8 = 1.0D - var4; return var4 + var8 * var6; } - private double method151(int var1) { + private double getFriction(int var1) { return var1 != 0 && (var1 < 4 || var1 > 11) && var1 != 19 && var1 != 47 ? (var1 == 1 ? 0.92D @@ -1095,15 +1094,15 @@ private double method151(int var1) { : 0.9935D; } - private void method145(int var1, boolean var2) { - if (this.aDoubleArray2821[var1] >= 0.0D && this.aDoubleArray2821[var1] >= 0.0D) { - this.playerX[var1] = this.aDoubleArray2821[var1]; - this.playerY[var1] = this.aDoubleArray2822[var1]; - } else if (this.aDouble2817 >= 0.0D && this.aDouble2818 >= 0.0D) { - this.playerX[var1] = this.aDouble2817; - this.playerY[var1] = this.aDouble2818; + private void resetposition(int var1, boolean var2) { + if (this.resetPositionX[var1] >= 0.0D && this.resetPositionX[var1] >= 0.0D) { + this.playerX[var1] = this.resetPositionX[var1]; + this.playerY[var1] = this.resetPositionY[var1]; + } else if (this.startPositionX >= 0.0D && this.startPositionY >= 0.0D) { + this.playerX[var1] = this.startPositionX; + this.playerY[var1] = this.startPositionY; if (var2) { - this.aBooleanArray2834[var1] = false; + this.playerActive[var1] = false; } } else { @@ -1112,27 +1111,27 @@ private void method145(int var1, boolean var2) { } } - private void method164(int var1) { - anIntArray2837[0] = anIntArray2837[1]; - anIntArray2837[1] = anIntArray2837[2]; - if (anIntArray2837[1] < var1) { - var1 = anIntArray2837[1]; + private void adjustPhysicsIterations(int var1) { + frameTimeHistory[0] = frameTimeHistory[1]; + frameTimeHistory[1] = frameTimeHistory[2]; + if (frameTimeHistory[1] < var1) { + var1 = frameTimeHistory[1]; } - if (anIntArray2837[0] < var1) { - var1 = anIntArray2837[0]; + if (frameTimeHistory[0] < var1) { + var1 = frameTimeHistory[0]; } - while (var1 > 700 && this.anInt2839 > 1) { + while (var1 > 700 && this.maxPhysicsIterations > 1) { var1 -= 700; - --this.anInt2839; + --this.maxPhysicsIterations; } - while (var1 < -2000 && this.anInt2839 < 6) { + while (var1 < -2000 && this.maxPhysicsIterations < 6) { var1 += 2000; - ++this.anInt2839; + ++this.maxPhysicsIterations; } - anIntArray2837[2] = var1; + frameTimeHistory[2] = var1; } } diff --git a/client/src/main/java/agolf/game/Map.java b/client/src/main/java/agolf/game/Map.java new file mode 100644 index 00000000..d37ad61f --- /dev/null +++ b/client/src/main/java/agolf/game/Map.java @@ -0,0 +1,324 @@ +package agolf.game; + +import agolf.SpriteManager; +import java.util.StringTokenizer; + +class Map { + // String mapData; + private static final String mapChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + private byte[][] collisionMap; + private boolean[] latestTileSpeciality; + private Tile[][] tiles; + private int width; + private int height; + private int[][] tileCodeArray; + public int index = 0; + + public Map(int width, int height, String inputData) { + this.width = width; + this.height = height; + this.tiles = new Tile[width][height]; + this.tileCodeArray = new int[width][height]; // To remain compatible with hackedshot + this.parse(inputData); + } + + /* + * The below is the map parsing: + * firstly the input map is "expanded", any letter preceeding by a number is duplicated that number times. + * If input letter is A,B,C, the letter + the next three are concatenated into one int (4 * bytes) + * If input letters are D,E,F,G,H,I, the current tile is exactly the same as an adjacent one so + * one is selected, depending on the input letter. + */ + private void parse(String inputData) { + StringTokenizer subTokenizer = new StringTokenizer(inputData, ","); + String mapData = this.expandMap(subTokenizer.nextToken()); + int cursorIndex = 0; + + int tileX; + for (int tileY = 0; tileY < 25; ++tileY) { + for (tileX = 0; tileX < 49; ++tileX) { + + int currentMapIndex = mapChars.indexOf(mapData.charAt(cursorIndex)); + + if (currentMapIndex <= 2) { // if input= A,B or C + int mapcursor_one_ahead; + int mapcursor_two_ahead; + int mapcursor_three_ahead; + + if (currentMapIndex == 1) { // if input = B. + mapcursor_one_ahead = mapChars.indexOf(mapData.charAt(cursorIndex + 1)); + mapcursor_two_ahead = mapChars.indexOf(mapData.charAt(cursorIndex + 2)); + mapcursor_three_ahead = mapChars.indexOf(mapData.charAt(cursorIndex + 3)); + cursorIndex += 4; + } else { // if input = A or C + mapcursor_one_ahead = mapChars.indexOf(mapData.charAt(cursorIndex + 1)); + mapcursor_two_ahead = mapChars.indexOf(mapData.charAt(cursorIndex + 2)); + mapcursor_three_ahead = 0; + cursorIndex += 3; + } + + // (currentMapIndex << 24) + (mapcursor_one_ahead << 16) + + // (mapcursor_two_ahead << 8) + mapcursor_three_ahead; + int tileCode = currentMapIndex * 256 * 256 * 256 + + mapcursor_one_ahead * 256 * 256 + + mapcursor_two_ahead * 256 + + mapcursor_three_ahead; + this.updateTile(tileX, tileY, tileCode); + this.tileCodeArray[tileX][tileY] = tileCode; + } else { + if (currentMapIndex == 3) { // if input = D + this.updateTile(tileX, tileY, this.tiles[tileX - 1][tileY].getCode()); + // tile to west is same as current + } + + if (currentMapIndex == 4) { // if input = E; + this.updateTile(tileX, tileY, this.tiles[tileX][tileY - 1].getCode()); + // tile to the north is same as current + } + + if (currentMapIndex == 5) { // if input = F; + this.updateTile(tileX, tileY, this.tiles[tileX - 1][tileY - 1].getCode()); + // tile to the northwest is same as + } + + if (currentMapIndex == 6) { // if input = G; + this.updateTile(tileX, tileY, this.tiles[tileX - 2][tileY].getCode()); + // 2 tiles west is same as current (skip a tile to the left) + } + + if (currentMapIndex == 7) { // if input = H + this.updateTile(tileX, tileY, this.tiles[tileX][tileY - 2].getCode()); + // 2 tiles north is same as current (skip the tile above) + } + + if (currentMapIndex == 8) { // if input= I + this.updateTile(tileX, tileY, this.tiles[tileX - 2][tileY - 2].getCode()); + // 2 tiles northwest is same as current (skip the diagonal) + } + + ++cursorIndex; + } + } + } + + if (subTokenizer.hasMoreTokens()) { + mapData = subTokenizer.nextToken(); + if (!mapData.startsWith("Ads:")) { + // Something fishy going on, maybe throw an error + } + // Ads are not used anymore, nothing to parse here. + } + } + + public byte getColMap(int x, int y) { + return this.collisionMap[x][y]; + } + + public byte[][] getColMap() { + return this.collisionMap; + } + + // public void setTile(int x, int y, Tile tile) { + // this.tiles[x][y] = tile; + // } + + public Tile getTile(int x, int y) { + return this.tiles[x][y]; + } + + public int[][] getTileCodeArray() { + return this.tileCodeArray; + } + + public void checkSolids(SpriteManager manager) { + this.latestTileSpeciality = new boolean[2]; + this.latestTileSpeciality[0] = this.latestTileSpeciality[1] = false; + this.collisionMap = new byte[735][375]; + + for (int y = 0; y < 25; ++y) { + for (int x = 0; x < 49; ++x) { + this.collisionMap(x, y, manager); + } + } + } + + public boolean isTeleportStart(int x, int y) { + return x >= 0 && x < this.width && y >= 0 && y < this.height + ? this.getColMap(x, y) == 32 + || this.getColMap(x, y) == 34 + || this.getColMap(x, y) == 36 + || this.getColMap(x, y) == 38 + : false; + } + + public boolean castShadow(int x, int y, boolean[] specialSettings) { + // trackSpecialSettings[3] + // 3:false => illusion walls shadowless 3:true => illusion walls shadows + return x >= 0 && x < this.width && y >= 0 && y < this.height + ? this.getColMap(x, y) >= 16 + && this.getColMap(x, y) <= 23 + && (specialSettings[3] || !specialSettings[3] && this.getColMap(x, y) != 19) + : false; + } + + public void updateTile(int x, int y, int tileCode) { + if (tiles[x][y] == null) { + tiles[x][y] = new Tile(tileCode); + } else { + tiles[x][y].update(tileCode); + } + } + + protected void collisionMap(int tileX, int tileY, SpriteManager manager) { + Tile tile = this.getTile(tileX, tileY); + int special = tile.getSpecial(); + int shape = tile.getShapeReduced(); + int background = tile.getBackground(); + int foreground = tile.getForeground(); + int pixel = Integer.MIN_VALUE; + + if (special == 1 && (background == 19 || foreground == 19)) { // IF HAX BLOCK + this.latestTileSpeciality[0] = true; + } else if (special == 2 && shape == 2) { + this.latestTileSpeciality[1] = true; + } + + int[][] mask = manager.getPixelMask(special, shape); + + for (int y = 0; y < 15; ++y) { + for (int x = 0; x < 15; ++x) { + + if (special == 1) { + pixel = mask[x][y] == 1 ? background : foreground; + + } else if (special == 2) { + shape += 24; + pixel = mask[x][y] == 1 ? background : shape; + // 24 StartPosition + if (shape == 24) { + pixel = background; + } + // 26 Fake Hole + if (shape == 26) { + pixel = background; + } + // Teleport Exits + if (shape == 33 || shape == 35 || shape == 37 || shape == 39) { + pixel = background; + } + + // Bricks + if (shape >= 40 && shape <= 43) { + pixel = shape; + } + + // magnet + if (shape == 44) { + pixel = background != 12 && background != 13 && background != 14 && background != 15 + ? shape + : background; + } + + // magnet repel + if (shape == 45) { + pixel = background; + } + + shape -= 24; + } + + this.collisionMap[tileX * 15 + x][tileY * 15 + y] = (byte) pixel; + } + } + } + + protected boolean[] getLatestTileSpeciality() { + return this.latestTileSpeciality; + } + + private String expandMap(String mapString) { + StringBuffer buffer = new StringBuffer(4900); + int length = mapString.length(); + + for (int var4 = 0; var4 < length; ++var4) { + int var5 = this.readNumber(mapString, var4); + if (var5 >= 2) { + ++var4; + } + + if (var5 >= 10) { + ++var4; + } + + if (var5 >= 100) { + ++var4; + } + + if (var5 >= 1000) { + ++var4; + } + + char var6 = mapString.charAt(var4); + + buffer.append(String.valueOf(var6).repeat(Math.max(0, var5))); + } + + return buffer.toString(); + } + + private int readNumber(String mapStr, int charIdx) { + String result = null; + + while (true) { + char digit = mapStr.charAt(charIdx); + if (digit < '0' || digit > '9') { + return result == null ? 1 : Integer.parseInt(result); + } + + if (result == null) { + result = String.valueOf(digit); + } else { + result = result + digit; + } + + ++charIdx; + } + } + + // Checks whether the tile at position x, y is such, that a movable block can move to it. + // If the block cannot move, returns -1 + // If the block can move, returns the background value for that tile + int canMovableBlockMove(int x, int y, double[] playerX, double[] playerY, int playerCount) { + if (x >= 0 && x < 49 && y >= 0 && y < 25) { + Tile tile = this.getTile(x, y); + int special = tile.getSpecial(); + int shape = tile.getShapeReduced(); + int background = tile.getBackground(); + if (special == 1 && shape == 0 && background <= 15) { + // Check that the tile has no players + for (int i = 0; i < playerCount; ++i) { + if (isPlayerAtPosition(x, y, playerX[i], playerY[i])) { + return -1; + } + } + return background; + } else { + return -1; + } + } else { + return -1; + } + } + + // (x, y) tile coordinates + // (playerX, playerY) pixel coordinates + private boolean isPlayerAtPosition(int x, int y, double playerX, double playerY) { + if (playerX > (double) (x * 15) + && playerX < (double) (x * 15 + 15 - 1) + && playerY > (double) (y * 15) + && playerY < (double) (y * 15 + 15 - 1)) { + return true; + } + return false; + } +} diff --git a/client/src/main/java/agolf/game/Tile.java b/client/src/main/java/agolf/game/Tile.java new file mode 100644 index 00000000..36f46a11 --- /dev/null +++ b/client/src/main/java/agolf/game/Tile.java @@ -0,0 +1,150 @@ +package agolf.game; + +import java.util.UUID; + +class Tile { + private int code; + private int special; + private int shape; + private int background; + private int foreground; + private int shapeReduced; + public UUID uuid; + + public int getSpecialsettingCode(boolean[] trackSettings) { + int currentCode = code; + + if (special == 2) { + // 16777216 == blank tile with grass + // 34144256 == teleport blue exit with grass + // 34078720 == teleport start with grass + + // 0:false => mines invisible 0:true => mines visible + if (!trackSettings[0] && (special == 28 || shape == 30)) { + currentCode = 16777216 + background * 256; + } + + // 1:false => magnets invisible 1:true => magnets visible + if (!trackSettings[1] && (shape == 44 || shape == 45)) { + currentCode = 16777216 + background * 256; + } + + // 2:false => teleport colorless 2:true => normal colors + if (!trackSettings[2]) { + if (shape == 34 || shape == 36 || shape == 38) { + currentCode = 34078720 + background * 256; + } + + if (shape == 35 || shape == 37 || shape == 39) { + currentCode = 34144256 + background * 256; + } + } + } + return currentCode; + } + + public int getSpecial() { + return this.special; + } + + public int getCode() { + return this.code; + } + + public int getShape() { + return this.shape; + } + + public int getForeground() { + return this.foreground; + } + + public int getBackground() { + return this.background; + } + + public int getShapeReduced() { + return this.shapeReduced; + } + + public int getYPixelsFromSpecialId() { + switch (this.shape) { + case 24: + return 16777215; // Starting point common + case 48: + return 11579647; // Start blue + case 49: + return 16752800; // Start red + case 50: + return 16777088; // Start yellow + case 51: + return 9502608; // Start green + default: + return -1; + } + } + + public Tile(int code) { + this.code = code; + this.special = code >> 24; + this.shape = (code >> 16) % 256 + 24; + this.shapeReduced = shape - 24; + this.background = (code >> 8) % 256; + this.foreground = code % 256; + this.uuid = UUID.randomUUID(); + } + + public void printDebug() { + System.out.println("special: " + special); + System.out.println("shape: " + shape); + System.out.println("back: " + background); + System.out.println("uuid: " + uuid); + } + + public void update(int code) { + this.code = code; + this.special = code >> 24; + this.shape = (code >> 16) % 256 + 24; + this.shapeReduced = shape - 24; + this.background = (code >> 8) % 256; + this.foreground = code % 256; + } + + public boolean equals(Tile other) { + if (other == null) { + return false; + } + return this.code == other.getCode(); + } + + public static double calculateFriction(int value, double speed) { + double friction = getFriction(value); + double speedModifier = 0.75D * speed / 6.5D; + double frictionModifier = 1.0D - friction; + return friction + (frictionModifier * speedModifier); + } + + private static double getFriction(int var1) { + return var1 != 0 && (var1 < 4 || var1 > 11) && var1 != 19 && var1 != 47 + ? (var1 == 1 + ? 0.92D + : (var1 == 2 + ? 0.8D + : (var1 != 3 && var1 != 32 && var1 != 34 && var1 != 36 && var1 != 38 + ? (var1 != 12 && var1 != 13 + ? (var1 != 14 && var1 != 15 + ? (var1 >= 20 && var1 <= 23 + ? 0.995D + : (var1 == 25 + ? 0.96D + : (var1 != 28 && var1 != 30 + ? (var1 != 29 && var1 != 31 + ? (var1 == 44 ? 0.9D : 1.0D) + : 0.9D) + : 1.0D))) + : 0.95D) + : 0.0D) + : 0.9975D))) + : 0.9935D; + } +} diff --git a/shared/src/main/java/org/moparforia/shared/tracks/Track.java b/shared/src/main/java/org/moparforia/shared/tracks/Track.java index 2799b923..e7c3b312 100644 --- a/shared/src/main/java/org/moparforia/shared/tracks/Track.java +++ b/shared/src/main/java/org/moparforia/shared/tracks/Track.java @@ -9,13 +9,18 @@ public class Track { private final String track; - private final String author; - private String map; - private Set categories; + // Specialsettings by index + // 0:false => mines invisible 0:true => mines visible + // 1:false => magnets invisible 1:true => magnets visible + // 2:false => teleport colorless 2:true => normal colors + // 3:false => illusion walls shadowless 3:true => illusion walls shadows + private boolean[] specialSettings; + private String settings; + public Track(String name, String author, String map, Set categories) { this.track = name; this.author = author; @@ -23,6 +28,21 @@ public Track(String name, String author, String map, Set categori this.categories = categories; } + public Track( + String name, + String author, + String map, + Set categories, + boolean[] specialSettings, + String settings) { + this.track = name; + this.author = author; + this.map = map; + this.categories = categories; + this.specialSettings = specialSettings; + this.settings = settings; + } + public Track(String track, String author, String map) { this(track, author, map, Collections.emptySet()); } @@ -84,4 +104,12 @@ public String serialize(String splitter) { .collect(Collectors.joining(",")); return Tools.izer(splitter, "V 2", "A " + getAuthor(), "N " + getName(), "T " + getMap(), "C " + categories); } + + public boolean[] getSpecialSettings() { + return this.specialSettings; + } + + public String getSettings() { + return this.settings; + } } diff --git a/shared/src/main/java/org/moparforia/shared/tracks/filesystem/FileSystemTrackStats.java b/shared/src/main/java/org/moparforia/shared/tracks/filesystem/FileSystemTrackStats.java index 0b2ae2d8..9a9dfa87 100644 --- a/shared/src/main/java/org/moparforia/shared/tracks/filesystem/FileSystemTrackStats.java +++ b/shared/src/main/java/org/moparforia/shared/tracks/filesystem/FileSystemTrackStats.java @@ -9,33 +9,39 @@ import org.moparforia.shared.tracks.stats.TrackStats; public class FileSystemTrackStats implements TrackStats { - private final int totalAttempts; + private final int numCompletions; private final int strokes; private final int bestPar; private final double bestParPercentage; public final int numberOfBestPar; private final String bestPlayer; private final LocalDate bestTime; + private final String lastBestPlayer; + private final LocalDate lastBestTime; private final int[] ratings; private Track track; public FileSystemTrackStats( - int totalAttempts, + int numCompletions, int strokes, int bestPar, double percentageofBestPar, int numberOfBestPar, String bestPlayer, LocalDate bestTime, + String lastBestPlayer, + LocalDate lastBestTime, int[] ratings, Track track) { - this.totalAttempts = totalAttempts; + this.numCompletions = numCompletions; this.strokes = strokes; this.bestPar = bestPar; this.bestParPercentage = percentageofBestPar; this.numberOfBestPar = numberOfBestPar; this.bestPlayer = bestPlayer; this.bestTime = bestTime; + this.lastBestPlayer = lastBestPlayer; + this.lastBestTime = lastBestTime; this.ratings = ratings; this.track = track; } @@ -50,8 +56,8 @@ public Track getTrack() { } @Override - public int getTotalAttempts() { - return totalAttempts; + public int getNumCompletions() { + return numCompletions; } @Override @@ -106,7 +112,7 @@ public String serialize(String splitter) { output.append(splitter); output.append(Tools.izer( splitter, - "I " + Tools.commaize(getTotalAttempts(), getTotalStrokes(), getBestPar(), numberOfBestPar), + "I " + Tools.commaize(getNumCompletions(), getTotalStrokes(), getBestPar(), numberOfBestPar), "R " + ratingsToString())); output.append(splitter); if (getBestPar() > 0) { @@ -127,7 +133,7 @@ public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof FileSystemTrackStats)) return false; FileSystemTrackStats that = (FileSystemTrackStats) o; - return getTotalAttempts() == that.getTotalAttempts() + return getNumCompletions() == that.getNumCompletions() && strokes == that.strokes && getBestPar() == that.getBestPar() && Double.compare(that.bestParPercentage, bestParPercentage) == 0 @@ -141,7 +147,7 @@ && getBestPar() == that.getBestPar() @Override public int hashCode() { int result = Objects.hash( - getTotalAttempts(), + getNumCompletions(), strokes, getBestPar(), bestParPercentage, @@ -170,7 +176,7 @@ public String networkSerialize() { "A " + getTrack().getAuthor(), "N " + getTrack().getName(), "T " + getTrack().getMap(), - "I " + Tools.commaize(getTotalAttempts(), getTotalStrokes(), getBestPar(), numberOfBestPar), + "I " + Tools.commaize(getNumCompletions(), getTotalStrokes(), getBestPar(), numberOfBestPar), "R " + ratingsToString()); } return Tools.tabularize( @@ -178,7 +184,7 @@ public String networkSerialize() { "A " + getTrack().getAuthor(), "N " + getTrack().getName(), "T " + getTrack().getMap(), - "I " + Tools.commaize(getTotalAttempts(), getTotalStrokes(), getBestPar(), numberOfBestPar), + "I " + Tools.commaize(getNumCompletions(), getTotalStrokes(), getBestPar(), numberOfBestPar), "B " + Tools.commaize( getBestPlayer(), @@ -187,4 +193,25 @@ public String networkSerialize() { .toEpochMilli()), "R " + ratingsToString()); } + + /** These two methods are required for the frontend and they could be be + * refactored / replaced with something better. But that would require + * non-trivial changes in the client. */ + public String[] generateTrackInformation() { + return new String[] { + track.getAuthor(), + track.getName(), + bestPlayer + "," + + bestTime.atStartOfDay(ZoneId.of("Etc/UTC")).toInstant().toEpochMilli(), + lastBestPlayer + "," + + lastBestTime + .atStartOfDay(ZoneId.of("Etc/UTC")) + .toInstant() + .toEpochMilli() + }; + } + + public int[][] generateTrackStatistics() { + return new int[][] {{numCompletions, strokes, bestPar, numberOfBestPar}, ratings}; + } } diff --git a/shared/src/main/java/org/moparforia/shared/tracks/parsers/GenericTrackParser.java b/shared/src/main/java/org/moparforia/shared/tracks/parsers/GenericTrackParser.java index f5d12a0c..7d277739 100644 --- a/shared/src/main/java/org/moparforia/shared/tracks/parsers/GenericTrackParser.java +++ b/shared/src/main/java/org/moparforia/shared/tracks/parsers/GenericTrackParser.java @@ -21,6 +21,13 @@ public Map parse(Map parser, Path path) t .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); } + public Map parseFromString(Map parser, String data) throws IOException { + return data.lines() + .map(line -> parseLine(parser, line)) + .flatMap(m -> m.entrySet().stream()) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + } + private Map parseLine(Map parsers, String line) { Character character = line.charAt(0); if (parsers.containsKey(character)) { diff --git a/shared/src/main/java/org/moparforia/shared/tracks/parsers/TrackFileParser.java b/shared/src/main/java/org/moparforia/shared/tracks/parsers/TrackFileParser.java index e2fce167..aa4b688c 100644 --- a/shared/src/main/java/org/moparforia/shared/tracks/parsers/TrackFileParser.java +++ b/shared/src/main/java/org/moparforia/shared/tracks/parsers/TrackFileParser.java @@ -41,7 +41,7 @@ public class TrackFileParser extends GenericTrackParser implements TrackParser { tmp_map.put('I', new ScoreInfoLineParser()); tmp_map.put('B', new BestTimeLineParser("bestTime", "bestPlayer")); // Uncomment if you want to also parse lastTime and lastPlayer - // tmp_map.put("L", new BestTimeLineParser("lastTime", "lastPlayer")); + // tmp_map.put("L", new BestTimeLineParser("lastTime", "lastPlayer")); STATS_PARSERS = Collections.unmodifiableMap(tmp_map); } @@ -61,6 +61,8 @@ private Track constructTrack(Map parsed) { return new Track(name, author, data, categories); } + // NOTE! Does not parse lastBestPlayer or lastBestTime, return just bestPlayer + // and bestTime instead. public TrackStats parseStats(Path path) throws IOException { Map parsed = parse(STATS_PARSERS, path); Track track = constructTrack(parsed); @@ -77,6 +79,16 @@ public TrackStats parseStats(Path path) throws IOException { double bestParPercentage = (double) numberOfBestPar / attempts; return new FileSystemTrackStats( - attempts, strokes, bestPar, bestParPercentage, numberOfBestPar, bestPlayer, bestTime, ratings, track); + attempts, + strokes, + bestPar, + bestParPercentage, + numberOfBestPar, + bestPlayer, + bestTime, + bestPlayer, + bestTime, + ratings, + track); } } diff --git a/shared/src/main/java/org/moparforia/shared/tracks/parsers/VersionedTrackFileParser.java b/shared/src/main/java/org/moparforia/shared/tracks/parsers/VersionedTrackFileParser.java index cbdc1983..0cf1c140 100644 --- a/shared/src/main/java/org/moparforia/shared/tracks/parsers/VersionedTrackFileParser.java +++ b/shared/src/main/java/org/moparforia/shared/tracks/parsers/VersionedTrackFileParser.java @@ -37,12 +37,13 @@ public class VersionedTrackFileParser extends GenericTrackParser implements Trac tmp_map.put('N', new SimpleLineParser("name")); tmp_map.put('T', new SimpleLineParser("data")); tmp_map.put('C', new CategoriesLineParser()); + tmp_map.put('S', new SimpleLineParser("settings")); BASE_PARSERS = Collections.unmodifiableMap(tmp_map); tmp_map.put('R', new RatingsLineParser()); tmp_map.put('I', new ScoreInfoLineParser()); tmp_map.put('B', new BestTimeLineParser("bestTime", "bestPlayer")); // Uncomment if you want to also parse lastTime and lastPlayer - // tmp_map.put("L", new BestTimeLineParser("lastTime", "lastPlayer")); + tmp_map.put('L', new BestTimeLineParser("lastTime", "lastPlayer")); STATS_PARSERS = Collections.unmodifiableMap(tmp_map); } @@ -75,7 +76,14 @@ private Track constructTrack(Map parsed) { String author = (String) parsed.get("author"); String data = (String) parsed.get("data"); Set categories = (Set) parsed.get("categories"); - return new Track(name, author, data, categories); + String settings = (String) parsed.get("settings"); + boolean[] trackSpecialSettings = new boolean[4]; + if (settings != null && settings.length() != 6) { + for (int i = 0; i < 4; i++) { + trackSpecialSettings[i] = settings.charAt(i) == 't'; + } + } + return new Track(name, author, data, categories, trackSpecialSettings, settings); } @Override @@ -95,15 +103,77 @@ public TrackStats parseStats(Path path) throws IOException { int attempts = (int) parsed.getOrDefault("attempts", 0); int strokes = (int) parsed.getOrDefault("strokes", 0); int bestPar = (int) parsed.getOrDefault("bestPar", -1); + int numberOfBestPar = (Integer) parsed.getOrDefault("numberOfBestPar", 0); // Widen int primitive type, to support integer division resulting in double + LocalDate bestTime = (LocalDate) parsed.getOrDefault("bestTime", LocalDate.now()); + String bestPlayer = (String) parsed.getOrDefault("bestPlayer", ""); + LocalDate lastBestTime = (LocalDate) parsed.get("lastBestTime"); + String lastBestPlayer = (String) parsed.get("lastBestPlayer"); + + double bestParPercentage = (double) numberOfBestPar / attempts; + + return new FileSystemTrackStats( + attempts, + strokes, + bestPar, + bestParPercentage, + numberOfBestPar, + bestPlayer, + bestTime, + lastBestPlayer, + lastBestTime, + ratings, + track); + } + + public Track parseTrackFromString(String data) throws IOException { + Map parsed = parseFromString(BASE_PARSERS, data); + int version = (int) parsed.getOrDefault("version", 0); + if (version < allowed_version) { + throw new InvalidTrackVersion("Given track has unsupported version " + + version + + ", while this parser requires " + + allowed_version); + } + return constructTrack(parsed); + } + + public TrackStats parseStatsFromString(String data) throws IOException { + Map parsed = parseFromString(STATS_PARSERS, data); + int version = (int) parsed.getOrDefault("version", 0); + if (version < allowed_version) { + throw new InvalidTrackVersion("Given track has unsupported version " + + version + + ", while this parser requires " + + allowed_version); + } + Track track = constructTrack(parsed); + int[] ratings = (int[]) parsed.getOrDefault("ratings", new int[10]); + int attempts = (int) parsed.getOrDefault("attempts", 0); + int strokes = (int) parsed.getOrDefault("strokes", 0); + int bestPar = (int) parsed.getOrDefault("bestPar", -1); int numberOfBestPar = (Integer) parsed.getOrDefault("numberOfBestPar", 0); + + // Widen int primitive type, to support integer division resulting in double LocalDate bestTime = (LocalDate) parsed.getOrDefault("bestTime", LocalDate.now()); String bestPlayer = (String) parsed.getOrDefault("bestPlayer", ""); + LocalDate lastBestTime = (LocalDate) parsed.getOrDefault("lastBestTime", LocalDate.now()); + String lastBestPlayer = (String) parsed.getOrDefault("lastBestPlayer", ""); double bestParPercentage = (double) numberOfBestPar / attempts; return new FileSystemTrackStats( - attempts, strokes, bestPar, bestParPercentage, numberOfBestPar, bestPlayer, bestTime, ratings, track); + attempts, + strokes, + bestPar, + bestParPercentage, + numberOfBestPar, + bestPlayer, + bestTime, + lastBestPlayer, + lastBestTime, + ratings, + track); } } diff --git a/shared/src/main/java/org/moparforia/shared/tracks/stats/TrackStats.java b/shared/src/main/java/org/moparforia/shared/tracks/stats/TrackStats.java index abac8bde..865d6e44 100644 --- a/shared/src/main/java/org/moparforia/shared/tracks/stats/TrackStats.java +++ b/shared/src/main/java/org/moparforia/shared/tracks/stats/TrackStats.java @@ -17,7 +17,7 @@ public interface TrackStats { /** * @return Total number of attempts across all the games */ - int getTotalAttempts(); + int getNumCompletions(); /** * @return Total number of strobes across all the games @@ -71,4 +71,10 @@ public interface TrackStats { /** Converts to format supported by Client */ String networkSerialize(); + + /** Bundles information from Track and TrackStats into array */ + public String[] generateTrackInformation(); + + /** Bundles information about track statistics */ + public int[][] generateTrackStatistics(); } diff --git a/shared/src/test/java/org/moparforia/shared/tracks/filesystem/FileSystemStatsManagerTest.java b/shared/src/test/java/org/moparforia/shared/tracks/filesystem/FileSystemStatsManagerTest.java index 5a13beae..018863f5 100644 --- a/shared/src/test/java/org/moparforia/shared/tracks/filesystem/FileSystemStatsManagerTest.java +++ b/shared/src/test/java/org/moparforia/shared/tracks/filesystem/FileSystemStatsManagerTest.java @@ -42,7 +42,7 @@ void testSimpleLoad() throws IOException, URISyntaxException { TrackStats stats = statsManager.getStats(single); assertEquals("Sprt", stats.getBestPlayer()); - assertEquals(537, stats.getTotalAttempts()); + assertEquals(537, stats.getNumCompletions()); assertEquals(11734, stats.getTotalStrokes()); assertEquals(4, stats.getBestPar()); assertEquals(0.039, stats.getPercentageOfBestPar(), PRECISION); @@ -57,7 +57,7 @@ void testEmptyStats() throws IOException, URISyntaxException { statsManager.load(tracksLocation); TrackStats stats = statsManager.getStats(empty_stats); assertEquals("", stats.getBestPlayer()); - assertEquals(0, stats.getTotalAttempts()); + assertEquals(0, stats.getNumCompletions()); assertEquals(0, stats.getTotalStrokes()); assertEquals(-1, stats.getBestPar()); assertEquals(NaN, stats.getPercentageOfBestPar(), PRECISION);