]> git.lizzy.rs Git - dragonblocks.git/blob - engine/mainmenu.js
Add Map Manager
[dragonblocks.git] / engine / mainmenu.js
1 /*
2  * mainmenu.js
3  *
4  * Copyright 2020 Elias Fleckenstein <eliasfleckenstein@web.de>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19  * MA 02110-1301, USA.
20  *
21  *
22  */
23
24 {
25         document.title = dragonblocks.version.string;
26
27         let mainmenu = document.body.insertBefore(document.createElement("div"), document.body.firstChild);
28         mainmenu.style.visibility = "hidden";
29
30         let center = mainmenu.appendChild(document.createElement("center"));
31
32         let logo = center.appendChild(document.createElement("img"));
33         logo.src = "textures/logo-mainmenu.png";
34
35         let splash = mainmenu.appendChild(document.createElement("div"));
36         splash.style.position = "fixed";
37         splash.style.overflow = "hidden";
38         splash.style.whiteSpace = "nowrap";
39         splash.style.transform = "rotate(-15deg)";
40         splash.style.color = "yellow";
41         splash.style.fontSize = "30px";
42
43         let status = center.appendChild(document.createElement("h1"));
44         status.style.fontSize = "50px";
45         status.style.display = "none";
46
47         let content = center.appendChild(document.createElement("div"));
48         content.id = "dragonblocks.mainmenu.content";
49         content.style.position = "relative";
50         content.style.top = "50px";
51
52         let buttons = [];
53         let onReload = [];
54
55         let clearChildren = parent => {
56                 while (elem = parent.firstChild)
57                         elem.remove();
58         };
59
60         let worlds;
61
62         // Load World Button
63
64         {
65                 let loadWorldGUI, worldlistDisplay, noWorldsNotice;
66
67                 let worldProperties = new dragonblocks.World.Properties(true);
68
69                 if (dragonblocks.loggedin) {
70                         onReload.push(_ => {
71                                 if (loadWorldGUI) {
72                                         clearChildren(worldlistDisplay);
73                                 } else {
74                                         loadWorldGUI = new dragonblocks.gui.Box();
75
76                                         let headline = loadWorldGUI.create("h1");
77                                         headline.innerHTML = "Select World";
78                                         headline.align = "center";
79
80                                         noWorldsNotice = loadWorldGUI.create("center").appendChild(document.createElement("b"));
81
82                                         worldlistDisplay = loadWorldGUI.create("ul");
83                                 }
84
85                                 noWorldsNotice.innerHTML = worlds.length == 0 ? "No Worlds" : "";
86
87                                 for (let worldname in worlds) {
88                                         let world = worlds[worldname];
89
90                                         if (world.owned) {
91                                                 let worldDisplay = worldlistDisplay.appendChild(document.createElement("li"));
92                                                 worldDisplay.style.fontSize = "20px";
93                                                 worldDisplay.textContent = world.name;
94                                                 worldDisplay.style.postion = "relative";
95
96                                                 let button = worldDisplay.appendChild(document.createElement("button"));
97                                                 button.textContent = "Play";
98                                                 button.style.position = "absolute";
99                                                 button.style.right = "5px";
100                                                 button.style.fontSize = "12px";
101                                                 button.addEventListener("click", event => {
102                                                         event.srcElement.blur();
103                                                         loadWorldGUI.close();
104
105                                                         worldProperties.name = world.name;
106                                                         dragonblocks.start(worldProperties);
107                                                 });
108                                         }
109                                 }
110                         });
111                 }
112
113                 buttons.push({
114                         text: "Load Saved World",
115                         action: _ => {
116                                 loadWorldGUI.open()
117                         },
118                         disabled: ! dragonblocks.loggedin,
119                 })
120         }
121
122         // Create World Button
123
124         {
125                 let createWorldGUI = new dragonblocks.gui.Box();
126                 let createButton;
127
128                 let worldProperties = new dragonblocks.World.Properties(false);
129
130                 let headline = createWorldGUI.create("h1");
131                 headline.innerHTML = "New World";
132                 headline.align = "center";
133
134                 // Worldname
135                 createWorldGUI.create("h2").innerHTML = "&ensp;World Name";
136
137                 let worldnameInput = createWorldGUI.create("input");
138                 worldnameInput.type = "text";
139                 worldnameInput.style.position = "relative";
140                 worldnameInput.style.left = "40px";
141
142                 let worldnameAlert = createWorldGUI.create("b");
143                 worldnameAlert.style.position = "relative";
144                 worldnameAlert.style.left = "50px";
145
146                 worldnameInput.addEventListener("input", _ => {
147                         worldProperties.name = worldnameInput.value;
148
149                         if (! dragonblocks.loggedin) {
150                                 worldnameAlert.textContent = "Warning: You are not logged in and cannot save worlds.";
151                                 worldnameAlert.style.color = "#FF7D00";
152                                 createButton.disabled = false;
153                         } else if (worldProperties.name == "") {
154                                 worldnameAlert.textContent = "";
155                                 createButton.disabled = true;
156                         } else if (! worldProperties.checkSpelling()) {
157                                 worldnameAlert.textContent = "The world name contains forbidden characters";
158                                 worldnameAlert.style.color = "#FF001F";
159                                 createButton.disabled = true;
160                         } else if (worlds[worldProperties.name]) {
161                                 if (worlds[worldProperties.name].owned) {
162                                         worldnameAlert.textContent = "Warning: This will overwrite an existing world";
163                                         worldnameAlert.style.color = "#FF7D00";
164                                         createButton.disabled = false;
165                                 } else {
166                                         worldnameAlert.textContent = "This Worldname is taken";
167                                         worldnameAlert.style.color = "#FF001F";
168                                         createButton.disabled = true;
169                                 }
170                         } else {
171                                 worldnameAlert.textContent = "";
172                                 createButton.disabled = false;
173                         }
174                 });
175
176                 // Mods
177                 createWorldGUI.create("h2").innerHTML = "&ensp;Mods";
178
179                 let modlistDisplay = createWorldGUI.create("ul");
180
181                 let updateModlist = _ => {
182                         clearChildren(modlistDisplay);
183
184                         let oldSelectedMods = worldProperties.mods;
185                         worldProperties.mods = {};
186
187                         for (let modname in dragonblocks.mods) {
188                                 let modinfo = dragonblocks.mods[modname];
189
190                                 let modDisplay = modlistDisplay.appendChild(document.createElement("li"));
191                                 modDisplay.style.fontSize = "20px";
192                                 modDisplay.innerHTML = modname;
193                                 modDisplay.style.postion = "relative";
194                                 modDisplay.title = modinfo.description;
195
196                                 let checkbox = modDisplay.appendChild(document.createElement("input"));
197                                 checkbox.type = "checkbox";
198                                 checkbox.style.position = "absolute";
199                                 checkbox.style.right = "5px";
200
201                                 checkbox.addEventListener("input", _ => {
202                                         worldProperties.mods[modname] = checkbox.checked;
203                                 });
204
205                                 worldProperties.mods[modname] = checkbox.checked = oldSelectedMods[modname];
206                         }
207                 };
208
209                 // Gamemode
210                 createWorldGUI.create("h2").innerHTML = "&ensp;Gamemode";
211
212                 for (let gamemode of ["survival", "creative"]){
213                         let radiobox = createWorldGUI.create("input");
214                         radiobox.name = "dragonblocks.mainmenu.createWorldGUI.gamemode";
215                         radiobox.type = "radio";
216                         radiobox.checked = gamemode == worldProperties.gamemode;
217                         radiobox.style.position = "relative";
218                         radiobox.style.left = "40px";
219
220                         radiobox.addEventListener("input", _ => {
221                                 if (radiobox.checked)
222                                         worldProperties.gamemode = gamemode;
223                         });
224
225                         let label = createWorldGUI.create("label");
226                         label.innerHTML = dblib.humanFormat(gamemode);
227                         label.style.position = "relative";
228                         label.style.left = "40px";
229                 }
230
231                 // Mapgen
232                 createWorldGUI.create("h2").innerHTML = "&ensp;Mapgen";
233
234                 let selectMapgen = createWorldGUI.create("select");
235                 selectMapgen.style.position = "relative";
236                 selectMapgen.style.left = "40px";
237                 selectMapgen.value = worldProperties.mapgen;
238
239                 selectMapgen.addEventListener("input", _ => {
240                         worldProperties.mapgen = selectMapgen.value;
241                 });
242
243                 for (let mapgen in dragonblocks.mapgen.list)
244                         selectMapgen.appendChild(document.createElement("option")).innerHTML = mapgen;
245
246                 createWorldGUI.create("br");
247                 createWorldGUI.create("br");
248
249                 // Create Button
250                 createButton = createWorldGUI.create("button");
251                 createButton.style.position = "absolute";
252                 createButton.style.left = "1%";
253                 createButton.style.bottom = "5px";
254                 createButton.style.width = "98%";
255                 createButton.style.fontSize = "20px";
256                 createButton.innerHTML = "Create World";
257
258                 createButton.addEventListener("click", event => {
259                         event.srcElement.blur();
260                         createWorldGUI.close();
261
262                         dragonblocks.start(worldProperties);
263                 });
264
265                 createWorldGUI.create("br");
266                 createWorldGUI.create("br");
267
268                 onReload.push(_ => {
269                         worldnameInput.value = "";
270                         worldnameAlert.textContent = "";
271                         createButton.disabled = dragonblocks.loggedin;
272
273                         updateModlist();
274                 });
275
276                 buttons.push({
277                         text: "Create New World",
278                         action: _ => {
279                                 createWorldGUI.open();
280                         },
281                 });
282         }
283
284         // Credits Button
285
286         {
287                 let creditsGUI = new dragonblocks.gui.Box();
288
289                 let pages = $.getJSON("credits.json").responseJSON;
290                 let page = 0;
291
292                 for (let dir of ["left", "right"]) {
293                         let arrow = creditsGUI.create("div");
294                         arrow.style.position = "absolute";
295                         arrow.style.width = "80px";
296                         arrow.style.height = "80px";
297                         arrow.style.position = "absolute";
298                         arrow.style[dir] = "3px";
299                         arrow.style.background = dragonblocks.getTexture("arrow.png");
300                         arrow.style.cursor = "pointer";
301
302                         if (dir == "right")
303                                 arrow.style.transform = "rotate(180deg)";
304
305                         arrow.addEventListener("click", _ => {
306                                 if (dir == "right")
307                                         page++;
308                                 else
309                                         page--;
310
311                                 creditsGUI.open();
312                         });
313
314                         dblib.centerVertical(arrow);
315                 }
316
317                 let creditsContent = creditsGUI.create("center");
318
319                 creditsGUI.addEventListener("open", _ => {
320                         if (page < 0)
321                                 page = pages.length - 1;
322                         else if (page >= pages.length)
323                                 page = 0;
324
325                         creditsContent.innerHTML = pages[page];
326                         dragonblocks.resolveTextures(creditsContent);
327
328                         // fix to center the dots of the li elements in chromium as well
329
330                         let lis = creditsContent.getElementsByTagName("li");
331
332                         for (let li of lis)
333                                 li.style.width = "max-content";
334                 });
335
336                 buttons.push({
337                         text: "Credits",
338                         action: _ => {
339                                 creditsGUI.open();
340                         },
341                 });
342         }
343
344         // Quit Button
345
346         {
347                 buttons.push({
348                         text: "Quit",
349                         action: _ => {
350                                 if (dragonblocks.isChromeApp)
351                                         close();
352                                 else
353                                         history.back();
354                         },
355                 });
356         }
357
358         for (let {text, action, disabled} of buttons) {
359                 let button = content.appendChild(document.createElement("button"));
360                 button.style.fontSize = "40px";
361                 button.style.width = "100%";
362                 button.innerHTML = text;
363                 button.disabled = disabled;
364                 button.addEventListener("click", action);
365
366                 content.appendChild(document.createElement("br"));
367                 content.appendChild(document.createElement("br"));
368         }
369
370         for (let [side, text] of [["left", dragonblocks.version.string], ["right", dragonblocks.version.copyright]]) {
371                 let notice = content.appendChild(document.createElement("span"));
372                 notice.style.position = "fixed";
373                 notice.style.bottom = "5px";
374                 notice.style[side] = "5px";
375                 notice.innerHTML = text;
376         }
377
378         dragonblocks.enterMainMenu = _ => {
379                 dragonblocks.loadModList();
380                 worlds = dragonblocks.backendCall("getWorlds");
381
382                 content.style.display = "inherit";
383                 status.style.display = "none";
384
385                 for (let func of onReload)
386                         func();
387         };
388
389         dragonblocks.registerOnStart(_ => {
390                 content.style.display = "none";
391                 status.style.display = "inherit";
392
393                 status.innerHTML = "Loading...";
394         });
395
396         dragonblocks.registerOnStarted(_ => {
397                 mainmenu.style.visibility = "hidden";
398         });
399
400         dragonblocks.registerOnQuit(_ => {
401                 mainmenu.style.visibility = "visible";
402                 status.innerHTML = "Saving...";
403         });
404
405         let updateSplash = _ => {
406                 splash.style.left = (logo.x + logo.width - splash.clientWidth / 2) + "px";
407                 splash.style.top = (logo.y + logo.height / 3 * 2 - splash.clientHeight / 2) + "px";
408         };
409
410         let initMainMenu = _ => {
411                 document.body.style.backgroundColor = "skyblue";
412                 document.getElementById("elidragon").remove();
413                 content.style.width = logo.offsetWidth + "px";
414                 mainmenu.style.visibility = "visible";
415
416                 let splashes = $.getJSON("splashes.json").responseJSON;
417
418                 splash.innerHTML = splashes[Math.floor(Math.random() * splashes.length)];
419                 let fontSize = Math.min(parseInt(10000 / splash.clientWidth), 30);
420                 splash.style.fontSize = fontSize + "px";
421                 updateSplash();
422
423                 let counter = 0;
424                 setInterval(_ => {
425                         splash.style.fontSize = Math.sin(counter++ / 100 * Math.PI) * fontSize / 6 + fontSize + "px";
426                         updateSplash();
427                 });
428
429                 dragonblocks.enterMainMenu();
430         };
431
432         if (logo.complete)
433                 initMainMenu();
434         else
435                 logo.addEventListener("load", initMainMenu);
436 }