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