package org.erikaredmark.monkeyshines.global;
import java.awt.event.KeyEvent;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.erikaredmark.monkeyshines.KeyBindings;
import org.erikaredmark.util.BinaryLocation;
/**
*
* Internal package class that, if possible (not required) will commit any preference changes made by the player
* to a file in the same folder as the binary, in addition to loading the preferences file for setting the initial
* values for the global static *Settings objects.
* <p/>
* This class is automatically initialised when a global preference object requests it's default preferences
* on its initialisation.
* <p/>
* Preferences include all persistent data and may not be contained within the same file, but multiple files according
* to use.
*
* @author Erika Redmark
*
*/
public final class MonkeyShinesPreferences {
private static final String CLASS_NAME = "org.erikaredmark.monkeyshines.global.MonkeyShinesPreferences";
private static final Logger LOGGER = Logger.getLogger(CLASS_NAME);
private static final Path PREFERENCES_EXPECTED = BinaryLocation.BINARY_LOCATION.getParent().resolve("monkeyshines.pref");
private static final Path HIGH_SCORES_EXPECTED = BinaryLocation.BINARY_LOCATION.getParent().resolve("ms_high_scores.txt");
private static final Properties PREF_INTERNAL = new Properties();
// Preference defaults if a new preferences file must be created.
private static final KeyBindings DEFAULT_BINDINGS = new KeyBindings(KeyEvent.VK_LEFT, KeyEvent.VK_RIGHT, KeyEvent.VK_UP);
private static final int DEFAULT_MUSIC_VOLUME = 60;
private static final int DEFAULT_SOUND_VOLUME = 100;
private static final boolean DEFAULT_FULLSCREEN_MODE = false;
// Names for each binding.
private static final String KEY_BINDING_LEFT = "keyleft";
private static final String KEY_BINDING_RIGHT = "keyright";
private static final String KEY_BINDING_JUMP = "keyjump";
private static final String SOUND_VOLUME = "sound";
private static final String MUSIC_VOLUME = "music";
private static final String FULLSCREEN = "fullscreen";
private static final String PLAYTEST = "thunderbird";
static {
boolean preferencesFileAvailable = true;
if (!(Files.exists(PREFERENCES_EXPECTED) ) ) {
try {
Files.createFile(PREFERENCES_EXPECTED);
} catch (IOException e) {
LOGGER.log(Level.WARNING,
"Preferences cannot be saved for this game session, nor can high scores! Unable to create preferences file: " + e.getMessage(),
e);
preferencesFileAvailable = false;
}
}
if (preferencesFileAvailable) {
try (InputStream inStream = Files.newInputStream(PREFERENCES_EXPECTED) ) {
PREF_INTERNAL.load(inStream);
// If the file was just created or the game program logic has changed and added more values,
// put defaults in for them now.
if (!(PREF_INTERNAL.containsKey(KEY_BINDING_LEFT) ) ) {
PREF_INTERNAL.setProperty(KEY_BINDING_LEFT, String.valueOf(DEFAULT_BINDINGS.left) );
}
if (!(PREF_INTERNAL.containsKey(KEY_BINDING_RIGHT) ) ) {
PREF_INTERNAL.setProperty(KEY_BINDING_RIGHT, String.valueOf(DEFAULT_BINDINGS.right) );
}
if (!(PREF_INTERNAL.containsKey(KEY_BINDING_JUMP) ) ) {
PREF_INTERNAL.setProperty(KEY_BINDING_JUMP, String.valueOf(DEFAULT_BINDINGS.jump) );
}
if (!(PREF_INTERNAL.containsKey(SOUND_VOLUME) ) ) {
PREF_INTERNAL.setProperty(SOUND_VOLUME, String.valueOf(DEFAULT_SOUND_VOLUME) );
}
if (!(PREF_INTERNAL.containsKey(MUSIC_VOLUME) ) ) {
PREF_INTERNAL.setProperty(MUSIC_VOLUME, String.valueOf(DEFAULT_MUSIC_VOLUME) );
}
if (!(PREF_INTERNAL.containsKey(FULLSCREEN) ) ) {
PREF_INTERNAL.setProperty(FULLSCREEN, String.valueOf(DEFAULT_FULLSCREEN_MODE) );
}
if (!(PREF_INTERNAL.containsKey(PLAYTEST) ) ) {
PREF_INTERNAL.setProperty(PLAYTEST, "false");
}
} catch (IOException e) {
LOGGER.log(Level.WARNING,
"Preferences cannot be saved for this game session, nor can high scores! Unable to load preferences file: possible preference corruption: " + e.getMessage(),
e);
}
}
}
/**
*
* Returns the path to the expected preferences file. This file is NOT guaranteed to exist. Clients
* should make no attempt to create it themselves.
*
* @return
* location the preferences file is expected to be
*
*/
public static Path getPreferencesPath() { return PREFERENCES_EXPECTED; }
/**
*
* Returns the path to the expected high scores file. The file is not guaranteed to exist.
*
* @return
*
*/
public static Path getHighScoresPath() { return HIGH_SCORES_EXPECTED; }
/**
*
* In order for other objects to store (such as highscores) if they have a reference to a properties file
* that is a preferences file, they must use the same comments.
*
* @return
* comments for the {@code store} method in {@code Properties}
*
*/
public static String getPreferencesComments() { return "Monkey Shines Preferences File"; }
static int defaultSoundVolume() { return Integer.valueOf(PREF_INTERNAL.getProperty(SOUND_VOLUME) ); }
static int defaultMusicVolume() { return Integer.valueOf(PREF_INTERNAL.getProperty(MUSIC_VOLUME) ); }
static boolean defaultFullscreen() { return Boolean.valueOf(PREF_INTERNAL.getProperty(FULLSCREEN) ); }
static boolean defaultThunderbird() { return Boolean.valueOf(PREF_INTERNAL.getProperty(PLAYTEST) ); }
static KeyBindings defaultKeyBindings() {
return new KeyBindings(Integer.valueOf(PREF_INTERNAL.getProperty(KEY_BINDING_LEFT) ),
Integer.valueOf(PREF_INTERNAL.getProperty(KEY_BINDING_RIGHT) ),
Integer.valueOf(PREF_INTERNAL.getProperty(KEY_BINDING_JUMP) ) );
}
private static void save() throws PreferencePersistException {
try (OutputStream out = Files.newOutputStream(PREFERENCES_EXPECTED) ) {
PREF_INTERNAL.store(out, getPreferencesComments() );
} catch (IOException e) {
throw new PreferencePersistException(e.getMessage(), e);
}
}
static void persistKeyBindings() throws PreferencePersistException {
PREF_INTERNAL.setProperty(KEY_BINDING_LEFT, String.valueOf(KeySettings.getBindings().left) );
PREF_INTERNAL.setProperty(KEY_BINDING_RIGHT, String.valueOf(KeySettings.getBindings().right) );
PREF_INTERNAL.setProperty(KEY_BINDING_JUMP, String.valueOf(KeySettings.getBindings().jump) );
save();
}
static void persistSound() throws PreferencePersistException {
PREF_INTERNAL.setProperty(SOUND_VOLUME, String.valueOf(SoundSettings.getSoundVolumePercent() ) );
PREF_INTERNAL.setProperty(MUSIC_VOLUME, String.valueOf(SoundSettings.getMusicVolumePercent() ) );
save();
}
static void persistVideo() throws PreferencePersistException {
PREF_INTERNAL.setProperty(FULLSCREEN, String.valueOf(VideoSettings.isFullscreen() ) );
save();
}
static void persistThunderbird() throws PreferencePersistException {
PREF_INTERNAL.setProperty(PLAYTEST, String.valueOf(SpecialSettings.isThunderbird() ) );
save();
}
}