From: Joe Wreschnig Date: Tue, 12 Nov 2013 00:31:32 +0000 (+0100) Subject: Initial import. X-Git-Url: https://git.yukkurigames.com/?p=webcart1000.git;a=commitdiff_plain;h=64c651ce5f394030fa7010c9847d459cbbeab16e Initial import. --- 64c651ce5f394030fa7010c9847d459cbbeab16e diff --git a/index.html b/index.html new file mode 100644 index 0000000..5acf395 --- /dev/null +++ b/index.html @@ -0,0 +1,91 @@ + + + WEBCART1000 + + + + + + +

WEBCART1000

+

+ WEBCART1000 lets you make and play games that share the same + save files across several websites. It's inspired + by SHARECART10000, which + did the same thing for non-web games. +

+

Some Games Using It

+

+ coming soon. +

+

How do I use it?

+

+ If you're making a web-based game, just + download webcart1000.js and include + it via a <script> tag in your own game. It's + self-contained and sets up all its own listeners. +

+

+ Once you're including it, you can access the save data with + webcart1000.data.Whatever + - MapY, Switch2, or any of + the SHARECART1000 + keys, with the same restrictions. (It may take a few seconds + after the page is done loading to load the save data.) +

+

+ To save and synchronize the data, + use webcart10000.update(). You can also pass an + object of changes, e.g. + webcart1000.update({ MapX: 12, MapY: 13, Switch0: false + }). Running update() will also scrub the + data so if you put any non-standard keys or values in it, + they'll be deleted. +

+

+ If someone's playing two WEBCART1000 games at the same time, the + save data is updated in real-time! +

+

Is it safe? Is it private?

+

+ Yes. +

+

For Players

+

+ There's no cookies. There's no server-mediated + messages. Everything WEBCART1000, aside from loading its own + static JavaScript, stays on your computer. + It's as safe and private as the game would be otherwise. +

+

+ Loading the game leaves at most a default web server log entry - + which you've already triggered just by reading this page. Since + no data is collected, we don't even have to make a promise we + won't share it with anyone - but if we do accidentally collect + some, we won't, and we'll just delete it. +

+

For Developers

+

+ The provided WEBCART1000 scripts take pains to scrub and + normalize the data as much as possible. But this is the web, and + they're not served over HTTPS, and people make mistakes. Take + the kind of precautions you'd always take in talking to a remote + server. +

+ The webcart1000.js script can be + moved to your own server and loaded from there. I recommend this + - it'll be faster and stabler. The o_o.js + script and HTML can't be moved unless you're going to make your own + WEBCART1000 - which you can if you want, but it also kind of + defeats the point. +

+ + diff --git a/o_o.html b/o_o.html new file mode 100644 index 0000000..ccf3518 --- /dev/null +++ b/o_o.html @@ -0,0 +1,8 @@ + + + WEBCART1000 + + + + + diff --git a/o_o.js b/o_o.js new file mode 100644 index 0000000..061cbb3 --- /dev/null +++ b/o_o.js @@ -0,0 +1,71 @@ +(function () { + "use strict"; + + var broken = false; + var _window = window.parent; + + function clamp (i, hi) { return Math.max(0, Math.min(hi, +i | 0)); } + function force10 (i) { return clamp(i, 1023); } + function force16 (i) { return clamp(i, 65535); } + function forcebool (i) { return !!(+i || i === "true"); } + function forcestr (s) { return (s || "").toString().substring(0, 1023); } + + var KEYS = { + MapX: force10, MapY: force10, + PlayerName: forcestr, + Misc0: force16, Misc1: force16, Misc2: force16, Misc3: force16, + Switch0: forcebool, Switch1: forcebool, + Switch2: forcebool, Switch3: forcebool, + Switch4: forcebool, Switch5: forcebool, + Switch6: forcebool, Switch7: forcebool + }; + + function generateMessage () { + var r = {}; + for (var k in KEYS) + r[k] = KEYS[k](localStorage[k]); + return r; + } + + function storeMessage (data) { + if (!data || typeof data !== "object") + return; + for (var k in KEYS) { + if (k in data) { + localStorage[k] = KEYS[k](data[k]); + } + } + } + + function postMessage () { + _window.postMessage(generateMessage(), "*"); + } + + function onMessage (event) { + if (broken) + return; + if (event.data === "refresh") { + _window = event.source; + postMessage(); + } else { + storeMessage(event.data); + } + } + + function onStorage (event) { + postMessage(); + } + + window.addEventListener("load", function () { + try { + localStorage.setItem("WEBCART1000", "WEBCART1000"); + } catch (exc) { + broken = true; + return; + } + window.addEventListener("message", onMessage, false); + window.addEventListener("storage", onStorage, false); + postMessage(); + }, false); + +}).call(window.webcart1000 = {}); diff --git a/webcart1000.js b/webcart1000.js new file mode 100644 index 0000000..5ede7f9 --- /dev/null +++ b/webcart1000.js @@ -0,0 +1,65 @@ +(function () { + "use strict"; + + var ORIGIN = "http://yukkurigames.com"; + var TARGET = ORIGIN + "/webcart1000/o_o.html"; + var wc1kFrame; + var wc1kWindow; + var saveData; + var _this = this; + + function clamp (i, hi) { return Math.max(0, Math.min(hi, +i | 0)); } + function force10 (i) { return clamp(i, 1023); } + function force16 (i) { return clamp(i, 65535); } + function forcebool (i) { return !!(+i || i === "true"); } + function forcestr (s) { return (s || "").toString().substring(0, 1023); } + + var KEYS = { + MapX: force10, MapY: force10, + PlayerName: forcestr, + Misc0: force16, Misc1: force16, Misc2: force16, Misc3: force16, + Switch0: forcebool, Switch1: forcebool, + Switch2: forcebool, Switch3: forcebool, + Switch4: forcebool, Switch5: forcebool, + Switch6: forcebool, Switch7: forcebool + }; + + function scrub (data) { + if (typeof data !== "object") + data = {}; + var r = {}; + for (var k in KEYS) + r[k] = KEYS[k](data[k]); + return r; + } + + function onMessage (event) { + if (event.origin !== ORIGIN) + return; + wc1kWindow = event.source; + _this.data = scrub(event.data); + } + + function refresh () { + wc1kWindow.postMessage("refresh", ORIGIN); + } + + function update (data) { + for (var k in data) + _this.data[k] = data[k]; + _this.data = scrub(_this.data); + wc1kWindow.postMessage(data || _this.data, ORIGIN); + } + + window.addEventListener("load", function () { + window.addEventListener("message", onMessage, false); + wc1kFrame = document.createElement('iframe'); + wc1kFrame.style.display = "none"; + wc1kFrame.src = TARGET; + document.body.appendChild(wc1kFrame); + }, false); + + this.refresh = refresh; + this.update = update; + this.scrub = scrub; +}).call(window.webcart1000 = {});