/** * */ package net.puppygames.applet; import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.nio.ByteBuffer; import org.lwjgl.BufferUtils; /** * The GameOutputStream is a replacement for the use of {@link FileOutputStream}. It will use the Steam cloud to or the local * filesystem dependent on whether Steam is present, etc. */ public class GameOutputStream extends OutputStream { /** Buffer size for Steam writes */ private static final int BUFFER_SIZE = 256 * 1024; /** The file path, relative to the game's storage dir */ private final String file; /** Append or overwrite */ private final boolean append; /** Using Steam? */ private final boolean usingSteam; /** Buffer for Steam... */ private final ByteArrayOutputStream baos; /** ...or FileOutputStream for local */ private final OutputStream fos; /** Shadows either output stream */ private final OutputStream os; /** Have we been flushed? */ private boolean flushed; /** Have we been closed? */ private boolean closed; /** * C'tor * @param file */ public GameOutputStream(String file) throws IOException { this(file, false); } /** * C'tor * @param file * @param append */ public GameOutputStream(String file, boolean append) throws IOException { this.file = file; this.append = append; usingSteam = Game.isUsingSteamCloud(); if (usingSteam) { baos = new ByteArrayOutputStream(BUFFER_SIZE); fos = null; os = baos; // If appending, read the original file in if (append) { readExisting(); } } else { baos = null; fos = new BufferedOutputStream(new FileOutputStream(file)); os = fos; } } private void readExisting() throws IOException { GameInputStream gis = new GameInputStream(file); byte[] buf = new byte[BUFFER_SIZE]; int ret; do { ret = gis.read(buf, 0, BUFFER_SIZE); if (ret != -1) { baos.write(buf, 0, ret); } } while (ret != -1); gis.close(); if (Game.DEBUG) { System.out.println("Successfully read existing file "+file+" from cloud"); } } @Override public void write(int b) throws IOException { os.write(b); } @Override public void write(byte[] b) throws IOException { os.write(b); } @Override public void write(byte[] b, int off, int len) throws IOException { os.write(b, off, len); } @Override public void flush() throws IOException { if (usingSteam) { // Ignore } else { os.flush(); } flushed = true; } private void doSteamFlush() throws IOException { ByteBuffer byteBuffer = BufferUtils.createByteBuffer(baos.size()); byteBuffer.put(baos.toByteArray()); byteBuffer.flip(); baos.reset(); } @Override public void close() throws IOException { if (closed) { return; } closed = true; try { if (!flushed) { flush(); } if (usingSteam) { doSteamFlush(); } } finally { os.close(); } } }