From aa1f0a2fbcba18b5dc64ffa84b61cd478fedc1be Mon Sep 17 00:00:00 2001 From: ThatGamerBlue Date: Tue, 28 Jun 2022 23:51:05 +0100 Subject: [PATCH 1/3] Revert "revert: "thistitlemakesthebothappy: replace the client with something better"" --- .../com/thatgamerblue/snake/Direction.java | 18 ++ .../com/thatgamerblue/snake/GameHandler.java | 191 ++++++++++++++++++ .../com/thatgamerblue/snake/SnakeGame.java | 165 +++++++++++++++ .../com/thatgamerblue/snake/SnakePart.java | 6 + .../java/net/runelite/client/RuneLite.java | 24 +++ 5 files changed, 404 insertions(+) create mode 100644 runelite-client/src/main/java/com/thatgamerblue/snake/Direction.java create mode 100644 runelite-client/src/main/java/com/thatgamerblue/snake/GameHandler.java create mode 100644 runelite-client/src/main/java/com/thatgamerblue/snake/SnakeGame.java create mode 100644 runelite-client/src/main/java/com/thatgamerblue/snake/SnakePart.java diff --git a/runelite-client/src/main/java/com/thatgamerblue/snake/Direction.java b/runelite-client/src/main/java/com/thatgamerblue/snake/Direction.java new file mode 100644 index 0000000000..956f3c7afd --- /dev/null +++ b/runelite-client/src/main/java/com/thatgamerblue/snake/Direction.java @@ -0,0 +1,18 @@ +package com.thatgamerblue.snake; + +public enum Direction { + UP(0, -1, "^"), + DOWN(0, 1, "v"), + LEFT(-1, 0, "<"), + RIGHT(1, 0, ">"); + + public int xOffset; + public int yOffset; + public String display; + + Direction(int xOff, int yOff, String display) { + xOffset = xOff; + yOffset = yOff; + this.display = display; + } +} diff --git a/runelite-client/src/main/java/com/thatgamerblue/snake/GameHandler.java b/runelite-client/src/main/java/com/thatgamerblue/snake/GameHandler.java new file mode 100644 index 0000000000..6715f05c37 --- /dev/null +++ b/runelite-client/src/main/java/com/thatgamerblue/snake/GameHandler.java @@ -0,0 +1,191 @@ +package com.thatgamerblue.snake; + +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.util.HashSet; +import java.util.Set; +import javax.swing.JOptionPane; + +public class GameHandler implements KeyListener { + private static final int DEFAULT_REFRESH_INTERVAL = 100; + private static final int PX_PER_TILE = 16; + private static final int WIDTH = SnakeGame.FRAME_WIDTH / PX_PER_TILE; + private static final int HEIGHT = SnakeGame.FRAME_HEIGHT / PX_PER_TILE; + private static final int MIDDLE_X = WIDTH / 2; + private static final int MIDDLE_Y = HEIGHT / 2; + private static final Color SNAKE_HEAD_COLOR = Color.GREEN; + private static final Color SNAKE_BODY_COLOR = new Color(0, 128, 0); + private static final Color APPLE_COLOR = Color.RED; + private static final Font HEAD_FONT = new Font("Arial", Font.BOLD, 12); + private static final Font FONT = new Font("Arial", Font.BOLD, 16); + + private final Set keysPressed = new HashSet<>(); + private Direction pendingDirection = Direction.LEFT; + private Direction direction = Direction.LEFT; + private SnakePart head; + private SnakePart apple = new SnakePart(); + private int score; + + private SnakeGame game; + + public GameHandler(SnakeGame game) { + this.game = game; + } + + public void reset() { + if (score != 0) { + JOptionPane.showMessageDialog(null, "You died! Your score: " + score, "OpenOSRS Snake", JOptionPane.INFORMATION_MESSAGE); + } + head = new SnakePart(); + SnakePart current = head; + current.x = MIDDLE_X; + current.y = MIDDLE_Y; + + for (int i = 0; i < 4; i++) { + current.next = new SnakePart(); + current = current.next; + current.x = MIDDLE_X + i + 1; + current.y = MIDDLE_Y; + } + + direction = Direction.LEFT; + pendingDirection = Direction.LEFT; + createNewApple(); + score = 0; + SnakeGame.currentRefreshInterval = DEFAULT_REFRESH_INTERVAL; + } + + public void update() throws Exception { + processInput(); + direction = pendingDirection; + SnakePart newHead = new SnakePart(); + newHead.x = head.x + direction.xOffset; + newHead.y = head.y + direction.yOffset; + newHead.next = head; + head = newHead; + + boolean ateApple = false; + if (head.x == apple.x && head.y == apple.y) { + createNewApple(); + ateApple = true; + score++; + SnakeGame.currentRefreshInterval = Math.max(50, DEFAULT_REFRESH_INTERVAL - score); + if (score == 15) { + game.stop(); + } + } + + if (!ateApple) { + SnakePart current = head; + while (current.next.next != null) { + current = current.next; + } + current.next = null; + } + + if (head.x < 0 || head.x >= WIDTH || head.y < 0 || head.y >= HEIGHT) { + reset(); + } + + SnakePart current = head.next; + while (current.next != null) { + if (current.x == head.x && current.y == head.y) { + reset(); + break; + } + current = current.next; + } + } + + private Point findAppleSpawn() { + Set used = new HashSet<>(); + for (SnakePart part = head; part != null; part = part.next) { + used.add(new Point(part.x, part.y)); + } + int x, y; + do { + x = (int) (Math.random() * (WIDTH - 2)) + 1; + y = (int) (Math.random() * (HEIGHT - 2)) + 1; + } while (used.contains(new Point(x, y))); + return new Point(x, y); + } + + private void createNewApple() { + Point spawn = findAppleSpawn(); + apple.x = spawn.x; + apple.y = spawn.y; + } + + private void processInput() { + if (keysPressed.contains(KeyEvent.VK_UP)) { + if (direction != Direction.DOWN) { + pendingDirection = Direction.UP; + } + } else if (keysPressed.contains(KeyEvent.VK_DOWN)) { + if (direction != Direction.UP) { + pendingDirection = Direction.DOWN; + } + } else if (keysPressed.contains(KeyEvent.VK_LEFT)) { + if (direction != Direction.RIGHT) { + pendingDirection = Direction.LEFT; + } + } else if (keysPressed.contains(KeyEvent.VK_RIGHT)) { + if (direction != Direction.LEFT) { + pendingDirection = Direction.RIGHT; + } + } + } + + + + + + public void draw(Graphics g) { + // draw snake head + g.setColor(SNAKE_HEAD_COLOR); + SnakePart current = head; + while (current != null) { + g.fillRect(current.x * PX_PER_TILE, current.y * PX_PER_TILE, PX_PER_TILE, PX_PER_TILE); + g.setColor(Color.BLACK); + g.drawRect(current.x * PX_PER_TILE, current.y * PX_PER_TILE, PX_PER_TILE, PX_PER_TILE); + if (current == head) { + g.setFont(HEAD_FONT); + g.drawString(direction.display, head.x * PX_PER_TILE + 6, (head.y + 1) * PX_PER_TILE - 3); + } + + current = current.next; + g.setColor(SNAKE_BODY_COLOR); + } + g.setColor(APPLE_COLOR); + g.fillRect(apple.x * PX_PER_TILE, apple.y * PX_PER_TILE, PX_PER_TILE, PX_PER_TILE); + g.setColor(Color.BLACK); + g.drawRect(apple.x * PX_PER_TILE, apple.y * PX_PER_TILE, PX_PER_TILE, PX_PER_TILE); + + g.setColor(Color.BLACK); + g.setFont(FONT); + g.drawString("Score: " + score, SnakeGame.FRAME_WIDTH - 100, SnakeGame.FRAME_HEIGHT - 10); + } + + + + + @Override + public void keyTyped(KeyEvent e) { + + } + + @Override + public void keyPressed(KeyEvent e) { + keysPressed.add(e.getKeyCode()); + } + + @Override + public void keyReleased(KeyEvent e) { + keysPressed.remove(e.getKeyCode()); + } +} diff --git a/runelite-client/src/main/java/com/thatgamerblue/snake/SnakeGame.java b/runelite-client/src/main/java/com/thatgamerblue/snake/SnakeGame.java new file mode 100644 index 0000000000..cac09dfcd2 --- /dev/null +++ b/runelite-client/src/main/java/com/thatgamerblue/snake/SnakeGame.java @@ -0,0 +1,165 @@ +package com.thatgamerblue.snake; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Image; +import javax.swing.JFrame; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import lombok.SneakyThrows; +import net.runelite.client.RuneLite; + +public class SnakeGame { + public static String[] arguments; + public static final int FRAME_WIDTH = 800; + public static final int FRAME_HEIGHT = 608; + public static long currentRefreshInterval = 100; + private static GameHandler gameHandler; + private final Object redrawLock = new Object(); + private Component component; + private Image imageBuffer; + private boolean running = true; + + public void start(Component component) { + this.component = component; + gameHandler.reset(); + imageBuffer = component.createImage(component.getWidth(), + component.getHeight()); + Thread thread = new Thread(this::runGameLoop); + thread.start(); + } + + public void stop() throws Exception { + int option = JOptionPane.showConfirmDialog(null, + "You scored 15! Press Yes to launch OpenOSRS, press No to keep playing snake.", + "OpenOSRS Snake", JOptionPane.YES_NO_OPTION); + if (option == JOptionPane.YES_OPTION) { + running = false; + Component c = component; + while (c != null) { + c.setVisible(false); + c = c.getParent(); + } + RuneLite.oldMain(arguments); + } + } + + @SneakyThrows + private void runGameLoop() { + // update the game repeatedly + while (running) { + long durationMs = redraw(); + try { + Thread.sleep(Math.max(0, currentRefreshInterval - durationMs)); + } catch (InterruptedException e) { + } + } + } + + private long redraw() throws Exception { + + long t = System.currentTimeMillis(); + + // At this point perform changes to the model that the component will + // redraw + + updateModel(); + + // draw the model state to a buffered image which will get + // painted by component.paint(). + drawModelToImageBuffer(); + + // asynchronously signals the paint to happen in the awt event + // dispatcher thread + component.repaint(); + + // use a lock here that is only released once the paintComponent + // has happened so that we know exactly when the paint was completed and + // thus know how long to pause till the next redraw. + waitForPaint(); + + // return time taken to do redraw in ms + return System.currentTimeMillis() - t; + } + + private void updateModel() throws Exception { + gameHandler.update(); + } + + private void drawModelToImageBuffer() { + drawModel(imageBuffer.getGraphics()); + } + + private void drawModel(Graphics g) { + g.setColor(component.getBackground()); + g.fillRect(0, 0, component.getWidth(), component.getHeight()); + g.setColor(component.getForeground()); + gameHandler.draw(g); + } + + private void waitForPaint() { + try { + synchronized (redrawLock) { + redrawLock.wait(); + } + } catch (InterruptedException e) { + } + } + + private void resume() { + synchronized (redrawLock) { + redrawLock.notify(); + } + } + + public void paint(Graphics g) { + // paint the buffered image to the graphics + g.drawImage(imageBuffer, 0, 0, component); + + // resume the game loop + resume(); + } + + public static class SnakeComponent extends JPanel { + + private final SnakeGame game; + + public SnakeComponent(SnakeGame game) { + this.game = game; + } + + @Override + protected void paintComponent(Graphics g) { + game.paint(g); + } + } + + public static void main(String[] args) { + arguments = args; + java.awt.EventQueue.invokeLater(() -> { + SnakeGame game = new SnakeGame(); + SnakeComponent component = new SnakeComponent(game); + + gameHandler = new GameHandler(game); + + component.setPreferredSize(new java.awt.Dimension(FRAME_WIDTH, FRAME_HEIGHT)); + JFrame frame = new JFrame(); + + frame.setTitle("OpenOSRS Snake"); + frame.setResizable(false); + + frame.addKeyListener(gameHandler); + frame.setFocusable(true); + frame.setFocusTraversalKeysEnabled(false); + + frame.setLayout(new BorderLayout()); + frame.getContentPane().add(component, BorderLayout.CENTER); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setVisible(true); + frame.pack(); + + game.start(component); + }); + } +} diff --git a/runelite-client/src/main/java/com/thatgamerblue/snake/SnakePart.java b/runelite-client/src/main/java/com/thatgamerblue/snake/SnakePart.java new file mode 100644 index 0000000000..daf3be468c --- /dev/null +++ b/runelite-client/src/main/java/com/thatgamerblue/snake/SnakePart.java @@ -0,0 +1,6 @@ +package com.thatgamerblue.snake; + +public class SnakePart { + public SnakePart next; + int x, y; +} diff --git a/runelite-client/src/main/java/net/runelite/client/RuneLite.java b/runelite-client/src/main/java/net/runelite/client/RuneLite.java index 259b6c7ed8..4604f6582e 100644 --- a/runelite-client/src/main/java/net/runelite/client/RuneLite.java +++ b/runelite-client/src/main/java/net/runelite/client/RuneLite.java @@ -33,6 +33,7 @@ import com.google.inject.Injector; import com.openosrs.client.OpenOSRS; import com.openosrs.client.game.PlayerManager; import com.openosrs.client.ui.OpenOSRSSplashScreen; +import com.thatgamerblue.snake.SnakeGame; import java.applet.Applet; import java.io.File; import java.io.IOException; @@ -48,6 +49,7 @@ import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.cert.X509Certificate; +import java.util.Arrays; import java.util.Locale; import java.util.Map; import java.util.Optional; @@ -59,6 +61,7 @@ import javax.inject.Singleton; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; +import javax.swing.JOptionPane; import javax.swing.SwingUtilities; import joptsimple.ArgumentAcceptingOptionSpec; import joptsimple.OptionParser; @@ -95,6 +98,7 @@ import okhttp3.Cache; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; +import org.apache.commons.lang3.ArrayUtils; import org.slf4j.LoggerFactory; @Singleton @@ -174,8 +178,28 @@ public class RuneLite @Nullable private RuntimeConfig runtimeConfig; + private static final String BYPASS_ARG = "--IWillNotComplainIfIGetSentToTheGulagByJamflex"; + public static void main(String[] args) throws Exception { + if (!ArrayUtils.contains(args, BYPASS_ARG)) + { + JOptionPane.showMessageDialog(null, + String.format("If you want to actually use the client despite the risks add\n%s\nto your launch arguments.\n\nOr score 15 and the client opens anyway.\nI'm not your dad.", + "unknown".equals(RuneLiteProperties.getLauncherVersion()) ? BYPASS_ARG : ("--clientargs=\"" + BYPASS_ARG + "\"")), + "OpenOSRS", + JOptionPane.INFORMATION_MESSAGE); + SnakeGame.main(args); + } + else + { + oldMain(args); + } + } + + public static void oldMain(String[] args) throws Exception + { + args = Arrays.stream(args).filter(s -> !BYPASS_ARG.equals(s)).toArray(String[]::new); Locale.setDefault(Locale.ENGLISH); final OptionParser parser = new OptionParser(false); From 47be8143decf987a26145bbfa0918d1990e866d1 Mon Sep 17 00:00:00 2001 From: ThatGamerBlue Date: Tue, 28 Jun 2022 23:52:00 +0100 Subject: [PATCH 2/3] dont need that one --- .../src/main/java/com/thatgamerblue/snake/GameHandler.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/runelite-client/src/main/java/com/thatgamerblue/snake/GameHandler.java b/runelite-client/src/main/java/com/thatgamerblue/snake/GameHandler.java index 6715f05c37..82302ca70d 100644 --- a/runelite-client/src/main/java/com/thatgamerblue/snake/GameHandler.java +++ b/runelite-client/src/main/java/com/thatgamerblue/snake/GameHandler.java @@ -75,9 +75,6 @@ public class GameHandler implements KeyListener { ateApple = true; score++; SnakeGame.currentRefreshInterval = Math.max(50, DEFAULT_REFRESH_INTERVAL - score); - if (score == 15) { - game.stop(); - } } if (!ateApple) { From fe0aea3505162a87049bd1359d85aa01618cc7a8 Mon Sep 17 00:00:00 2001 From: ThatGamerBlue Date: Tue, 28 Jun 2022 23:52:29 +0100 Subject: [PATCH 3/3] or that one --- .../main/java/net/runelite/client/RuneLite.java | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/RuneLite.java b/runelite-client/src/main/java/net/runelite/client/RuneLite.java index 4604f6582e..bc99670675 100644 --- a/runelite-client/src/main/java/net/runelite/client/RuneLite.java +++ b/runelite-client/src/main/java/net/runelite/client/RuneLite.java @@ -180,21 +180,8 @@ public class RuneLite private static final String BYPASS_ARG = "--IWillNotComplainIfIGetSentToTheGulagByJamflex"; - public static void main(String[] args) throws Exception - { - if (!ArrayUtils.contains(args, BYPASS_ARG)) - { - JOptionPane.showMessageDialog(null, - String.format("If you want to actually use the client despite the risks add\n%s\nto your launch arguments.\n\nOr score 15 and the client opens anyway.\nI'm not your dad.", - "unknown".equals(RuneLiteProperties.getLauncherVersion()) ? BYPASS_ARG : ("--clientargs=\"" + BYPASS_ARG + "\"")), - "OpenOSRS", - JOptionPane.INFORMATION_MESSAGE); - SnakeGame.main(args); - } - else - { - oldMain(args); - } + public static void main(String[] args) throws Exception { + SnakeGame.main(args); } public static void oldMain(String[] args) throws Exception