commit 1dc8705b861770fe19e09777b7b5015980314a39 Author: Felipe Martín Date: Thu Feb 18 01:33:44 2016 +0100 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ae1dcd8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +# Emacs +*~ \ No newline at end of file diff --git a/CCSync.js b/CCSync.js new file mode 100644 index 0000000..062a3cb --- /dev/null +++ b/CCSync.js @@ -0,0 +1,220 @@ +/* + * CookieClickerSync + * @author Felipe Martin @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; +}; + +// Addon main object +var CCSync = {}; + +// Init config +CCSync.Config = { + varName: { + localStorageKey: 'CCSync.lastSave', + remoteStorageKey: 'savegame' + }, + interval: 30 // Default interval to autosync the game +} + +// Internal mod state +CCSync.State = { + lastSave: { // Empty last save state to initialize states + time: 0, + str: '' + } +}; + +// Init providers +CCSync.Providers = {}; +CCSync.Providers.Firebase = {}; +CCSync.Providers.Firebase.init = function() { + CCSync.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() { + CCSync.State._providerLoadFinished = true; + CCSync.State._firebase = new Firebase(CCSync.Config.providerConf.url); + }; + document.head.appendChild(script); +}; +CCSync.Providers.Firebase._setKey = function(key, value, callback) { + CCSync.State._firebase.child(key).set(value, callback); +}; +CCSync.Providers.Firebase._getKey = function(key, callback) { + CCSync.State._firebase.child(key).once('value', function(result) { + callback(result.val()); + }); +}; +CCSync.Providers.Firebase.save = function(data, callback) { + this._setKey(CCSync.Config.varName.remoteStorageKey, data, function(error) { + // TODO handle errors + if (!error && callback) callback(true); + }) +}; +CCSync.Providers.Firebase.load = function(callback) { + this._getKey(CCSync.Config.varName.remoteStorageKey, function(result) { + // TODO handle errors + callback(result); + }); +}; +CCSync.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 +CCSync.Notifications = {}; +CCSync.Notifications.notify = function(content) { + Game.Notify('CookieClicker Sync', content, null, false); +}; +CCSync.Notifications.quickNotify = function(content) { + Game.Notify(content, '', null, true); +}; + +// Interval +CCSync.Interval = {}; +CCSync.Interval.start = function() { + if (CCSync.State._interval) CCSync.State.stop(); + setInterval(function() { CCSync.Interval.run() }, CCSync.Config.interval*1000) +}; + +CCSync.Interval.stop = function() { + if (CCSync.State._interval) clearInterval(CCSync.State._interval); +}; + +CCSync.Interval.run = function() { + CCSync.Save.sync(); + CCSync.Notifications.quickNotify('Save game synced'); +} + +// Game save +CCSync.Save = {}; +CCSync.Save.getForStorage = function(game) { + return { game: game, time: CCSync.Utils.getTime() } +} +CCSync.Save.load = function(save) { + Game.LoadSave(save.game); + this._setLastSave(save); +}; +CCSync.Save._setLastSave = function(save) { + localStorage.setItem(CCSync.Config.varName.localStorageKey, JSON.stringify(save)); +} +CCSync.Save.get = function() { + return Game.WriteSave(1); +}; +CCSync.Save.sync = function() { + var save = this.getForStorage(this.get()); + console.log(save) + CCSync.$provider.save(save); + this._setLastSave(save); +}; + +// Utils +CCSync.Utils = {}; +CCSync.Utils.getTime = function() { + if (!Date.now) { + // Fix for old browsers. Probably not needed, but... + return new Date().getTime(); + } else { + return Date.now(); + } +}; + +CCSync.init = function() { + // Load user configuration + Object.extend(this.Config, Game.CCSyncConfig); + + // 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)) { + CCSync.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 (CCSync.State._providerLoadFinished) { + clearInterval(CCSync.State._providerLoadInterval); + CCSync.State._providerLoadInterval = null; + CCSync.checkStuff(); + } + }, 500); + return true; +}; + +CCSync.checkStuff = function() { + // Check provider + this.Providers[this.Config.provider].testConfig(function(success) { + if (success) { + CCSync.start(); + return true; + } else { + CCSync.Notifications.notify('Failed to start: Check your provider configuration.'); + return false; + } + }); +}; + +CCSync.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 && CCSync.State.lastSynced) { + if (syncedSave.time > CCSync.State.lastSynced.time) { + console.log('Synced is newer'); + CCSync.Save.load(syncedSave); + } else { + console.log('Local is newer'); + CCSync.$provider.save(CCSync.State.lastSynced); + } + } else if (syncedSave && !CCSync.State.lastSynced) { + console.log('Local not present, using synced'); + CCSync.Save.load(syncedSave); + } else if (!syncedSave && CCSync.State.lastSynced) { + console.log('Synced not present, using local') + CCSync.$provider.save(CCSync.Save.getForStorage(CCSync.State.lastSynced.game)); + } else { + console.log('Synced nor local present') + CCSync.Save.sync(); + } + }) + + // Autosync every Config.timer seconds. + CCSync.Interval.start(); + + return true; // Loaded succesfully. +}; + +// Init mod +CCSync.init(); \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..f425732 --- /dev/null +++ b/README.md @@ -0,0 +1,32 @@ +Cookie Clicker Sync +=================== + +Cookie Clicker add-on to sync your save automatically with a custom provider. + + +## Loading the mod + +Add this code to a bookmark on your browser. + +``` javascript +javascript: (function () { + Game.CCSyncConfig = { + // Read configuration section + }; + Game.LoadMod('http://localhost:8001/CCSync.js'); +}()); +``` + +## Configuration + +... + +## Providers + +### Firebase + +... + +## Disclaimer + +No warranty.