272 lines
7.8 KiB
JavaScript
272 lines
7.8 KiB
JavaScript
/*
|
|
* CookieClickerSync
|
|
* @author Felipe Martin <me@fmartingr.com> @fmartingr
|
|
* 2016
|
|
*/
|
|
|
|
// Add extend function to Object so we can merge associative arrays
|
|
Object.extend = function(destination, source) {
|
|
for (var property in source) {
|
|
if (source.hasOwnProperty(property)) {
|
|
destination[property] = source[property];
|
|
}
|
|
}
|
|
return destination;
|
|
};
|
|
|
|
/*
|
|
* CCCloud main object
|
|
*/
|
|
var CCCloud = {};
|
|
|
|
// Initial configuration variables
|
|
CCCloud.Config = {
|
|
varName: {
|
|
localStorageBackupKey: 'CCCloud.backupSaveString',
|
|
localStorageKey: 'CCCloud.lastSave',
|
|
remoteStorageKey: 'savegame'
|
|
},
|
|
interval: 30 // Default interval to autosync the game
|
|
}
|
|
|
|
/*
|
|
* State machine
|
|
* Useful to store status for the various components of the addon.
|
|
*/
|
|
CCCloud.State = {
|
|
lastSave: { // Empty last save state to initialize states
|
|
time: 0,
|
|
str: ''
|
|
}
|
|
};
|
|
|
|
/*
|
|
* Providers
|
|
*/
|
|
CCCloud.Providers = {};
|
|
|
|
// Firebase
|
|
CCCloud.Providers.Firebase = {};
|
|
CCCloud.Providers.Firebase.init = function() {
|
|
// Init loads the official firebase javascript library
|
|
CCCloud.State._providerLoadFinished = false;
|
|
var script = document.createElement('script');
|
|
script.type = 'text/javascript';
|
|
script.setAttribute('src', 'https://cdn.firebase.com/js/client/2.4.0/firebase.js');
|
|
script.onload = function() {
|
|
CCCloud.State._providerLoadFinished = true;
|
|
CCCloud.State._firebase = new Firebase(CCCloud.Config.providerConf.url);
|
|
};
|
|
document.head.appendChild(script);
|
|
};
|
|
CCCloud.Providers.Firebase._setKey = function(key, value, callback) {
|
|
CCCloud.State._firebase.child(key).set(value, callback);
|
|
};
|
|
CCCloud.Providers.Firebase._getKey = function(key, callback) {
|
|
CCCloud.State._firebase.child(key).once('value', function(result) {
|
|
callback(result.val());
|
|
});
|
|
};
|
|
CCCloud.Providers.Firebase.save = function(data, callback) {
|
|
this._setKey(CCCloud.Config.varName.remoteStorageKey, data, function(error) {
|
|
// TODO handle errors
|
|
if (!error && callback) callback(true);
|
|
})
|
|
};
|
|
CCCloud.Providers.Firebase.load = function(callback) {
|
|
this._getKey(CCCloud.Config.varName.remoteStorageKey, function(result) {
|
|
// TODO handle errors
|
|
callback(result);
|
|
});
|
|
};
|
|
CCCloud.Providers.Firebase.testConfig = function(callback) {
|
|
var $provider = this;
|
|
$provider._setKey('_check', "y", function(error) {
|
|
$provider._getKey('_check', function(result) {
|
|
if (result === "y") callback(true);
|
|
else callback(false);
|
|
})
|
|
});
|
|
};
|
|
|
|
/*
|
|
* Notifications
|
|
*/
|
|
CCCloud.Notifications = {};
|
|
CCCloud.Notifications.notify = function(content) {
|
|
Game.Notify('CookieClicker Sync', content, null, false);
|
|
};
|
|
CCCloud.Notifications.quickNotify = function(content) {
|
|
Game.Notify(content, '', null, true);
|
|
};
|
|
|
|
/*
|
|
* Interval
|
|
* Handles the interval that syncs the save with the provider
|
|
*/
|
|
CCCloud.Interval = {};
|
|
CCCloud.Interval.start = function() {
|
|
if (CCCloud.State._interval) CCCloud.State.stop();
|
|
CCCloud.State._interval = setInterval(function() { CCCloud.Interval.run() }, CCCloud.Config.interval*1000)
|
|
};
|
|
|
|
CCCloud.Interval.stop = function() {
|
|
if (CCCloud.State._interval) clearInterval(CCCloud.State._interval);
|
|
};
|
|
|
|
CCCloud.Interval.run = function() {
|
|
CCCloud.Save.sync();
|
|
CCCloud.Notifications.quickNotify('Save game synced');
|
|
}
|
|
|
|
/*
|
|
* Saves
|
|
*/
|
|
CCCloud.Save = {};
|
|
CCCloud.Save.getForStorage = function(game) {
|
|
return { game: game, time: CCCloud.Utils.getTime() }
|
|
}
|
|
CCCloud.Save.load = function(save) {
|
|
Game.LoadSave(save.game);
|
|
this._setLastSave(save);
|
|
};
|
|
CCCloud.Save._setLastSave = function(save) {
|
|
localStorage.setItem(CCCloud.Config.varName.localStorageKey, JSON.stringify(save));
|
|
}
|
|
CCCloud.Save.get = function() {
|
|
return Game.WriteSave(1);
|
|
};
|
|
CCCloud.Save.sync = function() {
|
|
var save = this.getForStorage(this.get());
|
|
CCCloud.$provider.save(save);
|
|
this._setLastSave(save);
|
|
};
|
|
|
|
/*
|
|
* Utils
|
|
*/
|
|
CCCloud.Utils = {};
|
|
CCCloud.Utils.getTime = function() {
|
|
if (!Date.now) {
|
|
// Fix for old browsers. Probably not needed, but...
|
|
return new Date().getTime();
|
|
} else {
|
|
return Date.now();
|
|
}
|
|
};
|
|
|
|
/*
|
|
* Addon logging helpers
|
|
*/
|
|
CCCloud.Log = {}
|
|
CCCloud.Log._log = function(level, message) {
|
|
if (window.console) console[level](message);
|
|
}
|
|
CCCloud.Log.info = function(message) {
|
|
this._log('info', message);
|
|
}
|
|
CCCloud.Log.error = function(message) {
|
|
this._log('error', message);
|
|
}
|
|
CCCloud.Log.warning = function(message) {
|
|
this._log('warning', message);
|
|
}
|
|
|
|
/*
|
|
* Startup phases
|
|
*/
|
|
CCCloud.init = function() {
|
|
// Load user configuration
|
|
Object.extend(this.Config, Game.CCCloudSaveConfig);
|
|
|
|
// Load provider if configured and present
|
|
if (!this.Config.provider) {
|
|
this.Notifications.notify('Failed to start: Provider not specified.');
|
|
return false;
|
|
}
|
|
|
|
if (!(this.Config.provider in this.Providers)) {
|
|
CCCloud.Notifications.notify('Failed to start: Provider ' + this.Config.provider + ' does not exist.');
|
|
return false;
|
|
}
|
|
|
|
this.$provider = this.Providers[this.Config.provider];
|
|
this.$provider.init();
|
|
|
|
this.State._providerLoadInterval = setInterval(function() {
|
|
// TODO Check iterations and break at some point.
|
|
if (CCCloud.State._providerLoadFinished) {
|
|
clearInterval(CCCloud.State._providerLoadInterval);
|
|
CCCloud.State._providerLoadInterval = null;
|
|
CCCloud.checkStuff();
|
|
}
|
|
}, 500);
|
|
return true;
|
|
};
|
|
|
|
CCCloud.checkStuff = function() {
|
|
// Check provider
|
|
this.Providers[this.Config.provider].testConfig(function(success) {
|
|
if (success) {
|
|
CCCloud.start();
|
|
return true;
|
|
} else {
|
|
CCCloud.Notifications.notify('Failed to start: Check your provider configuration.');
|
|
return false;
|
|
}
|
|
});
|
|
};
|
|
|
|
CCCloud.start = function() {
|
|
// Load current epoch time
|
|
this.State.epoch = this.Utils.getTime();
|
|
|
|
// Load last synced save (if present)
|
|
var lastSave = localStorage.getItem(this.Config.varName.localStorageKey);
|
|
if (lastSave) {
|
|
this.State.lastSynced = JSON.parse(lastSave);
|
|
}
|
|
|
|
// Get provider synced save
|
|
this.$provider.load(function(syncedSave) {
|
|
if (syncedSave && CCCloud.State.lastSynced) {
|
|
// If both local and cloud are available, the newer is used.
|
|
if (syncedSave.time > CCCloud.State.lastSynced.time) {
|
|
CCCloud.Log.info('Cloud file is newer than last local synced save.');
|
|
CCCloud.Save.load(syncedSave);
|
|
} else {
|
|
CCCloud.Log.info('Last local synced save is newer than cloud save.');
|
|
CCCloud.$provider.save(CCCloud.State.lastSynced);
|
|
}
|
|
} else if (syncedSave && !CCCloud.State.lastSynced) {
|
|
// If not local save is present but a cloud is
|
|
CCCloud.Log.info('Last local save not present. Overwriting with cloud save.');
|
|
// Backup current game, just in case!
|
|
localStorage.setItem(CCCloud.Config.varName.localStorageBackupKey, CCCloud.Save.get());
|
|
CCCloud.Save.load(syncedSave);
|
|
} else if (!syncedSave && CCCloud.State.lastSynced) {
|
|
// If not cloud save is present but local is
|
|
// TODO is this clause really needed?
|
|
CCCloud.Log.info('Cloud save not present, using last local synced save.');
|
|
CCCloud.$provider.save(CCCloud.Save.getForStorage(CCCloud.State.lastSynced.game));
|
|
} else {
|
|
// If there's no cloud or local save present
|
|
CCCloud.Log.info('Cloud/Last local synced save not present. Using last game status.');
|
|
// Backup current game, just in case!
|
|
localStorage.setItem(CCCloud.Config.varName.localStorageBackupKey, CCCloud.Save.get());
|
|
CCCloud.Save.sync();
|
|
}
|
|
})
|
|
|
|
// Autosync every Config.timer seconds.
|
|
CCCloud.Interval.start();
|
|
|
|
// Give the player the 'third party' achievement
|
|
Game.Win('Third-party');
|
|
|
|
return true; // Loaded succesfully.
|
|
};
|
|
|
|
// Init mod
|
|
CCCloud.init()
|