Skip to content

Commit 644f08a

Browse files
committed
- added local storage FS for saved games
1 parent 6695633 commit 644f08a

3 files changed

Lines changed: 161 additions & 2 deletions

File tree

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
// Reusing all MEMFS functionality
2+
// additionaly read data at mount
3+
// and save data at some operations.
4+
// Intended to use only for small files (like game settings),
5+
// because LocalStorage is very limited
6+
// and data saved as text in JSON format.
7+
8+
function LSFS() {
9+
if (LSFS.mount) {
10+
return LSFS;
11+
}
12+
13+
var wrapCreateNode = wrapNode(MEMFS.createNode);
14+
15+
var wrap_node_ops = {
16+
setattr: wrapSave(MEMFS.node_ops.setattr),
17+
mknod: wrapNode(MEMFS.node_ops.mknod),
18+
rename: wrapSave(MEMFS.node_ops.rename),
19+
unlink: wrapSave(MEMFS.node_ops.unlink),
20+
rmdir: wrapSave(MEMFS.node_ops.rmdir),
21+
symlink: wrapNode(MEMFS.node_ops.symlink)
22+
};
23+
24+
var wrap_stream_ops = {
25+
write: wrapSave(MEMFS.stream_ops.write),
26+
msync: wrapSave(MEMFS.stream_ops.msync)
27+
};
28+
29+
var props = [ 'name', 'mode', 'rdev', 'link', 'usedBytes', 'timestamp' ];
30+
31+
LSFS.mount = mount;
32+
33+
return LSFS;
34+
35+
function wrapNode(fn) {
36+
return function() {
37+
var node = fn.apply(null, arguments);
38+
setupNode(node);
39+
return node;
40+
}
41+
}
42+
43+
function wrapSave(fn) {
44+
return function(node) {
45+
var res = fn.apply(null, arguments);
46+
save(node);
47+
return res;
48+
}
49+
}
50+
51+
function setupNode(node) {
52+
var node_ops = {};
53+
for (var op in node.node_ops) {
54+
node_ops[op] = wrap_node_ops[op] || node.node_ops[op];
55+
}
56+
node.node_ops = node_ops;
57+
58+
var stream_ops = {};
59+
for (var op in node.stream_ops) {
60+
stream_ops[op] = wrap_stream_ops[op] || node.stream_ops[op];
61+
}
62+
node.stream_ops = stream_ops;
63+
}
64+
65+
function filter(node) {
66+
var result = {};
67+
for (var key in node) {
68+
if (props.indexOf(key) !== -1) {
69+
result[key] = node[key];
70+
}
71+
}
72+
73+
if (node.contents) {
74+
if (node.contents.length) {
75+
result.contents = Array.apply([], node.contents);
76+
} else {
77+
result.contents = {};
78+
for (var name in node.contents) {
79+
result.contents[name] = filter(node.contents[name]);
80+
}
81+
}
82+
}
83+
84+
return result;
85+
}
86+
87+
function save(node) {
88+
if (node.node) {
89+
node = node.node;
90+
}
91+
92+
var mount = node.mount;
93+
if (!mount || !mount.opts || !mount.opts.key) {
94+
return;
95+
}
96+
97+
try {
98+
localStorage.setItem(mount.opts.key, JSON.stringify(filter(mount.root)));
99+
} catch (err) {}
100+
}
101+
102+
function mount(mount) {
103+
if (!mount.opts || !mount.opts.key) {
104+
return;
105+
}
106+
107+
var data;
108+
try {
109+
data = localStorage.getItem(mount.opts.key);
110+
} catch (err) {}
111+
if (data) {
112+
try {
113+
data = JSON.parse(data);
114+
} catch (err) {}
115+
}
116+
117+
var node = MEMFS.mount(mount);
118+
setupNode(node);
119+
load(node, mount, data);
120+
121+
return node;
122+
}
123+
124+
function load(node, mount, data) {
125+
node.mount = mount;
126+
if (!data) {
127+
return;
128+
}
129+
for (var key in data) {
130+
if (props.indexOf(key) !== -1) {
131+
node[key] = data[key];
132+
}
133+
}
134+
if (data.contents) {
135+
if (data.contents.length) {
136+
node.contents = data.contents;
137+
} else {
138+
node.contents = {};
139+
for (var name in data.contents) {
140+
var childData = data.contents[name];
141+
var childNode = wrapCreateNode(node, name, childData.mode, childData.rdev);
142+
load(childNode, mount, childData);
143+
}
144+
}
145+
}
146+
}
147+
}

src_rebuild/platform/Emscripten/shell.html

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
<link rel="stylesheet" href="style.css">
88
<link href="https://fonts.googleapis.com/css?family=Oswald&display=swap" rel="stylesheet">
99
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
10-
1110
<style>
1211
.emscripten {
1312
padding-right: 0;
@@ -173,10 +172,21 @@
173172
Module.setStatus(left ? 'Preparing... (' + (this.totalDependencies - left) + '/' + this.totalDependencies + ')' : 'All downloads complete.');
174173
}
175174
};
175+
176176
Module.setStatus('Downloading...');
177177

178+
// don't immediately run the game
178179
Module['noInitialRun'] = true
179180

181+
// for save data
182+
Module.preRun.push(function() {
183+
ENV.HOME = "/userstorage";
184+
185+
// create LSFS and mount 'data' local storage item into '/data' directory
186+
FS.mkdir('/userstorage'); // for old versions use: FS.createFolder(FS.root, 'data', true, true);
187+
FS.mount(LSFS(), { key: 'userstorage' }, '/userstorage');
188+
})
189+
180190
window.onerror = function () {
181191
Module.setStatus('Exception thrown, see JavaScript console');
182192
spinnerElement.style.display = 'none';
@@ -202,6 +212,7 @@
202212
callMain(["-ini", "demo_config.ini"]);
203213
}
204214
</script>
215+
<script src="lsfs.js"></script>
205216
{{{ SCRIPT }}}
206217
</body>
207218
</html>

src_rebuild/premake5.lua

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ workspace "REDRIVER2"
7676
targetextension ".html"
7777

7878
postbuildcommands {
79-
"{COPY} " .. WEBSHELL_PATH .. "/style.css %{cfg.buildtarget.directory}"
79+
"{COPY} " .. WEBSHELL_PATH .. "/style.css %{cfg.buildtarget.directory}",
80+
"{COPY} " .. WEBSHELL_PATH .. "/lsfs.js %{cfg.buildtarget.directory}"
8081
}
8182

8283
else

0 commit comments

Comments
 (0)