diff --git a/.gitignore b/.gitignore index d883eb3..61a44a8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /out/ /.ideal/ -final.iml \ No newline at end of file +final.iml +/local \ No newline at end of file diff --git a/src/BufferedImage.java b/src/BufferedImage.java new file mode 100644 index 0000000..7023972 --- /dev/null +++ b/src/BufferedImage.java @@ -0,0 +1,40 @@ +import javax.imageio.ImageIO; +import java.awt.image.ColorModel; +import java.awt.image.IndexColorModel; +import java.awt.image.WritableRaster; +import java.io.*; +import java.util.Hashtable; + +public class BufferedImage extends java.awt.image.BufferedImage implements Serializable { + + public BufferedImage(int width, int height, int imageType) { + super(width, height, imageType); + } + + public BufferedImage(int width, int height, int imageType, IndexColorModel cm) { + super(width, height, imageType, cm); + } + + public BufferedImage(ColorModel cm, WritableRaster raster, boolean isRasterPremultiplied, Hashtable properties) { + super(cm, raster, isRasterPremultiplied, properties); + } + + @Serial + private void writeObject(ObjectOutputStream out) throws IOException { + ImageIO.write(this, "png", out); // png is lossless + } + + @Serial + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + java.awt.image.BufferedImage temporaryImage = ImageIO.read(in); + ColorModel cm = temporaryImage.getColorModel(); + boolean isAlphaPremultiplied = cm.isAlphaPremultiplied(); + WritableRaster raster = temporaryImage.copyData(null); + // TODO: make work + setState(this, new BufferedImage(cm, raster, isAlphaPremultiplied, null)); + } + + private void setState(BufferedImage currentImage, BufferedImage newImage) { + currentImage = newImage; + } +} diff --git a/src/Camera.java b/src/Camera.java index ca5279b..ad5cd5d 100644 --- a/src/Camera.java +++ b/src/Camera.java @@ -1,7 +1,9 @@ +import java.io.Serializable; + //This class controls the x-scrolling aspect for the player //If you look at the players absolute position(Relative to the screen), the players y position changes, but the x position //never actually changes. -public class Camera { +public class Camera implements Serializable { public int x; public Camera(int x){ this.x = x; diff --git a/src/FileManager.java b/src/FileManager.java index 467490c..1a72371 100644 --- a/src/FileManager.java +++ b/src/FileManager.java @@ -1,6 +1,8 @@ //This class allows us to input and output flies useful for //Inputing levels and making save data. import java.io.*; +import java.util.ArrayList; +import java.util.List; import java.util.Scanner; // TODO: close scanner etc after use @@ -24,7 +26,7 @@ public class FileManager { } } - public static Object readObjectFromFile(String fileLocation, String allowedObject) throws IOException, ClassNotFoundException { + public static Object readObjectFromFile(String fileLocation, List allowedObject) throws IOException, ClassNotFoundException { FileInputStream fileStream = new FileInputStream(fileLocation); SafeObjectInputStream objectStream = new SafeObjectInputStream(fileStream, allowedObject); return objectStream.readObject(); @@ -34,5 +36,6 @@ public class FileManager { FileOutputStream fileStream = new FileOutputStream(fileLocation); ObjectOutputStream objectStream = new ObjectOutputStream(fileStream); objectStream.writeObject(o); + System.out.println(o + " " + fileLocation); } } diff --git a/src/GameFrame.java b/src/GameFrame.java index 8fefc50..edb1c18 100644 --- a/src/GameFrame.java +++ b/src/GameFrame.java @@ -5,6 +5,9 @@ Runs the constructor in GamePanel class */ import java.awt.*; import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.Set; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.UnsupportedAudioFileException; @@ -18,11 +21,23 @@ public class GameFrame extends JFrame{ CameraPanel main; public GameFrame(){ + try { + // read previously saved controls + // SafeObjectInputStream was implemented to prevent arbitrary code execution from occurring if the save files were modified + GamePanel.middlewareArray = (ArrayList)FileManager. + readObjectFromFile("local/controls", Arrays.asList("java.util.ArrayList", "Middleware")); + } catch (IOException | ClassNotFoundException | ClassCastException | SecurityException e) { + GamePanel.middlewareArray = new ArrayList(); + } try { main = new CameraPanel(); main.setLayout(new CardLayout()); menu = new MenuPanel(main); - game = new GamePanel(main); //run GamePanel constructor + try { + game = (GamePanel)FileManager.readObjectFromFile("local/game_state", Collections.singletonList("GamePanel")); + } catch (IOException | ClassNotFoundException | ClassCastException | SecurityException e) { + game = new GamePanel(main); //run GamePanel constructor + } settings = new SettingPanel(main); main.add(menu, "menu"); main.add(settings, "settings"); diff --git a/src/GamePanel.java b/src/GamePanel.java index ededaf7..fc38571 100644 --- a/src/GamePanel.java +++ b/src/GamePanel.java @@ -13,12 +13,13 @@ import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; +import java.io.Serializable; import java.util.ArrayList; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.UnsupportedAudioFileException; import javax.swing.*; -public class GamePanel extends JPanel implements Runnable, KeyListener{ +public class GamePanel extends JPanel implements Runnable, KeyListener, Serializable { //dimensions of window public static final int GAME_WIDTH = 1225; @@ -331,6 +332,12 @@ public class GamePanel extends JPanel implements Runnable, KeyListener{ // increment sprite image to be used and keeps it below 12 playerFrame = (playerFrame + 1) % 11; playerFrameCounter -= 5; + // if the player has moved enough to justify a frame change, a new save will also be made + try { + FileManager.writeObjectToFile("local/game_state", this); + } catch (IOException e) { + e.printStackTrace(); + } } } repaint(); diff --git a/src/LevelManager.java b/src/LevelManager.java index 20a5b14..b31c6dc 100644 --- a/src/LevelManager.java +++ b/src/LevelManager.java @@ -32,11 +32,7 @@ public class LevelManager { } try { MapReader.inputMap(filePath); - } catch (IOException | SpriteException e) { - throw new RuntimeException(e); - } catch (UnsupportedAudioFileException e) { - throw new RuntimeException(e); - } catch (LineUnavailableException e) { + } catch (IOException | SpriteException | UnsupportedAudioFileException | LineUnavailableException e) { throw new RuntimeException(e); } //GamePanel.player.reset(); diff --git a/src/Middleware.java b/src/Middleware.java index 3c2f42d..b88aaf8 100644 --- a/src/Middleware.java +++ b/src/Middleware.java @@ -1,9 +1,10 @@ import com.sun.jdi.request.DuplicateRequestException; import java.awt.event.KeyEvent; +import java.io.Serializable; import java.util.ArrayList; -public class Middleware { +public class Middleware implements Serializable { public static ArrayList allOldCode = new ArrayList(); public static ArrayList allNewCode = new ArrayList(); diff --git a/src/SafeObjectInputStream.java b/src/SafeObjectInputStream.java index 3045b32..3230005 100644 --- a/src/SafeObjectInputStream.java +++ b/src/SafeObjectInputStream.java @@ -2,12 +2,14 @@ import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectStreamClass; +import java.util.ArrayList; +import java.util.List; public class SafeObjectInputStream extends ObjectInputStream { - String allowedClass; + List allowedClass; - public SafeObjectInputStream(InputStream in, String allowedClass) throws IOException { + public SafeObjectInputStream(InputStream in, List allowedClass) throws IOException { super(in); this.allowedClass = allowedClass; } @@ -16,8 +18,8 @@ public class SafeObjectInputStream extends ObjectInputStream { // please note that it is still insecure; don't use in sensitive contexts! @Override protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { - if (!desc.getName().equals(allowedClass)) { - throw new SecurityException(); + if (!allowedClass.contains(desc.getName())) { + throw new SecurityException(desc.getName()); } return super.resolveClass(desc); } diff --git a/src/SettingPanel.java b/src/SettingPanel.java index 67ef73f..1edb19d 100644 --- a/src/SettingPanel.java +++ b/src/SettingPanel.java @@ -17,6 +17,7 @@ import java.awt.image.BufferedImage; import java.io.IOException; import java.security.Key; import java.util.ArrayList; +import java.util.Arrays; public class SettingPanel extends MenuPanel { @@ -115,6 +116,13 @@ public class SettingPanel extends MenuPanel { GamePanel.middlewareArray.add(new Middleware(-1, Integer.parseInt(textBoxArray.get(currentBox).id))); // lastKeyCode is set to -1 to prevent endless execution lastKeyCode = -1; + + // save new key bind to file + try { + FileManager.writeObjectToFile("local/controls", GamePanel.middlewareArray); + } catch (IOException e) { + e.printStackTrace(); + } } }