Various persistent state things

master
John 2022-06-14 14:54:55 -04:00
parent be648a8f3f
commit b0ccf9697b
10 changed files with 90 additions and 15 deletions

3
.gitignore vendored
View File

@ -1,3 +1,4 @@
/out/ /out/
/.ideal/ /.ideal/
final.iml final.iml
/local

40
src/BufferedImage.java Normal file
View File

@ -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;
}
}

View File

@ -1,7 +1,9 @@
import java.io.Serializable;
//This class controls the x-scrolling aspect for the player //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 //If you look at the players absolute position(Relative to the screen), the players y position changes, but the x position
//never actually changes. //never actually changes.
public class Camera { public class Camera implements Serializable {
public int x; public int x;
public Camera(int x){ public Camera(int x){
this.x = x; this.x = x;

View File

@ -1,6 +1,8 @@
//This class allows us to input and output flies useful for //This class allows us to input and output flies useful for
//Inputing levels and making save data. //Inputing levels and making save data.
import java.io.*; import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner; import java.util.Scanner;
// TODO: close scanner etc after use // 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<String> allowedObject) throws IOException, ClassNotFoundException {
FileInputStream fileStream = new FileInputStream(fileLocation); FileInputStream fileStream = new FileInputStream(fileLocation);
SafeObjectInputStream objectStream = new SafeObjectInputStream(fileStream, allowedObject); SafeObjectInputStream objectStream = new SafeObjectInputStream(fileStream, allowedObject);
return objectStream.readObject(); return objectStream.readObject();
@ -34,5 +36,6 @@ public class FileManager {
FileOutputStream fileStream = new FileOutputStream(fileLocation); FileOutputStream fileStream = new FileOutputStream(fileLocation);
ObjectOutputStream objectStream = new ObjectOutputStream(fileStream); ObjectOutputStream objectStream = new ObjectOutputStream(fileStream);
objectStream.writeObject(o); objectStream.writeObject(o);
System.out.println(o + " " + fileLocation);
} }
} }

View File

@ -5,6 +5,9 @@ Runs the constructor in GamePanel class
*/ */
import java.awt.*; import java.awt.*;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Set; import java.util.Set;
import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException; import javax.sound.sampled.UnsupportedAudioFileException;
@ -18,11 +21,23 @@ public class GameFrame extends JFrame{
CameraPanel main; CameraPanel main;
public GameFrame(){ 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<Middleware>)FileManager.
readObjectFromFile("local/controls", Arrays.asList("java.util.ArrayList", "Middleware"));
} catch (IOException | ClassNotFoundException | ClassCastException | SecurityException e) {
GamePanel.middlewareArray = new ArrayList<Middleware>();
}
try { try {
main = new CameraPanel(); main = new CameraPanel();
main.setLayout(new CardLayout()); main.setLayout(new CardLayout());
menu = new MenuPanel(main); 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); settings = new SettingPanel(main);
main.add(menu, "menu"); main.add(menu, "menu");
main.add(settings, "settings"); main.add(settings, "settings");

View File

@ -13,12 +13,13 @@ import java.awt.image.BufferedImage;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException; import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.*; import javax.swing.*;
public class GamePanel extends JPanel implements Runnable, KeyListener{ public class GamePanel extends JPanel implements Runnable, KeyListener, Serializable {
//dimensions of window //dimensions of window
public static final int GAME_WIDTH = 1225; 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 // increment sprite image to be used and keeps it below 12
playerFrame = (playerFrame + 1) % 11; playerFrame = (playerFrame + 1) % 11;
playerFrameCounter -= 5; 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(); repaint();

View File

@ -32,11 +32,7 @@ public class LevelManager {
} }
try { try {
MapReader.inputMap(filePath); MapReader.inputMap(filePath);
} catch (IOException | SpriteException e) { } catch (IOException | SpriteException | UnsupportedAudioFileException | LineUnavailableException e) {
throw new RuntimeException(e);
} catch (UnsupportedAudioFileException e) {
throw new RuntimeException(e);
} catch (LineUnavailableException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
//GamePanel.player.reset(); //GamePanel.player.reset();

View File

@ -1,9 +1,10 @@
import com.sun.jdi.request.DuplicateRequestException; import com.sun.jdi.request.DuplicateRequestException;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
public class Middleware { public class Middleware implements Serializable {
public static ArrayList<Integer> allOldCode = new ArrayList<Integer>(); public static ArrayList<Integer> allOldCode = new ArrayList<Integer>();
public static ArrayList<Integer> allNewCode = new ArrayList<Integer>(); public static ArrayList<Integer> allNewCode = new ArrayList<Integer>();

View File

@ -2,12 +2,14 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.ObjectInputStream; import java.io.ObjectInputStream;
import java.io.ObjectStreamClass; import java.io.ObjectStreamClass;
import java.util.ArrayList;
import java.util.List;
public class SafeObjectInputStream extends ObjectInputStream { public class SafeObjectInputStream extends ObjectInputStream {
String allowedClass; List<String> allowedClass;
public SafeObjectInputStream(InputStream in, String allowedClass) throws IOException { public SafeObjectInputStream(InputStream in, List<String> allowedClass) throws IOException {
super(in); super(in);
this.allowedClass = allowedClass; 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! // please note that it is still insecure; don't use in sensitive contexts!
@Override @Override
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
if (!desc.getName().equals(allowedClass)) { if (!allowedClass.contains(desc.getName())) {
throw new SecurityException(); throw new SecurityException(desc.getName());
} }
return super.resolveClass(desc); return super.resolveClass(desc);
} }

View File

@ -17,6 +17,7 @@ import java.awt.image.BufferedImage;
import java.io.IOException; import java.io.IOException;
import java.security.Key; import java.security.Key;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
public class SettingPanel extends MenuPanel { 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))); GamePanel.middlewareArray.add(new Middleware(-1, Integer.parseInt(textBoxArray.get(currentBox).id)));
// lastKeyCode is set to -1 to prevent endless execution // lastKeyCode is set to -1 to prevent endless execution
lastKeyCode = -1; lastKeyCode = -1;
// save new key bind to file
try {
FileManager.writeObjectToFile("local/controls", GamePanel.middlewareArray);
} catch (IOException e) {
e.printStackTrace();
}
} }
} }