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