diff options
59 files changed, 1666 insertions, 598 deletions
@@ -17,52 +17,14 @@ switch (require('./package.json').channel) { break; } -if (process.argv[2] === "m") { - console.log(" * *******************************************"); - console.log(" * * DATA MITIGATION MODE *"); - console.log(" * * *"); - console.log(" * * Unless you ABSOLUTELY need this, please *"); - console.log(" * * consider starting Kartik normally. *"); - console.log(" * *******************************************"); - if (!require('fs').existsSync(__dirname + "/data")) { - require('fs').mkdirSync(__dirname + "/data"); - } - global.homedir = __dirname + "/data"; -} else { - global.homedir = require('os').userInfo().homedir; -}; - global.start = new Date(); global.KartikRoot = __dirname; global.shouldExitIfClosed = false; const { app, BrowserWindow } = require('electron'); (async () => { - console.log(" * Gathering language"); - slpm = require('os-locale'); - slpw = await slpm(); - slpo = slpw.substr(0, 2); - slng = require('./lang/languages.json'); - if (Object.keys(slng).includes(slpo)) { - dlp = slpo; - } else { - dlp = "en"; - } - - if (!require('fs').existsSync(require('os').userInfo().homedir + "/.kartik")) { - require('fs').mkdirSync(require('os').userInfo().homedir + "/.kartik") - } - - if (!require('fs').existsSync(require('os').userInfo().homedir + "/.kartik/crashes")) { - require('fs').mkdirSync(require('os').userInfo().homedir + "/.kartik/crashes") - } - - if (!require('fs').existsSync(require('os').userInfo().homedir + "/.kartik/mods")) { - require('fs').mkdirSync(require('os').userInfo().homedir + "/.kartik/mods") - } - process.on('uncaughtException', (error) => { - console.log(" * Starting recovery procedure: E_ERROR"); + console.log(" * Starting recovery procedure: E_ERROR: " + error.message); id = new Date().toISOString().replaceAll(":", "-"); require('fs').writeFileSync(require('os').userInfo().homedir + "/.kartik/crashes/" + id + ".txt", "Kartik Bootstraper Crash\n\n" + error.stack); @@ -77,7 +39,7 @@ const { app, BrowserWindow } = require('electron'); }) process.on('unhandledRejection', (reason) => { - console.log(" * Starting recovery procedure: E_PROMISE"); + console.log(" * Starting recovery procedure: E_PROMISE: " + reason); id = new Date().toISOString(); require('fs').writeFileSync(homedir + "/.kartik/crashes/" + id + ".txt", "Kartik Bootstraper Crash (in promise)\n\n" + reason); @@ -91,228 +53,303 @@ const { app, BrowserWindow } = require('electron'); process.exit(2); }) + if (process.argv[2] === "m") { + console.log(" * *******************************************"); + console.log(" * * DATA MITIGATION MODE *"); + console.log(" * * *"); + console.log(" * * Unless you ABSOLUTELY need this, please *"); + console.log(" * * consider starting Kartik normally. *"); + console.log(" * *******************************************"); + if (!require('fs').existsSync(__dirname + "/data")) { + require('fs').mkdirSync(__dirname + "/data"); + } + global.homedir = __dirname + "/data"; + } else { + global.homedir = require('os').userInfo().homedir; + } + /* --------------------- */ - console.log(" * Creating configuration"); + console.log(" * Preparing application paths"); + app.setAppLogsPath(homedir + "/.kartik/logs"); + app.setPath("crashDumps", homedir + "/.kartik/dumps"); + app.setPath('userData', homedir + "/.kartik/storage"); + app.whenReady().then(async () => { + if (require('./package.json').channel !== "stable" && require('./package.json').channel !== "git") { + console.log(" * Opening save data conversion dialog"); + global.converting = true; + btn = require('electron').dialog.showMessageBoxSync( + { + type: "warning", + title: "Migrating save data to Kartik Fox Nest required", + message: "Your save data needs to be converted", + buttons: [ + "Use a new game directory (recommended)", + "Convert existing save data", + "Quit without doing anything" + ], + cancelId: 2, + detail: "Kartik Fox Nest (the new save data format) has been introduced in this version, and it requires converting from the old save data format. Because it is not possible to downgrade from Kartik Fox Nest to the old save data format, you have to choose what to do." + } + ) + + switch (btn) { + case 2: + process.exit(2); + break; + case 1: + break; + case 0: + if (process.argv[2] === "m") { + console.log(" * *******************************************"); + console.log(" * * DATA MITIGATION MODE *"); + console.log(" * * *"); + console.log(" * * Unless you ABSOLUTELY need this, please *"); + console.log(" * * consider starting Kartik normally. *"); + console.log(" * *******************************************"); + if (!require('fs').existsSync(__dirname + "/data")) { + require('fs').mkdirSync(__dirname + "/data"); + } + global.homedir = __dirname + "/data/.KartikStaging$"; + } else { + global.homedir = require('os').userInfo().homedir + "/.KartikStaging$"; + } + app.setAppLogsPath(homedir + "/.kartik/logs"); + app.setPath("crashDumps", homedir + "/.kartik/dumps"); + app.setPath('userData', homedir + "/.kartik/storage"); + if (!require('fs').existsSync(homedir)) { + require('fs').mkdirSync(homedir); + } + break; + } + } - const fs = require('fs'); - const Nest = require('./nest/abi'); + console.log(" * Gathering language"); + slpm = require('os-locale'); + slpw = await slpm(); + slpo = slpw.substr(0, 2); + slng = require('./lang/languages.json'); + if (Object.keys(slng).includes(slpo)) { + dlp = slpo; + } else { + dlp = "en"; + } - /*if (!fs.existsSync(homedir + "/.kartik")) { - fs.mkdirSync(homedir + "/.kartik"); - } - if (!fs.existsSync(homedir + "/.kartik/config")) { - fs.mkdirSync(homedir + "/.kartik/config"); - } - if (!fs.existsSync(homedir + "/.kartik/crashes")) { - fs.mkdirSync(homedir + "/.kartik/crashes"); - } - if (!fs.existsSync(homedir + "/.kartik/logs")) { - fs.mkdirSync(homedir + "/.kartik/logs"); - } - if (!fs.existsSync(homedir + "/.kartik/dumps")) { - fs.mkdirSync(homedir + "/.kartik/dumps"); - } - if (!fs.existsSync(homedir + "/.kartik/mods")) { - fs.mkdirSync(homedir + "/.kartik/mods"); - } - if (!fs.existsSync(homedir + "/.kartik/storage")) { - fs.mkdirSync(homedir + "/.kartik/storage"); - } - fs.writeFileSync(homedir + "/.kartik/config/scale.txt", "1.2"); - if (!fs.existsSync(homedir + "/.kartik/config/lang.txt")) { - fs.writeFileSync(homedir + "/.kartik/config/lang.txt", dlp); - } - if (!fs.existsSync(homedir + "/.kartik/config/music.txt")) { - fs.writeFileSync(homedir + "/.kartik/config/music.txt", "1"); - } - if (!fs.existsSync(homedir + "/.kartik/config/online.txt")) { - fs.writeFileSync(homedir + "/.kartik/config/online.txt", "1"); - } - if (!fs.existsSync(homedir + "/.kartik/config/voice.txt")) { - fs.writeFileSync(homedir + "/.kartik/config/voice.txt", "0"); - }*/ + console.log(" * Saving to " + homedir); - if (fs.existsSync(homedir + "/.kartik/config") && fs.existsSync(homedir + "/.kartik/config/voice.txt") && fs.existsSync(homedir + "/.kartik/config/online.txt") && fs.existsSync(homedir + "/.kartik/config/music.txt") && fs.existsSync(homedir + "/.kartik/config/lang.txt") && fs.existsSync(homedir + "/.kartik/stats.json")) { - console.log(" * Found complete Config V1, migrating to Kartik Fox Nest..."); - Nest.convert(homedir + "/.kartik/current.kfn", homedir + "/.kartik"); - } else { - if (!fs.existsSync(homedir + "/.kartik/current.kfn")) { - console.log(" * No Kartik Fox Nest found, generating one..."); - Nest.generate(homedir + "/.kartik/current.kfn"); + if (!require('fs').existsSync(homedir + "/.kartik")) { + require('fs').mkdirSync(homedir + "/.kartik") } - } - global.currentNest = Nest.load(homedir + "/.kartik/current.kfn"); - console.log(" * Kartik Fox Nest loaded, " + fs.readFileSync(homedir + "/.kartik/current.kfn").toString().length + " bytes, last loaded in Kartik " + currentNest._version); + if (!require('fs').existsSync(homedir + "/.kartik/crashes")) { + require('fs').mkdirSync(homedir + "/.kartik/crashes") + } - currentNest._version = require('./package.json').version; - Nest.export(homedir + "/.kartik/current.kfn", currentNest); + if (!require('fs').existsSync(homedir + "/.kartik/mods")) { + require('fs').mkdirSync(homedir + "/.kartik/mods") + } - /* --------------------- */ + if (require('fs').existsSync(homedir + "/.kartik/build")) { + require('fs').rmSync(homedir + "/.kartik/build", { recursive: true }) + } + require('fs').mkdirSync(homedir + "/.kartik/build") + + console.log(" * Creating configuration"); + + const fs = require('fs'); + const Nest = require('./nest/abi'); - console.log(" * Checking channel"); - require('@electron/remote/main').initialize(); - - function createWindow () { - if (require('./package.json').channel === "stable") { - logo = "logo/logo.png"; - channel = " "; - global.dimg = "official"; - global.dimga = "stable"; - global.dchan = "Kartik Stable"; - } else if (require('./package.json').channel === "beta") { - logo = "logo/logo-beta.png"; - channel = " Beta "; - global.dimg = "beta"; - global.dimga = "beta"; - global.dchan = "Kartik Beta"; - } else if (require('./package.json').channel === "nightly") { - logo = "logo/logo-nightly.png"; - channel = " Nightly "; - global.dimg = "nightly"; - global.dimga = "nightly"; - global.dchan = "Kartik Nightly"; - } else if (require('./package.json').channel === "eap") { - logo = "logo/logo-eap.png"; - channel = " EAP "; - global.dimg = "eap"; - global.dimga = "eap"; - global.dchan = "Kartik EAP"; - } else if (require('./package.json').channel === "git") { - logo = "logo/logo-git.png"; - channel = " Trunk "; - global.dimg = "git"; - global.dimga = "git"; - global.dchan = "Kartik Trunk"; - try { - pk = require('./package.json'); - pk.version = require('fs').readFileSync("./.git/refs/heads/trunk").toString().substr(0, 7); - fs.writeFileSync("./package.json", JSON.stringify(pk, 2)) - } catch (e) {} + if (fs.existsSync(homedir + "/.kartik/config") && fs.existsSync(homedir + "/.kartik/config/voice.txt") && fs.existsSync(homedir + "/.kartik/config/online.txt") && fs.existsSync(homedir + "/.kartik/config/music.txt") && fs.existsSync(homedir + "/.kartik/config/lang.txt") && fs.existsSync(homedir + "/.kartik/stats.json")) { + console.log(" * Found complete Config V1, migrating to Kartik Fox Nest..."); + Nest.convert(homedir + "/.kartik/current.kfn", homedir + "/.kartik"); + } else { + if (!fs.existsSync(homedir + "/.kartik/current.kfn")) { + console.log(" * No Kartik Fox Nest found, generating one..."); + Nest.generate(homedir + "/.kartik/current.kfn"); + } else { + fs.copyFileSync(homedir + "/.kartik/current.kfn", homedir + "/.kartik/latest.kfn"); + } } - console.log(" * Checking configuration"); - - lp = currentNest.config.lang - - time = new Date() - start; - console.log(" * Started successfully in " + Math.round(time/1000) + " seconds"); - console.log(" * Why are you EVEN reading this?"); - load.close(); - console.log(" * Starting recovery procedure: E_PROMISE"); - global.win = new BrowserWindow({ - width: 1220, - height: 720, - minWidth: 720, - minHeight: 540, - resizeable: true, - resizable: true, - maximizable: true, - show: false, - enableLargerThanScreen: true, - icon: logo, - backgroundColor: "#000000", - title: "Kartik", - webPreferences: { - nodeIntegration: true, - contextIsolation: false, - enableRemoteModule: true, - webviewTag: true, - disableBlinkFeatures: "MediaSessionService", + global.currentNest = Nest.load(homedir + "/.kartik/current.kfn"); + console.log(" * Kartik Fox Nest loaded, " + fs.readFileSync(homedir + "/.kartik/current.kfn").toString().length + " bytes, last loaded in Kartik " + currentNest._version); + + currentNest._version = require('./package.json').version; + Nest.export(homedir + "/.kartik/current.kfn", currentNest); + + /* --------------------- */ + + console.log(" * Checking channel"); + require('@electron/remote/main').initialize(); + + function createWindow () { + if (require('./package.json').channel === "stable") { + logo = "logo/logo.png"; + channel = " "; + global.dimg = "official"; + global.dimga = "stable"; + global.dchan = "Kartik Stable"; + } else if (require('./package.json').channel === "beta") { + logo = "logo/logo-beta.png"; + channel = " Beta "; + global.dimg = "beta"; + global.dimga = "beta"; + global.dchan = "Kartik Beta"; + } else if (require('./package.json').channel === "nightly") { + logo = "logo/logo-nightly.png"; + channel = " Nightly "; + global.dimg = "nightly"; + global.dimga = "nightly"; + global.dchan = "Kartik Nightly"; + } else if (require('./package.json').channel === "eap") { + logo = "logo/logo-eap.png"; + channel = " EAP "; + global.dimg = "eap"; + global.dimga = "eap"; + global.dchan = "Kartik EAP"; + } else if (require('./package.json').channel === "git") { + logo = "logo/logo-git.png"; + channel = " Trunk "; + global.dimg = "git"; + global.dimga = "git"; + global.dchan = "Kartik Trunk"; + try { + pk = require('./package.json'); + pk.version = require('fs').readFileSync("./.git/refs/heads/trunk").toString().substr(0, 7); + fs.writeFileSync("./package.json", JSON.stringify(pk, 2)) + } catch (e) {} } - }) - global.shouldExitIfClosed = true; - - console.log(" * Starting IPC engine"); - win.pwidth = 720; - win.pheight = 540; - win.log = console.log; - - win.debug = process.argv[2] === "d"; - win.channel = channel; - win.scale = 1.2; - win.update = dimga; - win.gamepads = []; - win.controllerAttached = false; - win.webview = null; - win.dstate = "Kartik"; - win.ddetails = "Kartik"; - win.mods = mods; - - win.homedir = homedir; - - win.lp = lp; - win.music = currentNest.config.music; - win.voice = currentNest.config.voice; - - win.online = currentNest.config.online; - win.nest = currentNest; - - win.resources = resources; - global.currentSongValue = null; - - console.log(" * Starting language preloader"); - require('./lang/preload.js'); - console.log(" * Starting Discord RPC"); - require('./discord/client.js'); - - console.log(" * Loading view"); - win.loadFile('./index.html') - win.setMenu(null); - - if (win.debug) { - console.log(" * *******************************************"); - console.log(" * * KARTIK DEBUG MODE *"); - console.log(" * *******************************************"); - win.openDevTools(); - } - - win.webContents.on('dom-ready', () => { - musicIpc = require('electron').ipcMain; - musicIpc.on('newmusic', (event, value) => { - if (music) { - win.webContents.send('setmusic', value); + console.log(" * Checking configuration"); + + lp = currentNest.config.lang + + time = new Date() - start; + console.log(" * Started successfully in " + Math.round(time/1000) + " seconds"); + console.log(" * Why are you EVEN reading this?"); + try { load.close(); } catch (e) {} + console.log(" * Starting recovery procedure: E_PROMISE"); + global.win = new BrowserWindow({ + width: 1220, + height: 720, + minWidth: 720, + minHeight: 540, + resizeable: true, + resizable: true, + maximizable: true, + show: false, + enableLargerThanScreen: true, + icon: logo, + backgroundColor: "#000000", + title: "Kartik", + webPreferences: { + nodeIntegration: true, + contextIsolation: false, + enableRemoteModule: true, + webviewTag: true, + disableBlinkFeatures: "MediaSessionService", } }) - const LevelsAPI = require('./views/script/global_levelsapi'); - const lvl = new LevelsAPI(); - - stats = currentNest.stats; - musicIpc.on('addstats', (event, value) => { - currentNest.stats[value.catalog][value.key] = currentNest.stats[value.catalog][value.key] + value.add; - Nest.export(homedir + "/.kartik/current.kfn", currentNest); - - if (value.key === "laps" && fs.existsSync(homedir + "/.kartik/authentication.json")) { - auth = currentNest.auth; - level = lvl.correspond(currentNest.stats["ingame"]["laps"], "256") - 1 + 1; - - if (level !== auth.level) { - currentNest.auth.level = level - Nest.export(homedir + "/.kartik/current.kfn", currentNest); - if (level < 200) { - win.webContents.send("notification", {title: lang.polymer.levelup[0], message: lang.polymer.levelup[1] + " " + level + " " + lang.polymer.levelup[2]}); - } else { - win.webContents.send("notification", {title: lang.polymer.finished[0], message: lang.polymer.finished[1]}); + global.shouldExitIfClosed = true; + + console.log(" * Starting IPC engine"); + win.pwidth = 720; + win.pheight = 540; + win.log = console.log; + + win.debug = process.argv[2] === "d"; + win.channel = channel; + win.cmdlineargs = process.argv; + win.scale = 1.2; + win.update = dimga; + win.gamepads = []; + win.controllerAttached = false; + win.webview = null; + win.dstate = "Kartik"; + win.ddetails = "Kartik"; + win.mods = mods; + + win.invalidfiles = invalidfiles; + win.modsfiles = compiledTypeScriptFiles; + win.homedir = homedir; + + win.lp = lp; + win.music = currentNest.config.music; + win.voice = currentNest.config.voice; + + win.online = currentNest.config.online; + win.nest = currentNest; + + win.resources = resources; + global.currentSongValue = null; + + console.log(" * Starting language preloader"); + require('./lang/preload.js'); + console.log(" * Starting Discord RPC"); + require('./discord/client.js'); + + console.log(" * Loading view"); + win.loadFile('./index.html') + win.setMenu(null); + + if (win.debug) { + console.log(" * *******************************************"); + console.log(" * * KARTIK DEBUG MODE *"); + console.log(" * *******************************************"); + win.openDevTools(); + } + + win.webContents.on('dom-ready', () => { + musicIpc = require('electron').ipcMain; + musicIpc.on('newmusic', (event, value) => { + if (music) { + win.webContents.send('setmusic', value); + } + }) + + musicIpc.on('reloadNest', (event) => { + currentNest = Nest.load(homedir + "/.kartik/current.kfn"); + win.nest = currentNest; + }) + + const LevelsAPI = require('./views/script/global_levelsapi'); + const lvl = new LevelsAPI(); + + stats = currentNest.stats; + musicIpc.on('addstats', (event, value) => { + currentNest.stats[value.catalog][value.key] = currentNest.stats[value.catalog][value.key] + value.add; + Nest.export(homedir + "/.kartik/current.kfn", currentNest); + currentNest = Nest.load(homedir + "/.kartik/current.kfn"); + win.nest = currentNest; + + if (value.key === "laps" && currentNest.auth) { + auth = currentNest.auth; + level = lvl.correspond(currentNest.stats["ingame"]["laps"], "256") - 1 + 1; + + if (level !== auth.level) { + currentNest.auth.level = level; + Nest.export(homedir + "/.kartik/current.kfn", currentNest); + currentNest = Nest.load(homedir + "/.kartik/current.kfn"); + win.nest = currentNest; + if (level < 200) { + win.webContents.send("notification", {title: lang.polymer.levelup[0], message: lang.polymer.levelup[1] + " " + level + " " + lang.polymer.levelup[2]}); + } else { + win.webContents.send("notification", {title: lang.polymer.finished[0], message: lang.polymer.finished[1]}); + } } } - } + }) + musicIpc.on('addstatsandclose', (event, value) => { + currentNest.stats[value.catalog][value.key] = currentNest.stats[value.catalog][value.key] + value.add; + Nest.export(homedir + "/.kartik/current.kfn", currentNest); + currentNest = Nest.load(homedir + "/.kartik/current.kfn"); + win.nest = currentNest; + win.destroy(); + }) }) - musicIpc.on('addstatsandclose', (event, value) => { - currentNest.stats[value.catalog][value.key] = currentNest.stats[value.catalog][value.key] + value.add; - Nest.export(homedir + "/.kartik/current.kfn", currentNest); - win.destroy(); - }) - }) - } + } - console.log(" * Preparing application paths"); - app.setAppLogsPath(homedir + "/.kartik/logs"); - app.setPath("crashDumps", homedir + "/.kartik/dumps"); - app.setPath('userData', homedir + "/.kartik/storage"); - app.whenReady().then(() => { console.log(" * Starting splash screen"); global.load = new BrowserWindow({ width: 640, @@ -341,24 +378,20 @@ const { app, BrowserWindow } = require('electron'); setTimeout(() => { console.log(" * Checking signatures"); + invalidfiles = []; + sigdb = require("./bin/signatures.json"); total = Object.keys(sigdb["v1"]).length * 3; processed = 0; for (file in sigdb["v1"]) { - if (fs.existsSync(file)) { + if (fs.existsSync(file) && !invalidfiles.includes(file)) { try { hash = require('crypto').createHash('sha512').update(fs.readFileSync(file)).digest('base64'); if (hash !== sigdb["v1"][file]) { - require('electron').dialog.showMessageBoxSync( - { - type: "warning", - title: "Source modification detected", - message: "File " + file + " has been flagged as modified (signing V1). If this is normal, please run the signing process again.\n\nExpected: " + sigdb["v1"][file] + "\nGot: " + hash + "\n\nYou are running a modified version of Kartik, do not expect to get support!" - } - ) + invalidfiles.push(file); } } catch (e) { - console.warn(" ! Could not V1 compute hash for " + file); + console.warn(" ! Could not compute V1 hash for " + file); } } @@ -366,17 +399,11 @@ const { app, BrowserWindow } = require('electron'); load.webContents.send('progress', (processed/total)*100); } for (file in sigdb["v2"]) { - if (fs.existsSync(file)) { + if (fs.existsSync(file) && !invalidfiles.includes(file)) { try { hash = require('crypto').createHash('sha1').update(fs.readFileSync(file)).digest('base64'); if (hash !== sigdb["v2"][file]) { - require('electron').dialog.showMessageBoxSync( - { - type: "warning", - title: "Source modification detected", - message: "File " + file + " has been flagged as modified (signing V2). If this is normal, please run the signing process again.\n\nExpected: " + sigdb["v2"][file] + "\nGot: " + hash + "\n\nYou are running a modified version of Kartik, do not expect to get support!" - } - ) + invalidfiles.push(file); } } catch (e) { console.warn(" ! Could not compute V2 hash for " + file); @@ -387,17 +414,11 @@ const { app, BrowserWindow } = require('electron'); load.webContents.send('progress', (processed/total)*100); } for (file in sigdb["v3"]) { - if (fs.existsSync(file)) { + if (fs.existsSync(file) && !invalidfiles.includes(file)) { try { hash = require('crypto').createHash('md5').update(fs.readFileSync(file)).digest('base64'); if (hash !== sigdb["v3"][file]) { - require('electron').dialog.showMessageBoxSync( - { - type: "warning", - title: "Source modification detected", - message: "File " + file + " has been flagged as modified (signing V3). If this is normal, please run the signing process again.\n\nExpected: " + sigdb["v3"][file] + "\nGot: " + hash + "\n\nYou are running a modified version of Kartik, do not expect to get support!" - } - ) + invalidfiles.push(file); } } catch (e) { console.warn(" ! Could not compute V3 hash for " + file); @@ -408,10 +429,16 @@ const { app, BrowserWindow } = require('electron'); load.webContents.send('progress', (processed/total)*100); } + global.importedTypeScriptFiles = []; + global.compiledTypeScriptFiles = []; console.log(" * Generating resources pack"); require('./modding/resources'); console.log(" * Starting Kartik Modding Platform"); require('./modding/parser'); + console.log(" * Compiling KMP API TypeScript files"); + require('./modding/compiler'); + console.log(" * Loading KMP TypeScript mods"); + require('./typescript/preloader'); createWindow(); }, 5000) }) diff --git a/crash/client.js b/crash/client.js index e70467f..95cc342 100644 --- a/crash/client.js +++ b/crash/client.js @@ -1,8 +1,40 @@ +taglines = [ + "Who set us up the engine?", + "Everything's going as planned. No, really, that was supposed to happen.", + "Uh... Did I do that? (oops)", + "Oops.", + "Why did you do that?", + "I feel sad now :(", + "My bad.", + "I'm sorry, Dave. I'm afraid I can't do that.", + "I let you down. Sorry :(", + "On the bright side, I bought you a teddy bear!", + "Oh - I know what I did wrong!", + "Hey, that tickles! Hehehe!", + "I blame Microsoft.", + "Don't be sad. I'll do better next time, pinky swear!", + "Don't be sad, have a hug! <3", + "I just don't know what went wrong :(", + "Shall we play a game?", + "Quite honestly, I wouldn't worry myself about that.", + "Sorry :(", + "Surprise! Haha. Well, this is awkward.", + "Would you like a cupcake?", + "Hi. I'm Kartik, and I'm a crashaholic.", + "Ooh. Shiny.", + "This doesn't make any sense!", + "Why is it breaking :(", + "Don't do that.", + "Ouch. That hurt :(", + "You're mean.", + "But it works on my machine.", + "Welp, I guess it's broken now.", + "¯\\_(ツ)_/¯", + "*boop*" +] + if (native) { function crash(error) { - try { - require('@electron/remote').getCurrentWindow().hide(); - } catch (e) {} id = new Date().toISOString().replaceAll(":", "-"); try { @@ -13,72 +45,79 @@ if (native) { } - report = "\n"; - report += "Kartik Crash Report\n\nPlease send this to the developers so they can fix the problem and deploy a patch to all players.\n\nStack Trace:\n" - error.stack.split("\n").forEach((line) => { - report += " " + line + "\n"; - }) - report += "\n\nSystem Information:\n" - report += " " + "Kartik"+require('@electron/remote').getCurrentWindow().channel + "(" + pkg.name + ") " +pkg.version + " [" + pkg.serial + "]\n"; + try { + pubver = require('../package.json').version; + } catch (e) { + pubver = require('./package.json').version; + } + pvpart = pubver.split("."); + if (pvpart.length === 3) { + intver = pvpart[0] + "." + pvpart[1]; + } else { + intver = "unknown"; + } - report += " " + require('os').type() + " (" + require('os').version() + ", " + require('os').arch() +") version " + require('os').release() + "\n"; - cores = require('os').cpus() - if (cores.length > 1) { - report += " " + cores.length + " processors"; + if (require('@electron/remote').getCurrentWindow().mods.length > 0) { + release = "mods+" + require('@electron/remote').getCurrentWindow().mods.length; } else { - report += " " + cores.length + " processor"; + release = "official"; } - report += "\n\nKartik Components:\n"; - Object.keys(process.versions).forEach((e) => { - v = process.versions[e]; - report += " " + e + "@" + v + "\n"; + report = "---- Kartik Crash Report ----\n"; + report += "// " + taglines[Math.floor(Math.random() * taglines.length)] + "\n\n" + + report += "Time: " + new Date().toUTCString() + "\n\n"; + error.stack.split("\n").forEach((line) => { + report += line + "\n"; }) - require('fs').writeFileSync(require('os').userInfo().homedir + "/.kartik/crashes/" + id + ".txt", report); - if (error.message !== "Invalid display" && error.message !== "Out of memory") { + report += "\n\n\nA detailed walkthrough of the error, its code path and all known details is as follows:\n" + + "---------------------------------------------------------------------------------------\n\n"; - fetch("https://kartik.hopto.org/telemetry/report/?report=" + btoa(report.replaceAll(require('os').userInfo().username, "<information removed>"))) + report += "-- Head --\nThread: Renderer #" + process.pid + "\n\n" - .then(() => { - if (require('os').platform() === "win32") { - require('child_process').execSync("runtime\\kartik-crash.bat"); - } else if (require('os').platform() === "darwin") { - require('child_process').execSync("./runtime/kartik-crash-mac.sh"); - } else { - require('child_process').execSync("./runtime/kartik-crash.sh"); - } - require('@electron/remote').getCurrentWindow().destroy(); + report += "-- Initialization --\nDetails: " + require('@electron/remote').getCurrentWindow().cmdlineargs.join(" ") + "\n\n" - window.close(); - require('@electron/remote').getCurrentWindow().close(); - }) - .catch(() => { - if (require('os').platform() === "win32") { - require('child_process').execSync("runtime\\kartik-crash.bat"); - } else if (require('os').platform() === "darwin") { + report += "-- System Details --\nDetails: \n"; - require('child_process').execSync("./runtime/kartik-crash-mac.sh"); - } else { - require('child_process').execSync("./runtime/kartik-crash.sh"); - } - require('@electron/remote').getCurrentWindow().destroy(); - window.close(); - require('@electron/remote').getCurrentWindow().close(); - }) - } else { - if (require('os').platform() === "win32") { - require('child_process').execSync("runtime\\kartik-crash.bat"); - } else if (require('os').platform() === "darwin") { - require('child_process').execSync("./runtime/kartik-crash-mac.sh"); + report += " Kartik Version: " + pkg.version + "\n"; + try { + channel = require('../package.json').channel; + } catch (e) { + channel = require('./package.json').channel; + } + report += " Kartik Version ID: " + intver + "/" + channel + "+" + release + "\n"; + report += " Kartik Version SKU: " + pkg.serial + "\n"; + report += " Operating System: " + require('os').type() + " (" + require('os').arch() + ") version " + require('os').release() + "\n"; + report += " Electron Version: " + process.versions.electron + "\n"; + report += " Electron VM Version: " + process.versions.v8 + "\n"; + report += " Node Version: " + process.versions.node + "\n"; + report += " Memory: " + process.memoryUsage().heapUsed + " bytes (" + Math.round(process.memoryUsage().heapUsed / 1000000) + " MB) / " + process.memoryUsage().heapTotal + " bytes (" + Math.round(process.memoryUsage().heapTotal / 1000000) + " MB) up to " + process.memoryUsage().rss + " bytes (" + Math.round(process.memoryUsage().rss / 1000000) + " MB)\n"; + report += " CPUs: " + require('os').cpus().length + "\n"; + if (require('@electron/remote').getCurrentWindow().mods.length > 0) { + report += " KMP Mods:\n"; + for (mod of require('@electron/remote').getCurrentWindow().mods) { + report += " " + mod + "\n"; + } + } + report += " Is Modded: "; + if (require('@electron/remote').getCurrentWindow().mods.length > 0) { + report += "Definitely; Client brand changed to 'kmp-client'" + } else if (require('@electron/remote').getCurrentWindow().invalidfiles.length > 0) { + if (require('@electron/remote').getCurrentWindow().invalidfiles.length > 1) { + report += "Very likely; " + require('@electron/remote').getCurrentWindow().invalidfiles.length + " signatures invalidated"; } else { - require('child_process').execSync("./runtime/kartik-crash.sh"); + report += "Very likely; " + require('@electron/remote').getCurrentWindow().invalidfiles.length + " signature invalidated"; } - - require('@electron/remote').getCurrentWindow().destroy(); - window.close(); - require('@electron/remote').getCurrentWindow().close(); + } else { + report += "Probably not. All signatures remains and client brand is untouched."; } + report += "\n"; + report += " CPU: " + require('os').cpus().length + "x " + require('os').cpus()[0].model.trim() + "\n"; + + require('fs').copyFileSync(homedir + "/.kartik/current.kfn", homedir + "/.kartik/crashed.kfn"); + require('fs').writeFileSync(require('os').userInfo().homedir + "/.kartik/crashes/" + id + ".txt", report); + require('@electron/remote').getCurrentWindow().webContents.send("crashreport", report); } window.onerror = (_a, _b, _c, _d, error) => { @@ -98,17 +137,4 @@ if (native) { crash(new Error("Unknown error")); } }) - - /*setInterval(() => { - try { - if (document.body.clientWidth >= (screen.width - 50) || document.body.clientHeight >= (screen.height - 50) || require('@electron/remote').getCurrentWindow().pwidth >= (screen.width - 50) || require('@electron/remote').getCurrentWindow().pheight >= (screen.height - 50) || require('@electron/remote').getCurrentWindow().scale < 0.9) { - - if (!location.href.includes("credits.html")) { - error("CrashManager", "Invalid display, crashing"); - crash(new Error("Invalid display")); - // TODO: Instead reset the size and restart - } - } - } catch (e) {} - }, 2000)*/ } diff --git a/discord/client.js b/discord/client.js index 1e98faf..d849ed3 100644 --- a/discord/client.js +++ b/discord/client.js @@ -23,7 +23,7 @@ async function setActivity() { state: win.dstate, startTimestamp, largeImageKey: 'kartik', - largeImageText: 'Kartik, ' + lang.game.credits.by + ' Minteck Projects', + largeImageText: 'Kartik, ' + lang.game.credits.by + ' Minteck', smallImageKey: dimg, smallImageText: dchan, instance: false, @@ -11,15 +11,10 @@ <script src="./views/script/core_head.js"></script> <script src="./views/script/core_compatlayer.js"></script> <script src="./views/script/core_fullscreen.js"></script> - <script> - if (native) { - require('@electron/remote').getCurrentWindow().show(); - } - </script> + <script src="./typescript/mainloader.js"></script> </head> <body style="background:#000000;margin:0;height:100%;width:100%;zoom:1.2;"> - <div id="dummyloader" style="display:flex;align-items:center;justify-content:center;position:fixed;z-index:1;inset: 0;height: 100%;background:#fed1ae;overflow:hidden;"> - <img src="logo/itch/banner.jpg" style="height:100%;width:auto;"> + <div id="dummyloader" style="display:flex;align-items:center;justify-content:center;position:fixed;z-index:1;inset: 0;height: 100%;background:#f4f3f4;overflow:hidden;"> </div> <div style="height: 64px;position: fixed;bottom: 10px;left: 0;background-image: url(./logo/newloader.svg);width: 100000000px;background-size: contain;animation-name: loading;animation-direction: reverse;animation-fill-mode: forwards;animation-timing-function: linear;animation-duration: 5000s;animation-iteration-count: infinite;opacity: .5;"></div> <style> @@ -100,12 +95,30 @@ <script> document.write(`<webview id="wb" src="views/loader.html" style="border: 0;z-index:2;top:0;left:0;right:0;bottom:0;position:fixed;" nodeintegration disablewebsecurity allowpopups webpreferences="nodeIntegration,contextIsolation=no"></webview>`); </script> - </div> <script src="./views/script/core_chart.js"></script> <script src="./views/script/core_music.js"></script> <script src="./views/script/core_viewer.js"></script> <script src="./views/script/core_stats.js"></script> <script src="./views/script/core_notification.js"></script> <script>info("MainWindow", "Main container up!");if (native){require('@electron/remote').getCurrentWindow().log(" * View loaded, Kartik is now up and running!");}</script> + + <div id="error-outer" style="display:none;background:rgba(0, 0, 0, .5);backdrop-filter: blur(10px);position:fixed;inset:0;align-items:center;justify-content: center;z-index:999;text-align: center;"> + <div id="error" style="background:#111;border-radius:10px;color:white;max-width:40vw;"> + <div id="error-title" style="padding:10px;background:#222;border-top-left-radius: 10px;border-top-right-radius: 10px;">Kartik encountered an error</div> + <div id="error-details" style="padding:10px;">An error occurred and Kartik couldn't continue running. We collected some info that you can send to the developers so they can fix the problem.<textarea id="crash-dump" disabled="" style="margin: 0;resize: none;background: #171717;color: white;margin-top: 10px;font-family: monospace;font-size: 10px;width: calc(100% - 13px);padding: 5px;border: 2px ridge white;border-radius: 0;height: 180px;overflow-y: scroll;">Nothing there yet!</textarea><div id="error-buttons" style="margin-top: 10px;"><button style="padding: 5px 10px;margin-right: 5px;border-radius: 5px;background: #161616;color: white;border: 1px solid #121212;cursor: pointer !important;outline:none;" class="error-button" onclick="require('open')('https://jetbrains.minteck.ro.lt:1024/youtrack/newIssue?project=KTK&summary=%5BTry%20to%20summarize%20what%20the%20bug%20says%5D&description=%23%20Kartik%20Bug%20Report%0A%0A%23%23%20Crash%20Report%0A%0A%60%60%60text%0A%25replace%25%0A%60%60%60%0A%0A%23%23%20Steps%20to%20reproduce%0A%0A%5BTell%20us%20how%20you%20triggered%20the%20crash%2C%20how%20to%20reproduce%20it%20if%20possible%5D%0A%0A%23%23%20Other%20notes%0A%0A%5BIf%20you%20modified%20your%20version%20of%20Kartik%2C%20tell%20us%20what%20you%20modified.%20All%20the%20rest%20of%20the%20information%20should%20be%20in%20the%20Crash%20Report.%5D'.replace('%25replace%25', encodeURI(document.getElementById('crash-dump').value.split('---------------------------------------------------------------------------------------')[0].trim())));">Open report page</button> <button class="error-button" style="padding: 5px 10px;border-radius: 5px;background: #161616;color: white;border: 1px solid #121212;cursor: pointer !important;outline:none;" onclick="location.reload();">Restart</button></div></div> + </div> + + <style> + .error-button:hover { + background: #212121 !important; + } + + .error-button:active, .error-button:focus { + background: #252525 !important; + } + </style> + </div> + + <script src="./views/script/core_crash.js"></script> </body> </html> diff --git a/kartik-nosandbox.bat b/kartik-nosandbox.bat new file mode 100644 index 0000000..c8f89e5 --- /dev/null +++ b/kartik-nosandbox.bat @@ -0,0 +1,2 @@ +@echo off +bin\win32\kartik-core.exe --no-sandbox app.js
\ No newline at end of file diff --git a/lang/en.json b/lang/en.json index 19372a4..4257553 100644 --- a/lang/en.json +++ b/lang/en.json @@ -203,10 +203,12 @@ }, "polymer": { "gpu": "GPU Support Status", + "gpuShift": "Press Shift for details", "logging": "We are logging you in ; check for your Web browser window and accept the login.", "loginClose": "You can now close this tab/window and go back to Kartik.", "gatheringLogin": "We are checking your account ; this may take a while.", "loginIntro": "Press L to login", + "logout": "L to logout", "ktoLevel": "Level", "ktoMaxLevel": "God", "error": [ diff --git a/lang/fr.json b/lang/fr.json index 3456ef1..6661575 100644 --- a/lang/fr.json +++ b/lang/fr.json @@ -200,5 +200,34 @@ "ingame.laps": "Nombre total de tours", "ingame.turns": "Nombre total de virages" } + }, + "polymer": { + "gpu": "État de support GPU", + "gpuShift": "Appuyez sur Shift pour voir plus", + "logging": "Nous vous connectons ; vérifiez la fenêtre de votre navigateur Web et autorisez la connexion.", + "loginClose": "Vous pouvez maintenant fermer cet onglet ou cette fenêtre et retourner à Kartik.", + "gatheringLogin": "Nous vérifions votre compte ; cela peut prendre un moment.", + "loginIntro": "Appuyez sur L pour vous connecter", + "logout": "L pour vous déconnecter", + "ktoLevel": "Niveau", + "ktoMaxLevel": "Dieu", + "error": [ + "Impossible de communiquer avec les serveurs", + "Vous ne pourrez pas utiliser Kartik Online tant que nous n'arrivons pas à communiquer avec les serveurs.", + "Connectez-vous à Internet" + ], + "updateError": [ + "Impossible de rechercher les mises à jour", + "Nous ne pouvons pas rechercher les mises à jour en ce moment, réessayez plus tard." + ], + "levelup": [ + "Niveau supérieur !", + "Vous avez atteint le niveau", + "et vous gagnez du pouvoir ! Continuez et essayez d'atteindre le niveau maximal." + ], + "finished": [ + "Vous avez battu le jeu !", + "Fini Kartik ?! Oui. Vous avez atteint le niveau Dieu!" + ] } } diff --git a/logo/itch/banner.jpg b/logo/itch/banner.jpg Binary files differindex 61c56d9..c7d5500 100644 --- a/logo/itch/banner.jpg +++ b/logo/itch/banner.jpg diff --git a/logo/itch/cover.jpg b/logo/itch/cover.jpg Binary files differindex b397af5..f850c47 100644 --- a/logo/itch/cover.jpg +++ b/logo/itch/cover.jpg diff --git a/modding/compiler.js b/modding/compiler.js new file mode 100644 index 0000000..240c9a9 --- /dev/null +++ b/modding/compiler.js @@ -0,0 +1,17 @@ +class BuildError extends Error { + constructor(orig, ...params) { + super(...params); + this.name = "BuildError"; + this.stack = this.stack + "\n" + orig.stack; + } +} + +const tsbuild = require('../typescript/builder'); + +for (file of importedTypeScriptFiles) { + try { + tsbuild(file.file, homedir + "/.kartik/build/" + file.output); + } catch (e) { + throw new BuildError(e, "Error while building " + file.file + " from package " + file.pkg) + } +}
\ No newline at end of file diff --git a/modding/hooks.js b/modding/hooks.js index d0ee779..8e189d2 100644 --- a/modding/hooks.js +++ b/modding/hooks.js @@ -1,14 +1,17 @@ +const { dialog } = require('electron'); +const fs = require('fs'); + function hook_Music(mod, type, hname) { hook = mod["Hook"][hname]; names = Object.keys(hook); for (i in names) { name = names[i]; - if (name !== "Music.Start" && name !== "Music.Prepare" && name !== "Music.Title" && name !== "Music.Credits" && name !== "Music.Win" && name !== "Music.Game1" && name !== "Music.Game2" && name !== "Music.Game3" && name !== "Music.Game4" && name !== "Music.Game5" && name !== "Music.Game6" && name !== "Music.Game7" && name !== "Music.Game8" && name !== "Music.Game9") { + if (name !== "Music.Start" && name !== "Music.Prepare" && name !== "Music.Title" && name !== "Music.Credits" && name !== "Music.Win" && name !== "Music.Game1" && name !== "Music.Game2" && name !== "Music.Game3" && name !== "Music.Game4" && name !== "Music.Game5" && name !== "Music.Game6" && name !== "Music.Game7" && name !== "Music.Game8" && name !== "Music.Game9" && name !== "Music.Menu") { dialog.showMessageBoxSync( { type: "error", - title: "Illegal Instruction", + title: "KMP Mod Loader", message: "On package " + item + ": hook " + hname + " (" + type + "): invalid hook data, EXITING" } ) @@ -23,6 +26,10 @@ function hook_Music(mod, type, hname) { resources.music['title'].file = mod["_Path"] + "/" + mod["Hook"][hname][name]; resources.music['title'].original = false; break; + case "Music.Menu": + resources.music['title'].file = mod["_Path"] + "/" + mod["Hook"][hname][name]; + resources.music['title'].original = false; + break; case "Music.Credits": resources.music['credits'].file = mod["_Path"] + "/" + mod["Hook"][hname][name]; resources.music['credits'].original = false; @@ -86,7 +93,7 @@ function hook_SoundFX(mod, type, hname) { dialog.showMessageBoxSync( { type: "error", - title: "Illegal Instruction", + title: "KMP Mod Loader", message: "On package " + item + ": hook " + hname + " (" + type + "): invalid hook data, EXITING" } ) @@ -138,7 +145,7 @@ function hook_Car(mod, type, hname) { dialog.showMessageBoxSync( { type: "error", - title: "Illegal Instruction", + title: "KMP Mod Loader", message: "On package " + item + ": hook " + hname + " (" + type + "): invalid hook data, EXITING" } ) @@ -160,7 +167,58 @@ function hook_Circuit(mod, type, hname) { dialog.showMessageBoxSync( { type: "error", - title: "Illegal Instruction", + title: "KMP Mod Loader", + message: "On package " + item + ": hook " + hname + " (" + type + "): invalid hook data, EXITING" + } + ) + process.exit(2); + } + } +} + +function hook_API(mod, type, hname) { + console.log(" * KMP-API TypeScript engine: " + item + "$" + hname) + hook = mod["Hook"][hname]; + names = Object.keys(hook); + + for (i in names) { + name = names[i]; + + if (name === "API.Includes") { + if (fs.existsSync(mod["_Path"] + "/" + mod["Hook"][hname][name])) { + if (fs.statSync(mod["_Path"] + "/" + mod["Hook"][hname][name]).isDirectory()) { + flist = fs.readdirSync(mod["_Path"] + "/" + mod["Hook"][hname][name]); + for (file of flist) { + if (file.endsWith(".ts")) { + importedTypeScriptFiles.push({ + file: mod["_Path"] + "/" + mod["Hook"][hname][name] + "/" + file, + pkg: item, + output: item + "--" + file + ".js" + }); + } + } + } else { + importedTypeScriptFiles.push({ + file: mod["_Path"] + "/" + mod["Hook"][hname][name], + pkg: item, + output: item + "--" + mod["Hook"][hname][name] + ".js" + }); + } + } else { + dialog.showMessageBoxSync( + { + type: "error", + title: "KMP Mod Loader", + message: "On package " + item + ": KMP-API includes " + mod["Hook"][hname][name] + " (" + mod["_Path"] + "/" + mod["Hook"][hname][name] + "): no such file or directory, EXITING" + } + ) + process.exit(2); + } + } else { + dialog.showMessageBoxSync( + { + type: "error", + title: "KMP Mod Loader", message: "On package " + item + ": hook " + hname + " (" + type + "): invalid hook data, EXITING" } ) @@ -172,11 +230,11 @@ function hook_Circuit(mod, type, hname) { module.exports = (mod, type, name) => { hook = mod["Hook"][name]; - if (type !== "Kartik.Music" && type !== "Kartik.SoundFX" && type !== "Kartik.Circuit" && type !== "Kartik.Car") { + if (type !== "Kartik.Music" && type !== "Kartik.SoundFX" && type !== "Kartik.Circuit" && type !== "Kartik.Car" && type !== "Kartik.API") { dialog.showMessageBoxSync( { type: "error", - title: "Illegal Instruction", + title: "KMP Mod Loader", message: "On package " + item + ": invalid hook type, EXITING" } ) @@ -193,9 +251,11 @@ module.exports = (mod, type, name) => { case "Kartik.Car": hook_Car(mod, type, name); break; - break; case "Kartik.Circuit": hook_Circuit(mod, type, name); break; + case "Kartik.API": + hook_API(mod, type, name); + break; } } diff --git a/modding/parser.js b/modding/parser.js index 26f5320..2c39055 100644 --- a/modding/parser.js +++ b/modding/parser.js @@ -26,7 +26,7 @@ for (index in list) { dialog.showMessageBoxSync( { type: "error", - title: "Illegal Instruction", + title: "KMP Mod Loader", message: "On package " + item + ": no kartik.ini or kartik.yml file found" } ) @@ -37,13 +37,13 @@ for (index in list) { item = list[index]; parts = item.split("."); - if (parts.length < 2 || parts[0].length > 5 || item.length > 49 || parts.length > 5 || !/^[a-zA-Z0-9.]*$/gm.test(item)) { + if (parts.length < 2 || parts[0].length > 5 || item.length > 49 || parts.length > 7 || !/^[a-zA-Z0-9.]*$/gm.test(item)) { unload(list, item); if (parts.length < 2) { dialog.showMessageBoxSync( { type: "error", - title: "Illegal Instruction", + title: "KMP Mod Loader", message: "On package " + item + ": invalid package name: not enough parts" } ) @@ -52,7 +52,7 @@ for (index in list) { dialog.showMessageBoxSync( { type: "error", - title: "Illegal Instruction", + title: "KMP Mod Loader", message: "On package " + item + ": invalid package name: tld too long" } ) @@ -61,16 +61,16 @@ for (index in list) { dialog.showMessageBoxSync( { type: "error", - title: "Illegal Instruction", + title: "KMP Mod Loader", message: "On package " + item + ": invalid package name: too long" } ) } - if (parts.length > 5) { + if (parts.length > 7) { dialog.showMessageBoxSync( { type: "error", - title: "Illegal Instruction", + title: "KMP Mod Loader", message: "On package " + item + ": invalid package name: too many parts" } ) @@ -79,7 +79,7 @@ for (index in list) { dialog.showMessageBoxSync( { type: "error", - title: "Illegal Instruction", + title: "KMP Mod Loader", message: "On package " + item + ": invalid package name: invalid format" } ) @@ -95,7 +95,7 @@ for (index in list) { dialog.showMessageBoxSync( { type: "error", - title: "Illegal Instruction", + title: "KMP Mod Loader", message: "On package " + item + ": both kartik.ini and kartik.yml found" } ) @@ -114,7 +114,7 @@ for (index in list) { dialog.showMessageBoxSync( { type: "error", - title: "Illegal Instruction", + title: "KMP Mod Loader", message: "On package " + item + ": ini parser error" } ) @@ -128,7 +128,7 @@ for (index in list) { dialog.showMessageBoxSync( { type: "error", - title: "Illegal Instruction", + title: "KMP Mod Loader", message: "On package " + item + ": yaml parser error" } ) @@ -149,7 +149,7 @@ for (index in list) { dialog.showMessageBoxSync( { type: "error", - title: "Illegal Instruction", + title: "KMP Mod Loader", message: "On package " + item + ": invalid root section: " + r } ) @@ -163,7 +163,7 @@ for (index in list) { dialog.showMessageBoxSync( { type: "error", - title: "Illegal Instruction", + title: "KMP Mod Loader", message: "On package " + item + ": invalid meta section: " + r } ) @@ -175,7 +175,7 @@ for (index in list) { dialog.showMessageBoxSync( { type: "error", - title: "Illegal Instruction", + title: "KMP Mod Loader", message: "On package " + item + ": meta sections incomplete" } ) @@ -190,7 +190,7 @@ for (index in list) { dialog.showMessageBoxSync( { type: "error", - title: "Illegal Instruction", + title: "KMP Mod Loader", message: "On package " + item + ": invalid property: " + r } ) @@ -202,7 +202,7 @@ for (index in list) { dialog.showMessageBoxSync( { type: "error", - title: "Illegal Instruction", + title: "KMP Mod Loader", message: "On package " + item + ": properties incomplete" } ) @@ -218,7 +218,7 @@ for (index in list) { dialog.showMessageBoxSync( { type: "error", - title: "Illegal Instruction", + title: "KMP Mod Loader", message: "On package " + item + ": mod made for another version of Kartik" } ) @@ -229,7 +229,7 @@ for (index in list) { dialog.showMessageBoxSync( { type: "error", - title: "Illegal Instruction", + title: "KMP Mod Loader", message: "On package " + item + ": invalid game version" } ) @@ -248,7 +248,7 @@ for (index in list) { dialog.showMessageBoxSync( { type: "error", - title: "Illegal Instruction", + title: "KMP Mod Loader", message: "On package " + item + ": block " + hook + " required by hook " + hookn + " not found" } ) @@ -270,6 +270,7 @@ for (index in list) { mod["_Path"] = homedir + "/.kartik/mods/" + item; + console.log(" * KMP hook: " + item + "$" + hookn) require('./hooks')(mod, hookn, hook); } } diff --git a/music/credits.mp3 b/music/credits.mp3 Binary files differindex 68297c6..5186fbd 100644 --- a/music/credits.mp3 +++ b/music/credits.mp3 diff --git a/music/prepare.mp3 b/music/prepare.mp3 Binary files differindex 6e84627..13f4ded 100644 --- a/music/prepare.mp3 +++ b/music/prepare.mp3 diff --git a/music/title.mp3 b/music/title.mp3 Binary files differindex bc2cbc7..a4e0f29 100644 --- a/music/title.mp3 +++ b/music/title.mp3 diff --git a/music/win.mp3 b/music/win.mp3 Binary files differindex 636a78d..1447d14 100644 --- a/music/win.mp3 +++ b/music/win.mp3 diff --git a/nest/abi.js b/nest/abi.js index b72f964..5945705 100644 --- a/nest/abi.js +++ b/nest/abi.js @@ -1,6 +1,8 @@ const fs = require('fs'); var zlib = require('zlib'); +console.log("\n\nKartik Fox Nest, a compressed and simple data storage for Kartik.\n(c) Minteck, All Rights Reserved\n\n") + module.exports = { export(file, obj) { fs.writeFileSync(file, zlib.deflateSync(Buffer.from(Buffer.from(JSON.stringify(obj)).toString("base64")).toString("base64"))) @@ -19,7 +21,7 @@ module.exports = { return decoded; }, - async generate(file) { + generate(file) { o = { "_version": "<unknown>", "stats": { @@ -40,25 +42,13 @@ module.exports = { }, "auth": null, "config": { - "lang": null, + "lang": "en", "music": true, "online": true, "voice": false } } - slpm = require('os-locale'); - slpw = await slpm(); - slpo = slpw.substr(0, 2); - slng = require('../lang/languages.json'); - if (Object.keys(slng).includes(slpo)) { - dlp = slpo; - } else { - dlp = "en"; - } - - o.config.lang = dlp; - this.export(file, o); }, diff --git a/online/global.js b/online/global.js index 0e4fe32..febe8ab 100644 --- a/online/global.js +++ b/online/global.js @@ -357,7 +357,7 @@ function checkOnlineLogin() { } $("#theirid").keydown(function(e) { - if (e.keyCode === 27 || e.keyCode === 8) { // esc + if (e.keyCode === 27) { // esc $("body").fadeOut(200); setTimeout(() => { location.href = "menu.html?back"; diff --git a/package.json b/package.json index 93490a9..e7d5843 100644 --- a/package.json +++ b/package.json @@ -1 +1 @@ -{"name":"kartik","version":"83fb25f","channel":"git","description":"A multiplatform 2D karting game","main":"app.js","dependencies":{"@electron/remote":"^1.0.4","discord-rpc":"^3.2.0","electron":"^12.0.1","ini":"^1.3.8","jquery":"^3.6.0","open":"^8.2.1","os-locale":"^5.0.0","systeminformation":"^5.7.7","uuid":"^8.3.2","yaml":"^1.10.2"},"scripts":{"test":"node_modules\\electron\\dist\\electron.exe app.js"},"author":"Minteck Projects","license":"GPL-3.0-or-later","serial":"XXX99999999999"}
\ No newline at end of file +{"name":"kartik","version":"79edea3","channel":"git","description":"A multiplatform 2D karting game","main":"app.js","dependencies":{"@electron/remote":"^1.0.4","discord-rpc":"^3.2.0","electron":"^12.0.1","ini":"^1.3.8","jquery":"^3.6.0","open":"^8.2.1","os-locale":"^5.0.0","systeminformation":"^5.7.7","typescript":"^4.3.5","uuid":"^8.3.2","yaml":"^1.10.2"},"scripts":{"test":"node_modules\\electron\\dist\\electron.exe app.js"},"author":"Minteck","license":"GPL-3.0-or-later","serial":"XXX99999999999"}
\ No newline at end of file diff --git a/race/_archived/triangle.html b/race/_archived/triangle.html index 33dcaae..59fe219 100644 --- a/race/_archived/triangle.html +++ b/race/_archived/triangle.html @@ -7,7 +7,7 @@ "fr": "Le triangle des Bermudes", "en": "The Bermuda Triangle" }, - "author": "Minteck Projects" + "author": "Minteck" } </circuit> diff --git a/race/circuits/furry.html b/race/circuits/furry.html index b1c0e9c..1e4c8d5 100644 --- a/race/circuits/furry.html +++ b/race/circuits/furry.html @@ -7,7 +7,7 @@ "fr": "Les petites pattes", "en": "The Little Paws" }, - "author": "Minteck Projects" + "author": "Minteck" } </circuit> @@ -88,7 +88,7 @@ width: 8px; top: 25px; left: 106px; -"></div><div class="wall" style="height: 310px;position: fixed;width: 8px;top: 110px;left: 498px;"></div><div class="wall" style="height: 8px;position: fixed;width: 57px;top: 413px;left: 211px;"></div><div class="wall" style="height: 8px;position: fixed;width: 248px;top: 151px;left: 235px;"></div><div class="wall" style="height: 24px;position: fixed;width: 8px;top: 485px;left: 261px;"></div><div class="wall" style="height: 8px;position: fixed;width: 24px;top: 236px;left: 347px;"></div><div class="wall" style="height: 270px;position: fixed;width: 8px;top: 236px;left: 361px;"></div><div class="wall" style="height: 113px;position: fixed;width: 8px;top: 151px;left: 235px;"></div><div class="wall" style="height: 32px;position: fixed;width: 8px;top: 151px;left: 370px;"></div><div class="wall" style="height: 32px;position: fixed;width: 8px;top: 151px;left: 340px;"></div><div class="wall" style="height: 28px;position: fixed;width: 8px;top: 236px;left: 370px;"></div><div class="wall" style="height: 8px;position: fixed;width: 24px;top: 255px;left: 325px;"></div><div class="wall" style="height: 9px;position: fixed;width: 24px;top: 351px;left: 498px;"></div><div class="wall" style="height: 9px;position: fixed;width: 24px;top: 249px;left: 106px;"></div><div class="wall" style="height: 9px;position: fixed;width: 46px;top: 249px;left: 173px;"></div><div class="wall" style="height: 9px;position: fixed;width: 46px;top: 246px;left: 498px;"></div><div class="wall" style="height: 9px;position: fixed;width: 46px;top: 351px;left: 566px;"></div><div class="wall" style="height: 9px;position: fixed;width: 46px;top: 255px;left: 234px;"></div><div class="wall" style="height: 9px;position: fixed;width: 46px;top: 257px;left: 439px;"></div><div class="wall" style="height: 9px;position: fixed;width: 46px;top: 353px;left: 106px;"></div><div class="wall" style="height: 9px;position: fixed;width: 75px;top: 302px;left: 328px;"></div><div class="wall" style="height: 9px;position: fixed;width: 23px;top: 302px;left: 441px;"></div><div class="wall" style="height: 9px;position: fixed;width: 23px;top: 302px;left: 260px;"></div><div class="wall" style="height: 9px;position: fixed;width: 24px;top: 352px;left: 195px;"></div><div class="wall" style="height: 8px;position: fixed;width: 24px;top: 246px;left: 589px;"></div><div class="wall" style="height: 8px;position: fixed;width: 24px;top: 256px;left: 367px;"></div><div class="wall" style="height: 28px;position: fixed;width: 8px;top: 236px;left: 340px;"></div><div class="wall" style="height: 113px;position: fixed;width: 8px;top: 151px;left: 475px;"></div><div class="wall" style="height: 166px;position: fixed;width: 8px;top: 255px;left: 260px;"></div><div class="wall" style="height: 118px;position: fixed;width: 8px;top: 302px;left: 456px;"></div><div class="wall" style="height: 24px;position: fixed;width: 8px;top: 485px;left: 457px;"></div><div class="wall" style=" +"></div><div class="wall" style="height: 310px;position: fixed;width: 8px;top: 110px;left: 498px;"></div><div class="wall" style="height: 8px;position: fixed;width: 57px;top: 413px;left: 211px;"></div><div class="wall" style="height: 8px;position: fixed;width: 248px;top: 151px;left: 235px;"></div><div class="wall" style="height: 24px;position: fixed;width: 8px;top: 485px;left: 261px;"></div><div class="wall" style="height: 8px;position: fixed;width: 24px;top: 236px;left: 347px;"></div><div class="wall" style="height: 270px;position: fixed;width: 8px;top: 236px;left: 361px;"></div><div class="wall" style="height: 113px;position: fixed;width: 8px;top: 151px;left: 235px;"></div><div class="wall" style="height: 32px;position: fixed;width: 8px;top: 151px;left: 370px;"></div><div class="wall" style="height: 32px;position: fixed;width: 8px;top: 151px;left: 340px;"></div><div class="wall" style="height: 28px;position: fixed;width: 8px;top: 236px;left: 370px;"></div><div class="wall" style="height: 8px;position: fixed;width: 24px;top: 255px;left: 325px;"></div><div class="wall" style="height: 9px;position: fixed;width: 24px;top: 351px;left: 498px;"></div><div class="wall" style="height: 9px;position: fixed;width: 24px;top: 249px;left: 106px;"></div><div class="wall" style="height: 9px;position: fixed;width: 46px;top: 249px;left: 173px;"></div><div class="wall" style="height: 9px;position: fixed;width: 46px;top: 246px;left: 498px;"></div><div class="wall" style="height: 9px;position: fixed;width: 46px;top: 351px;left: 587px;"></div><div class="wall" style="height: 9px;position: fixed;width: 46px;top: 255px;left: 234px;"></div><div class="wall" style="height: 9px;position: fixed;width: 46px;top: 257px;left: 439px;"></div><div class="wall" style="height: 9px;position: fixed;width: 46px;top: 353px;left: 106px;"></div><div class="wall" style="height: 9px;position: fixed;width: 75px;top: 302px;left: 328px;"></div><div class="wall" style="height: 9px;position: fixed;width: 23px;top: 302px;left: 441px;"></div><div class="wall" style="height: 9px;position: fixed;width: 23px;top: 302px;left: 260px;"></div><div class="wall" style="height: 9px;position: fixed;width: 24px;top: 352px;left: 195px;"></div><div class="wall" style="height: 8px;position: fixed;width: 24px;top: 246px;left: 589px;"></div><div class="wall" style="height: 8px;position: fixed;width: 24px;top: 256px;left: 367px;"></div><div class="wall" style="height: 28px;position: fixed;width: 8px;top: 236px;left: 340px;"></div><div class="wall" style="height: 113px;position: fixed;width: 8px;top: 151px;left: 475px;"></div><div class="wall" style="height: 166px;position: fixed;width: 8px;top: 255px;left: 260px;"></div><div class="wall" style="height: 118px;position: fixed;width: 8px;top: 302px;left: 456px;"></div><div class="wall" style="height: 24px;position: fixed;width: 8px;top: 485px;left: 457px;"></div><div class="wall" style=" height: 485px; position: fixed; width: 8px; @@ -112,4 +112,4 @@ width: 20px; top: 0; left: 355px; -" id="barrier"></div></div>
\ No newline at end of file +" id="barrier"></div></div> diff --git a/race/circuits/furry.png b/race/circuits/furry.png Binary files differindex c1d5d46..0e2dc77 100644 --- a/race/circuits/furry.png +++ b/race/circuits/furry.png diff --git a/race/circuits/main.html b/race/circuits/main.html index 5f21eed..2420a83 100644 --- a/race/circuits/main.html +++ b/race/circuits/main.html @@ -7,7 +7,7 @@ "fr": "Un simple carré", "en": "A Simple Square" }, - "author": "Minteck Projects" + "author": "Minteck" } </circuit> diff --git a/race/circuits/snowy.html b/race/circuits/snowy.html index 03ceab8..8254582 100644 --- a/race/circuits/snowy.html +++ b/race/circuits/snowy.html @@ -7,7 +7,7 @@ "fr": "La montagne enneigée", "en": "The Snowy Mountain" }, - "author": "Minteck Projects" + "author": "Minteck" } </circuit> diff --git a/race/circuits/water.html b/race/circuits/water.html index 3e3d6b8..811010f 100644 --- a/race/circuits/water.html +++ b/race/circuits/water.html @@ -7,7 +7,7 @@ "fr": "Attention à l'eau", "en": "Keep out the water" }, - "author": "Minteck Projects" + "author": "Minteck" } </circuit> diff --git a/sfx/gamecrash.wav b/sfx/gamecrash.wav Binary files differnew file mode 100644 index 0000000..4f42092 --- /dev/null +++ b/sfx/gamecrash.wav diff --git a/sfx/intro.mp3 b/sfx/intro.mp3 Binary files differnew file mode 100644 index 0000000..39eeae8 --- /dev/null +++ b/sfx/intro.mp3 diff --git a/typescript/builder.js b/typescript/builder.js new file mode 100644 index 0000000..e3294a1 --- /dev/null +++ b/typescript/builder.js @@ -0,0 +1,50 @@ +const os = require('os'); +const fs = require('fs'); +const { dialog } = require('electron'); + +if (os.platform() === "win32") { + cmd = "typescript\\engine-win32.exe"; +} else { + cmd = "./typescript/engine-" + os.platform(); +} + +fs.copyFileSync("./typescript/interface.ts", homedir + "/.kartik/build/kartik.ts"); + +cp = require('child_process').spawnSync(cmd, [ "./node_modules/typescript/bin/tsc", "--skipLibCheck", "--removeComments", "--sourceMap", "-m", "commonjs", "--target", "es6", homedir + "/.kartik/build/kartik.ts" ], { cwd: KartikRoot }); +if (cp.status !== 0) { + console.error(cp.stdout.toString()); + throw new Error("Subprocess exited with code " + cp.status); +} + +fs.unlinkSync(homedir + "/.kartik/build/kartik.ts"); + +module.exports = (source, destination) => { + if (os.platform() === "win32") { + source = source.replaceAll("/", "\\"); + destination = destination.replaceAll("/", "\\"); + } + + console.log(destination.substr(0, destination.length - 3)); + fs.copyFileSync(source, destination.substr(0, destination.length - 3)); + fs.writeFileSync(destination.substr(0, destination.length - 3), fs.readFileSync(destination.substr(0, destination.length - 3)).toString().replaceAll("$KARTIK:", homedir.replaceAll("\\", "\\\\") + "/.kartik/build/kartik.js")) + cp = require('child_process').spawnSync(cmd, [ "./node_modules/typescript/bin/tsc", "--skipLibCheck", "--removeComments", "--sourceMap", "-m", "commonjs", "--target", "es5", destination.substr(0, destination.length - 3) ], { cwd: KartikRoot }); + if (cp.status !== 0) { + if (cp.stdout !== undefined) { + dialog.showMessageBoxSync( + { + type: "error", + title: "KMP Mod Loader", + message: "On package " + item + ": KMP-API building " + source + ":\n\n" + cp.stdout.toString().trim() + "\n\nEXITING." + } + ) + process.exit(2); + } else { + throw new Error("Subprocess exited with code " + cp.status); + } + } + compiledTypeScriptFiles.push(destination.substr(0, destination.length - 6) + ".js"); + + lines = fs.readFileSync(destination.substr(0, destination.length - 6) + ".js").toString().split("\n"); + lines[1] = ""; + fs.writeFileSync(destination.substr(0, destination.length - 6) + ".js", lines.join("\n")); +}
\ No newline at end of file diff --git a/typescript/engine-darwin b/typescript/engine-darwin Binary files differnew file mode 100644 index 0000000..a09cf1e --- /dev/null +++ b/typescript/engine-darwin diff --git a/typescript/engine-linux b/typescript/engine-linux Binary files differnew file mode 100644 index 0000000..9a7aa3e --- /dev/null +++ b/typescript/engine-linux diff --git a/typescript/engine-win32.exe b/typescript/engine-win32.exe Binary files differnew file mode 100644 index 0000000..9c32378 --- /dev/null +++ b/typescript/engine-win32.exe diff --git a/typescript/interface.ts b/typescript/interface.ts new file mode 100644 index 0000000..28e8219 --- /dev/null +++ b/typescript/interface.ts @@ -0,0 +1,23 @@ +// @ts-nocheck + +let item = { + context: null, + + dom: { + document: null, + window: null, + }, + +}; + +if (typeof HTML !== "undefined") { + if (typeof HTML.document !== "undefined") { + item.dom.document = HTML.document; + } + + if (typeof window !== "undefined") { + item.dom.window = HTML.window; + } +} + +module.exports = item;
\ No newline at end of file diff --git a/typescript/mainloader.js b/typescript/mainloader.js new file mode 100644 index 0000000..6fee294 --- /dev/null +++ b/typescript/mainloader.js @@ -0,0 +1,10 @@ +window.addEventListener("load", () => { + files = require('@electron/remote').getCurrentWindow().modsfiles; + global.HTML = window; + + for (file of files) { + var script = document.createElement('script'); + script.src = "file://" + file.replaceAll("\\", "/"); + document.head.appendChild(script) + } +})
\ No newline at end of file diff --git a/typescript/preloader.js b/typescript/preloader.js new file mode 100644 index 0000000..fae3caf --- /dev/null +++ b/typescript/preloader.js @@ -0,0 +1,5 @@ +files = compiledTypeScriptFiles; + +for (file of files) { + require(file); +}
\ No newline at end of file diff --git a/views/background.jpg b/views/background.jpg Binary files differindex d3e959a..1129efc 100644 --- a/views/background.jpg +++ b/views/background.jpg diff --git a/views/common/compatibilityMode.css b/views/common/compatibilityMode.css index a436549..60c28a2 100644 --- a/views/common/compatibilityMode.css +++ b/views/common/compatibilityMode.css @@ -1,8 +1,6 @@ *:not(#gpuinfo-outer):not(#gpuinfo-inner) { backdrop-filter: none !important; - transition: none !important; opacity: 1 !important; - animation: none !important; } .rain { diff --git a/views/credits.html b/views/credits.html index b045ed4..80c1fe4 100644 --- a/views/credits.html +++ b/views/credits.html @@ -10,7 +10,7 @@ <link rel="stylesheet" href="menu.css"> <title>Kartik</title> <script src="../crash/client.js"></script> - <script src="./script/global_compatlayer.js"></script> + <script src="./script/global_compatlayer.js"></script><script src="../typescript/mainloader.js"></script> <script src="../sfx/sfx.js"></script> <script> require('@electron/remote').getCurrentWindow().dstate = lang.discord.credits[0]; @@ -42,7 +42,7 @@ <!-- START credits --> <h2>Kartik, a 2D car racing game</h2> - <p>© Minteck Projects/Cutefox Studios. All assets are licensed under their original license rather than Kartik's license.</p> + <p>© Minteck/Cutefox Studios. All assets are licensed under their original license rather than Kartik's license.</p> <p class="technical"><script src="./script/credits_technical.js"></script></p> made by<br> @@ -52,7 +52,7 @@ <p class="cred-content">Minteck</p> <p class="cred-title">Base Assets</p> - <p class="cred-content">Minteck<br>Redman 054</p> + <p class="cred-content">Minteck</p> <p class="cred-title">Narrator Character</p> <p class="cred-content"><b>Averi</b> by fiddle (@fiddleafox on Twitter)</p> @@ -186,7 +186,7 @@ </div> <p class="cred-title">Testing</p> - <p class="cred-content">Minteck<br>Romain<br>Redman 054<br>Oxymillion</p> + <p class="cred-content">Minteck<br>Romain<br>Oxymillion</p> <p class="cred-title">Libraries</p> <div class="cred-content" style="display:grid;grid-template-columns: 1fr 1fr 1fr; text-align:center;"><script src="./script/credits_libs.js"></script></div> diff --git a/views/game.html b/views/game.html index cefd720..6de20ef 100644 --- a/views/game.html +++ b/views/game.html @@ -10,7 +10,7 @@ <link rel="stylesheet" href="game.css"> <title>Kartik</title> <script src="../crash/client.js"></script> - <script src="./script/global_compatlayer.js"></script> + <script src="./script/global_compatlayer.js"></script><script src="../typescript/mainloader.js"></script> <script src="../sfx/sfx.js"></script> <script> require('@electron/remote').getCurrentWindow().dstate = lang.discord.game[0]; diff --git a/views/intro.html b/views/intro.html index d09ee15..1962b94 100644 --- a/views/intro.html +++ b/views/intro.html @@ -10,7 +10,7 @@ <link rel="stylesheet" href="common/blur.css"> <link rel="stylesheet" href="intro.css"> <script src="../crash/client.js"></script> - <script src="./script/global_compatlayer.js"></script> + <script src="./script/global_compatlayer.js"></script><script src="../typescript/mainloader.js"></script> <script> require('@electron/remote').getCurrentWindow().dstate = lang.discord.intro[0]; require('@electron/remote').getCurrentWindow().ddetails = lang.discord.intro[1]; @@ -31,23 +31,14 @@ </script> <script src="./script/intro_media.js"></script> <div id="box" style="display:none;position:fixed;inset:0;"> - <div class="hero"> - <div class="hero-inner"></div> - </div> - <div style="margin-left: auto;margin-right: auto;width: max-content;margin-top: 100px;"> - <img alt="full-logo" src="../logo/full.png" style="height: 96px;"> - </div> - <div id="intro" style="position: fixed;bottom: 0;height: 120px;width: 100%;background: rgba(0, 0, 0, .5);" class="clickable" onclick="ev = document.createEvent('Event');ev.initEvent('keypress');ev.which = ev.keyCode = 13;document.body.dispatchEvent(ev);"> - <span id="progress" style="color: white;position: fixed;left: 0;right: 0;text-align: center;bottom: 50px;"> - <script>document.write(lang.intro[0]);</script> - </span> - <script src="./script/intro_message.js"></script> - </div> </div> <script src="./script/intro_global.js"></script> <script>info("LoadWindow", "Launching start-up procedure");</script> <script src="./script/client_fullscreen.js"></script> + <script> + location.href = "menu.html"; + </script> </body> </html> diff --git a/views/intro.mp4 b/views/intro.mp4 Binary files differnew file mode 100644 index 0000000..e947f0a --- /dev/null +++ b/views/intro.mp4 diff --git a/views/loader.html b/views/loader.html index f18edd4..3dbaf4d 100644 --- a/views/loader.html +++ b/views/loader.html @@ -4,6 +4,7 @@ <script>if (typeof require !== "undefined") {native = true;try{global.native = true;}catch(e){}} else {native = false;try{global.native = false;}catch(e){}}if (!native){global = window;}if (native){kresources=require('@electron/remote').getCurrentWindow().resources;trackEvent=require('@electron/remote').getCurrentWindow().trackEvent;}info=(_a,b)=>{console.info(b);};warn=(_a,b)=>{console.warn(b);};error=(_a,b)=>{console.error(b);};const Nest = require("../nest/abi");currentNest = require('@electron/remote').getCurrentWindow().nest;</script> <script src="../lang/loader.js"></script> <script src="../scenario/client.js"></script> + <script src="./script/global_compatlayer.js"></script><script src="../typescript/mainloader.js"></script> <meta charset="UTF-8"> <title>Kartik</title> <link rel="stylesheet" href="common/fonts.css"> @@ -14,7 +15,7 @@ } </script> </head> -<body style="background:#000000;margin:0;height:100%;width:100%;"> +<body style="background:#f4f3f4;margin:0;height:100%;width:100%;"> <script>info("MainWindow", "Rendering initial frame..."); if (native) { @@ -22,10 +23,16 @@ } </script> - <img id="imgpreload" src="common/banner.gif" style="height:100%;width:auto;opacity:0;position:fixed;pointer-events:none;"> - <div style="display:flex;align-items:center;justify-content:center;inset: 0;height: 100%;background:#fed1ae;overflow:hidden;"> - <img id="banner" src="../logo/itch/banner.jpg" style="height:100%;width:auto;"> + <div id="banner-outer" style="display:flex;align-items:center;justify-content:center;inset: 0;height: 100%;background:#f4f3f4;overflow:hidden;"> + <img id="banner" src="../logo/full-alt.png" alt="" style="display:none;height:auto;width:380px;"> + <script> + const $ = require('jquery'); + $("#banner").fadeIn(200); + </script> </div> + <video style="display: none;position:fixed;inset:0;width: 100%;height: 100%;background: #f4f3f4;" id="intro-video"> + <source src="intro.mp4"> + </video> <script> document.write(`<div style="position: fixed;bottom: 20px;right: 20px;font-size: 12px;padding: 10px 20px;background: lightblue;border-radius: 5px;transition: all 200ms;display:none;" id="updates">${lang.updates.wait}</div>`); </script> diff --git a/views/menu.css b/views/menu.css index ca90e93..f9697a7 100644 --- a/views/menu.css +++ b/views/menu.css @@ -151,6 +151,9 @@ .item-icon { filter: invert(1); vertical-align: middle; + display: inline-block; + margin-top: 3px; + margin-bottom: -1px; } div.services.home { @@ -221,4 +224,25 @@ span#copyright { backdrop-filter: blur(10px); background: rgba(0, 0, 0, 0.5); left: 10vw; +} + +.item-text { + vertical-align: middle; + margin-top: 8px; + display: inline-block; +} + +@media (max-height: 600px) { + img[alt="full-logo"][src="../logo/full.png"].full-logo { + margin-top: 16px !important; + } + + span#copyright.copyright { + bottom: 14px !important; + } +} + +body { + height: calc(100vh / 1.2); + overflow: hidden; }
\ No newline at end of file diff --git a/views/menu.html b/views/menu.html index b2a0129..d06eba6 100644 --- a/views/menu.html +++ b/views/menu.html @@ -10,11 +10,15 @@ <link rel="stylesheet" href="menu.css"> <title>Kartik</title> <script src="../crash/client.js"></script> - <script src="./script/global_compatlayer.js"></script> + <script src="./script/global_compatlayer.js"></script><script src="../typescript/mainloader.js"></script> <script src="./script/menu_login.js"></script> <script src="../sfx/sfx.js"></script> - <link rel="stylesheet" href="rain/rainstyle.css"> + <script src="./rain/snow.js"></script> <script> + snowStorm.flakesMaxActive = 80; + snowStorm.followMouse = false; + snowStorm.snowStick = false; + scenar("intro", "neutral"); if (!require('@electron/remote').getCurrentWindow().debug) { document.write('<link rel="stylesheet" href="common/mouse.css">'); @@ -29,47 +33,47 @@ } </script> - <div id="box" style="display: none;background:#222;position:fixed;top:0;left:0;right:0;bottom:0;"> + <div id="box" style="display: none;background:#9abecd;position:fixed;top:0;left:0;right:0;bottom:0;"> <div id="loggingIn" style="position: fixed;color: white;background: rgba(0, 0, 0, .5);z-index: 999999999999;top: 0;left: 0;right: 0;bottom: 0;display: none;align-items: center;justify-content: center;backdrop-filter: blur(10px);"><script>document.write(lang.polymer.logging);</script></div> <div class="rain front-row"></div> <div class="rain back-row"></div> - <div style="width: 100%;height: 100%;background-color: #001743;background-image: url('./menu.jpg');background-size: cover;position: fixed;z-index: -1;"></div> - <img alt="full-logo" src="../logo/full.png" style="margin-left: 50px;margin-top: 30px;height: 96px;"> + <div style="width: 100%;height: 100%;opacity:.5;background-image: url('./menu.jpg');background-size: cover;position: fixed;z-index: -1;"></div> + <img alt="full-logo" class="full-logo" src="../logo/full.png" style="margin-left: 50px;margin-top: 30px;height: 96px;"> <div id="services-background"></div> <div class="services home"> <div class="items"> <ul> - <li class="selected"><span class="item"><a href="#" id="single"><img class="item-icon" src="../icons/singleplayer.svg"> <script>document.write(lang.menu.titles[0])</script></a></span></li> + <li class="selected"><span class="item"><a href="#" id="single"><img class="item-icon" src="../icons/singleplayer.svg"> <span class="item-text"><script>document.write(lang.menu.titles[0])</script></span></a></span></li> <script id="prefill"> if (require('@electron/remote').getCurrentWindow().online) { - document.write(`<li><span class="item"><a href="#" id="play"><img class="item-icon" src="../icons/local.svg"> ${lang.online.menu.local}</a></span></li>`) - document.write(`<li><span class="item"><a href="#" id="online"><img class="item-icon" src="../icons/online.svg"> ${lang.online.menu.online}</a></span></li>`); - document.write(`<li><span class="item"><a href="#" id="settings"><img class="item-icon" src="../icons/settings.svg"> ${lang.menu.titles[2]}</a></span></li>`); + document.write(`<li><span class="item"><a href="#" id="play"><img class="item-icon" src="../icons/local.svg"> <span class="item-text">${lang.online.menu.local}</span></a></span></li>`) + document.write(`<li><span class="item"><a href="#" id="online"><img class="item-icon" src="../icons/online.svg"> <span class="item-text">${lang.online.menu.online}</span></a></span></li>`); + document.write(`<li><span class="item"><a href="#" id="settings"><img class="item-icon" src="../icons/settings.svg"> <span class="item-text">${lang.menu.titles[2]}</span></a></span></li>`); } else { - document.write(`<li><span class="item"><a href="#" id="play"><img class="item-icon" src="../icons/local.svg"> ${lang.online.menu.local}</a></span></li>`) - document.write(`<li><span class="item"><a href="#" id="settings"><img class="item-icon" src="../icons/settings.svg"> ${lang.menu.titles[2]}</a></span></li>`); + document.write(`<li><span class="item"><a href="#" id="play"><img class="item-icon" src="../icons/local.svg"> <span class="item-text">${lang.online.menu.local}</span></a></span></li>`) + document.write(`<li><span class="item"><a href="#" id="settings"><img class="item-icon" src="../icons/settings.svg"> <span class="item-text">${lang.menu.titles[2]}</span></a></span></li>`); } document.getElementById('prefill').outerHTML = ""; </script> - <li><span class="item"><a href="#" id="stats"><img class="item-icon" src="../icons/stats.svg"> <script>document.write(lang.stats.menu)</script></a></span></li> - <li><span class="item"><a href="#" id="quit"><img class="item-icon" src="../icons/exit.svg"> <script>document.write(lang.menu.titles[4])</script></a></span></li> + <li><span class="item"><a href="#" id="stats"><img class="item-icon" src="../icons/stats.svg"> <span class="item-text"><script>document.write(lang.stats.menu)</script></span></a></span></li> + <li><span class="item"><a href="#" id="quit"><img class="item-icon" src="../icons/exit.svg"> <span class="item-text"><script>document.write(lang.menu.titles[4])</script></span></a></span></li> </ul> </div> </div> <div style="position: fixed;right: 16px;top: 79px;color: white;background: rgba(0, 0, 0, .5);font-size: 10px;text-align:left;z-index:999999999;padding: 10px;border-radius: 10px;width: 189px;" id="gpuinfo"> - <span style="text-align:center;display:block;font-weight: bold;margin-bottom: 5px;">GPU Support Status</span> + <span style="text-align:center;display:block;font-weight: bold;margin-bottom: 5px;"><script>document.write(lang.polymer.gpu);</script></span> <div style="margin-bottom: 10px;height: 16px;width: 100%;background: rgba(47, 47, 47, .5);border-radius: 999px;"> <div style="height: 16px;background: rgba(128, 0, 0, .5);border-radius: 999px;width: 0;" id="gpuinfo_progressbar"></div> </div> <span id="gpusupportperc" style="display: block;text-align: center;">0%</span> - <div id="gpuinfo-model" style="opacity: .25;padding-top: 5px;text-align: center;">Generic GPU</div> - <div id="gpuinfo-vram" style="opacity: .25;padding-top: 5px;text-align: center;">0 MiB VRAM</div> + <div id="gpuinfo-model" style="opacity: .25;padding-top: 5px;text-align: center;">-</div> + <div id="gpuinfo-vram" style="opacity: .25;padding-top: 5px;text-align: center;">- VRAM</div> <span id="gpuinfo-details" style="border-top:1px solid rgba(255, 255, 255, .25);"> - <div id="gpuinfo-outer" style="opacity: .25;padding-top: 5px;text-align: center;">↓ Hold Shift for details</div> + <div id="gpuinfo-outer" style="opacity: .25;padding-top: 5px;text-align: center;">↓ <script>document.write(lang.polymer.gpuShift);</script></div> <div id="gpuinfo-inner" style="font-family:monospace;opacity:0;height:0;"> <script src="./script/menu_gpuinfo.js"></script> </div> @@ -89,7 +93,7 @@ <span id="loginIntro" style="padding-top: 10px;display: inline-block;"><script>document.write(lang.polymer.loginIntro);</script></span> </div> - <div style="position: fixed;right: 16px;top: 16px;color: white;background: rgba(0, 0, 0, .5);font-size: 10px;z-index:999999999;padding-left: 10px;border-radius: 10px;width: 199px;text-align:center;display: none;backdrop-filter: blur(10px);grid-template-columns: 1fr 48px;" id="loginUser"><div style=" + <div style="position: fixed;right: 16px;top: 16px;color: white;font-size: 10px;z-index:999999999;padding-left: 10px;border-radius: 10px;width: 199px;text-align:center;display: none;backdrop-filter: blur(10px);grid-template-columns: 1fr 48px;" id="loginUser"><div style=" text-align: left; padding-top: 13px; padding-left: 5px; @@ -106,12 +110,11 @@ " alt=" " id="kto-picture"> </div> - <span id="copyright">© <script src="./script/menu_copyright.js"></script></span> + <span id="copyright" class="copyright">© <script src="./script/menu_copyright.js"></script></span> </div> <script src="./script/menu_music.js"></script> </body> <script src="./script/menu_global.js"></script> -<script src="./rain/rainscript.js"></script> <script src="./script/client_fullscreen.js"></script> </html> diff --git a/views/menu.jpg b/views/menu.jpg Binary files differindex 0ac1665..ade8fdd 100644 --- a/views/menu.jpg +++ b/views/menu.jpg diff --git a/views/online.html b/views/online.html index cd1cff5..f1c20c1 100644 --- a/views/online.html +++ b/views/online.html @@ -9,7 +9,7 @@ <link rel="stylesheet" href="common/fonts.css"> <link rel="stylesheet" href="common/blur.css"> <script src="../crash/client.js"></script> - <script src="./script/global_compatlayer.js"></script> + <script src="./script/global_compatlayer.js"></script><script src="../typescript/mainloader.js"></script> <script src="../sfx/sfx.js"></script> <script> if (!require('@electron/remote').getCurrentWindow().debug) { diff --git a/views/rain/snow.js b/views/rain/snow.js new file mode 100644 index 0000000..014dad0 --- /dev/null +++ b/views/rain/snow.js @@ -0,0 +1,666 @@ +/** @license + * DHTML Snowstorm! JavaScript-based snow for web pages + * Making it snow on the internets since 2003. You're welcome. + * ----------------------------------------------------------- + * Version 1.44.20131208 (Previous rev: 1.44.20131125) + * Copyright (c) 2007, Scott Schiller. All rights reserved. + * Code provided under the BSD License + * http://schillmania.com/projects/snowstorm/license.txt + */ + +/*jslint nomen: true, plusplus: true, sloppy: true, vars: true, white: true */ +/*global window, document, navigator, clearInterval, setInterval */ + +var snowStorm = (function(window, document) { + + // --- common properties --- + + this.autoStart = true; // Whether the snow should start automatically or not. + this.excludeMobile = true; // Snow is likely to be bad news for mobile phones' CPUs (and batteries.) Enable at your own risk. + this.flakesMax = 128; // Limit total amount of snow made (falling + sticking) + this.flakesMaxActive = 64; // Limit amount of snow falling at once (less = lower CPU use) + this.animationInterval = 33; // Theoretical "miliseconds per frame" measurement. 20 = fast + smooth, but high CPU use. 50 = more conservative, but slower + this.useGPU = true; // Enable transform-based hardware acceleration, reduce CPU load. + this.className = null; // CSS class name for further customization on snow elements + this.excludeMobile = true; // Snow is likely to be bad news for mobile phones' CPUs (and batteries.) By default, be nice. + this.flakeBottom = null; // Integer for Y axis snow limit, 0 or null for "full-screen" snow effect + this.followMouse = true; // Snow movement can respond to the user's mouse + this.snowColor = '#fff'; // Don't eat (or use?) yellow snow. + this.snowCharacter = '•'; // • = bullet, · is square on some systems etc. + this.snowStick = true; // Whether or not snow should "stick" at the bottom. When off, will never collect. + this.targetElement = null; // element which snow will be appended to (null = document.body) - can be an element ID eg. 'myDiv', or a DOM node reference + this.useMeltEffect = true; // When recycling fallen snow (or rarely, when falling), have it "melt" and fade out if browser supports it + this.useTwinkleEffect = false; // Allow snow to randomly "flicker" in and out of view while falling + this.usePositionFixed = false; // true = snow does not shift vertically when scrolling. May increase CPU load, disabled by default - if enabled, used only where supported + this.usePixelPosition = false; // Whether to use pixel values for snow top/left vs. percentages. Auto-enabled if body is position:relative or targetElement is specified. + + // --- less-used bits --- + + this.freezeOnBlur = true; // Only snow when the window is in focus (foreground.) Saves CPU. + this.flakeLeftOffset = 0; // Left margin/gutter space on edge of container (eg. browser window.) Bump up these values if seeing horizontal scrollbars. + this.flakeRightOffset = 0; // Right margin/gutter space on edge of container + this.flakeWidth = 8; // Max pixel width reserved for snow element + this.flakeHeight = 8; // Max pixel height reserved for snow element + this.vMaxX = 5; // Maximum X velocity range for snow + this.vMaxY = 4; // Maximum Y velocity range for snow + this.zIndex = 0; // CSS stacking order applied to each snowflake + + // --- "No user-serviceable parts inside" past this point, yadda yadda --- + + var storm = this, + features, + // UA sniffing and backCompat rendering mode checks for fixed position, etc. + isIE = navigator.userAgent.match(/msie/i), + isIE6 = navigator.userAgent.match(/msie 6/i), + isMobile = navigator.userAgent.match(/mobile|opera m(ob|in)/i), + isBackCompatIE = (isIE && document.compatMode === 'BackCompat'), + noFixed = (isBackCompatIE || isIE6), + screenX = null, screenX2 = null, screenY = null, scrollY = null, docHeight = null, vRndX = null, vRndY = null, + windOffset = 1, + windMultiplier = 2, + flakeTypes = 6, + fixedForEverything = false, + targetElementIsRelative = false, + opacitySupported = (function(){ + try { + document.createElement('div').style.opacity = '0.5'; + } catch(e) { + return false; + } + return true; + }()), + didInit = false, + docFrag = document.createDocumentFragment(); + + features = (function() { + + var getAnimationFrame; + + /** + * hat tip: paul irish + * http://paulirish.com/2011/requestanimationframe-for-smart-animating/ + * https://gist.github.com/838785 + */ + + function timeoutShim(callback) { + window.setTimeout(callback, 1000/(storm.animationInterval || 20)); + } + + var _animationFrame = (window.requestAnimationFrame || + window.webkitRequestAnimationFrame || + window.mozRequestAnimationFrame || + window.oRequestAnimationFrame || + window.msRequestAnimationFrame || + timeoutShim); + + // apply to window, avoid "illegal invocation" errors in Chrome + getAnimationFrame = _animationFrame ? function() { + return _animationFrame.apply(window, arguments); + } : null; + + var testDiv; + + testDiv = document.createElement('div'); + + function has(prop) { + + // test for feature support + var result = testDiv.style[prop]; + return (result !== undefined ? prop : null); + + } + + // note local scope. + var localFeatures = { + + transform: { + ie: has('-ms-transform'), + moz: has('MozTransform'), + opera: has('OTransform'), + webkit: has('webkitTransform'), + w3: has('transform'), + prop: null // the normalized property value + }, + + getAnimationFrame: getAnimationFrame + + }; + + localFeatures.transform.prop = ( + localFeatures.transform.w3 || + localFeatures.transform.moz || + localFeatures.transform.webkit || + localFeatures.transform.ie || + localFeatures.transform.opera + ); + + testDiv = null; + + return localFeatures; + + }()); + + this.timer = null; + this.flakes = []; + this.disabled = false; + this.active = false; + this.meltFrameCount = 20; + this.meltFrames = []; + + this.setXY = function(o, x, y) { + + if (!o) { + return false; + } + + if (storm.usePixelPosition || targetElementIsRelative) { + + o.style.left = (x - storm.flakeWidth) + 'px'; + o.style.top = (y - storm.flakeHeight) + 'px'; + + } else if (noFixed) { + + o.style.right = (100-(x/screenX*100)) + '%'; + // avoid creating vertical scrollbars + o.style.top = (Math.min(y, docHeight-storm.flakeHeight)) + 'px'; + + } else { + + if (!storm.flakeBottom) { + + // if not using a fixed bottom coordinate... + o.style.right = (100-(x/screenX*100)) + '%'; + o.style.bottom = (100-(y/screenY*100)) + '%'; + + } else { + + // absolute top. + o.style.right = (100-(x/screenX*100)) + '%'; + o.style.top = (Math.min(y, docHeight-storm.flakeHeight)) + 'px'; + + } + + } + + }; + + this.events = (function() { + + var old = (!window.addEventListener && window.attachEvent), slice = Array.prototype.slice, + evt = { + add: (old?'attachEvent':'addEventListener'), + remove: (old?'detachEvent':'removeEventListener') + }; + + function getArgs(oArgs) { + var args = slice.call(oArgs), len = args.length; + if (old) { + args[1] = 'on' + args[1]; // prefix + if (len > 3) { + args.pop(); // no capture + } + } else if (len === 3) { + args.push(false); + } + return args; + } + + function apply(args, sType) { + var element = args.shift(), + method = [evt[sType]]; + if (old) { + element[method](args[0], args[1]); + } else { + element[method].apply(element, args); + } + } + + function addEvent() { + apply(getArgs(arguments), 'add'); + } + + function removeEvent() { + apply(getArgs(arguments), 'remove'); + } + + return { + add: addEvent, + remove: removeEvent + }; + + }()); + + function rnd(n,min) { + if (isNaN(min)) { + min = 0; + } + return (Math.random()*n)+min; + } + + function plusMinus(n) { + return (parseInt(rnd(2),10)===1?n*-1:n); + } + + this.randomizeWind = function() { + var i; + vRndX = plusMinus(rnd(storm.vMaxX,0.2)); + vRndY = rnd(storm.vMaxY,0.2); + if (this.flakes) { + for (i=0; i<this.flakes.length; i++) { + if (this.flakes[i].active) { + this.flakes[i].setVelocities(); + } + } + } + }; + + this.scrollHandler = function() { + var i; + // "attach" snowflakes to bottom of window if no absolute bottom value was given + scrollY = (storm.flakeBottom ? 0 : parseInt(window.scrollY || document.documentElement.scrollTop || (noFixed ? document.body.scrollTop : 0), 10)); + if (isNaN(scrollY)) { + scrollY = 0; // Netscape 6 scroll fix + } + if (!fixedForEverything && !storm.flakeBottom && storm.flakes) { + for (i=0; i<storm.flakes.length; i++) { + if (storm.flakes[i].active === 0) { + storm.flakes[i].stick(); + } + } + } + }; + + this.resizeHandler = function() { + if (window.innerWidth || window.innerHeight) { + screenX = window.innerWidth - 16 - storm.flakeRightOffset; + screenY = (storm.flakeBottom || window.innerHeight); + } else { + screenX = (document.documentElement.clientWidth || document.body.clientWidth || document.body.scrollWidth) - (!isIE ? 8 : 0) - storm.flakeRightOffset; + screenY = storm.flakeBottom || document.documentElement.clientHeight || document.body.clientHeight || document.body.scrollHeight; + } + docHeight = document.body.offsetHeight; + screenX2 = parseInt(screenX/2,10); + }; + + this.resizeHandlerAlt = function() { + screenX = storm.targetElement.offsetWidth - storm.flakeRightOffset; + screenY = storm.flakeBottom || storm.targetElement.offsetHeight; + screenX2 = parseInt(screenX/2,10); + docHeight = document.body.offsetHeight; + }; + + this.freeze = function() { + // pause animation + if (!storm.disabled) { + storm.disabled = 1; + } else { + return false; + } + storm.timer = null; + }; + + this.resume = function() { + if (storm.disabled) { + storm.disabled = 0; + } else { + return false; + } + storm.timerInit(); + }; + + this.toggleSnow = function() { + if (!storm.flakes.length) { + // first run + storm.start(); + } else { + storm.active = !storm.active; + if (storm.active) { + storm.show(); + storm.resume(); + } else { + storm.stop(); + storm.freeze(); + } + } + }; + + this.stop = function() { + var i; + this.freeze(); + for (i=0; i<this.flakes.length; i++) { + this.flakes[i].o.style.display = 'none'; + } + storm.events.remove(window,'scroll',storm.scrollHandler); + storm.events.remove(window,'resize',storm.resizeHandler); + if (storm.freezeOnBlur) { + if (isIE) { + storm.events.remove(document,'focusout',storm.freeze); + storm.events.remove(document,'focusin',storm.resume); + } else { + storm.events.remove(window,'blur',storm.freeze); + storm.events.remove(window,'focus',storm.resume); + } + } + }; + + this.show = function() { + var i; + for (i=0; i<this.flakes.length; i++) { + this.flakes[i].o.style.display = 'block'; + } + }; + + this.SnowFlake = function(type,x,y) { + var s = this; + this.type = type; + this.x = x||parseInt(rnd(screenX-20),10); + this.y = (!isNaN(y)?y:-rnd(screenY)-12); + this.vX = null; + this.vY = null; + this.vAmpTypes = [1,1.2,1.4,1.6,1.8]; // "amplification" for vX/vY (based on flake size/type) + this.vAmp = this.vAmpTypes[this.type] || 1; + this.melting = false; + this.meltFrameCount = storm.meltFrameCount; + this.meltFrames = storm.meltFrames; + this.meltFrame = 0; + this.twinkleFrame = 0; + this.active = 1; + this.fontSize = (10+(this.type/5)*10); + this.o = document.createElement('div'); + this.o.innerHTML = storm.snowCharacter; + if (storm.className) { + this.o.setAttribute('class', storm.className); + } + this.o.style.color = storm.snowColor; + this.o.style.position = (fixedForEverything?'fixed':'absolute'); + if (storm.useGPU && features.transform.prop) { + // GPU-accelerated snow. + this.o.style[features.transform.prop] = 'translate3d(0px, 0px, 0px)'; + } + this.o.style.width = storm.flakeWidth+'px'; + this.o.style.height = storm.flakeHeight+'px'; + this.o.style.fontFamily = 'arial,verdana'; + this.o.style.cursor = 'default'; + this.o.style.overflow = 'hidden'; + this.o.style.fontWeight = 'normal'; + this.o.style.zIndex = storm.zIndex; + docFrag.appendChild(this.o); + + this.refresh = function() { + if (isNaN(s.x) || isNaN(s.y)) { + // safety check + return false; + } + storm.setXY(s.o, s.x, s.y); + }; + + this.stick = function() { + if (noFixed || (storm.targetElement !== document.documentElement && storm.targetElement !== document.body)) { + s.o.style.top = (screenY+scrollY-storm.flakeHeight)+'px'; + } else if (storm.flakeBottom) { + s.o.style.top = storm.flakeBottom+'px'; + } else { + s.o.style.display = 'none'; + s.o.style.bottom = '0%'; + s.o.style.position = 'fixed'; + s.o.style.display = 'block'; + } + }; + + this.vCheck = function() { + if (s.vX>=0 && s.vX<0.2) { + s.vX = 0.2; + } else if (s.vX<0 && s.vX>-0.2) { + s.vX = -0.2; + } + if (s.vY>=0 && s.vY<0.2) { + s.vY = 0.2; + } + }; + + this.move = function() { + var vX = s.vX*windOffset, yDiff; + s.x += vX; + s.y += (s.vY*s.vAmp); + if (s.x >= screenX || screenX-s.x < storm.flakeWidth) { // X-axis scroll check + s.x = 0; + } else if (vX < 0 && s.x-storm.flakeLeftOffset < -storm.flakeWidth) { + s.x = screenX-storm.flakeWidth-1; // flakeWidth; + } + s.refresh(); + yDiff = screenY+scrollY-s.y+storm.flakeHeight; + if (yDiff<storm.flakeHeight) { + s.active = 0; + if (storm.snowStick) { + s.stick(); + } else { + s.recycle(); + } + } else { + if (storm.useMeltEffect && s.active && s.type < 3 && !s.melting && Math.random()>0.998) { + // ~1/1000 chance of melting mid-air, with each frame + s.melting = true; + s.melt(); + // only incrementally melt one frame + // s.melting = false; + } + if (storm.useTwinkleEffect) { + if (s.twinkleFrame < 0) { + if (Math.random() > 0.97) { + s.twinkleFrame = parseInt(Math.random() * 8, 10); + } + } else { + s.twinkleFrame--; + if (!opacitySupported) { + s.o.style.visibility = (s.twinkleFrame && s.twinkleFrame % 2 === 0 ? 'hidden' : 'visible'); + } else { + s.o.style.opacity = (s.twinkleFrame && s.twinkleFrame % 2 === 0 ? 0 : 1); + } + } + } + } + }; + + this.animate = function() { + // main animation loop + // move, check status, die etc. + s.move(); + }; + + this.setVelocities = function() { + s.vX = vRndX+rnd(storm.vMaxX*0.12,0.1); + s.vY = vRndY+rnd(storm.vMaxY*0.12,0.1); + }; + + this.setOpacity = function(o,opacity) { + if (!opacitySupported) { + return false; + } + o.style.opacity = opacity; + }; + + this.melt = function() { + if (!storm.useMeltEffect || !s.melting) { + s.recycle(); + } else { + if (s.meltFrame < s.meltFrameCount) { + s.setOpacity(s.o,s.meltFrames[s.meltFrame]); + s.o.style.fontSize = s.fontSize-(s.fontSize*(s.meltFrame/s.meltFrameCount))+'px'; + s.o.style.lineHeight = storm.flakeHeight+2+(storm.flakeHeight*0.75*(s.meltFrame/s.meltFrameCount))+'px'; + s.meltFrame++; + } else { + s.recycle(); + } + } + }; + + this.recycle = function() { + s.o.style.display = 'none'; + s.o.style.position = (fixedForEverything?'fixed':'absolute'); + s.o.style.bottom = 'auto'; + s.setVelocities(); + s.vCheck(); + s.meltFrame = 0; + s.melting = false; + s.setOpacity(s.o,1); + s.o.style.padding = '0px'; + s.o.style.margin = '0px'; + s.o.style.fontSize = s.fontSize+'px'; + s.o.style.lineHeight = (storm.flakeHeight+2)+'px'; + s.o.style.textAlign = 'center'; + s.o.style.verticalAlign = 'baseline'; + s.x = parseInt(rnd(screenX-storm.flakeWidth-20),10); + s.y = parseInt(rnd(screenY)*-1,10)-storm.flakeHeight; + s.refresh(); + s.o.style.display = 'block'; + s.active = 1; + }; + + this.recycle(); // set up x/y coords etc. + this.refresh(); + + }; + + this.snow = function() { + var active = 0, flake = null, i, j; + for (i=0, j=storm.flakes.length; i<j; i++) { + if (storm.flakes[i].active === 1) { + storm.flakes[i].move(); + active++; + } + if (storm.flakes[i].melting) { + storm.flakes[i].melt(); + } + } + if (active<storm.flakesMaxActive) { + flake = storm.flakes[parseInt(rnd(storm.flakes.length),10)]; + if (flake.active === 0) { + flake.melting = true; + } + } + if (storm.timer) { + features.getAnimationFrame(storm.snow); + } + }; + + this.mouseMove = function(e) { + if (!storm.followMouse) { + return true; + } + var x = parseInt(e.clientX,10); + if (x<screenX2) { + windOffset = -windMultiplier+(x/screenX2*windMultiplier); + } else { + x -= screenX2; + windOffset = (x/screenX2)*windMultiplier; + } + }; + + this.createSnow = function(limit,allowInactive) { + var i; + for (i=0; i<limit; i++) { + storm.flakes[storm.flakes.length] = new storm.SnowFlake(parseInt(rnd(flakeTypes),10)); + if (allowInactive || i>storm.flakesMaxActive) { + storm.flakes[storm.flakes.length-1].active = -1; + } + } + storm.targetElement.appendChild(docFrag); + }; + + this.timerInit = function() { + storm.timer = true; + storm.snow(); + }; + + this.init = function() { + var i; + for (i=0; i<storm.meltFrameCount; i++) { + storm.meltFrames.push(1-(i/storm.meltFrameCount)); + } + storm.randomizeWind(); + storm.createSnow(storm.flakesMax); // create initial batch + storm.events.add(window,'resize',storm.resizeHandler); + storm.events.add(window,'scroll',storm.scrollHandler); + if (storm.freezeOnBlur) { + if (isIE) { + storm.events.add(document,'focusout',storm.freeze); + storm.events.add(document,'focusin',storm.resume); + } else { + storm.events.add(window,'blur',storm.freeze); + storm.events.add(window,'focus',storm.resume); + } + } + storm.resizeHandler(); + storm.scrollHandler(); + if (storm.followMouse) { + storm.events.add(isIE?document:window,'mousemove',storm.mouseMove); + } + storm.animationInterval = Math.max(20,storm.animationInterval); + storm.timerInit(); + }; + + this.start = function(bFromOnLoad) { + if (!didInit) { + didInit = true; + } else if (bFromOnLoad) { + // already loaded and running + return true; + } + if (typeof storm.targetElement === 'string') { + var targetID = storm.targetElement; + storm.targetElement = document.getElementById(targetID); + if (!storm.targetElement) { + throw new Error('Snowstorm: Unable to get targetElement "'+targetID+'"'); + } + } + if (!storm.targetElement) { + storm.targetElement = (document.body || document.documentElement); + } + if (storm.targetElement !== document.documentElement && storm.targetElement !== document.body) { + // re-map handler to get element instead of screen dimensions + storm.resizeHandler = storm.resizeHandlerAlt; + //and force-enable pixel positioning + storm.usePixelPosition = true; + } + storm.resizeHandler(); // get bounding box elements + storm.usePositionFixed = (storm.usePositionFixed && !noFixed && !storm.flakeBottom); // whether or not position:fixed is to be used + if (window.getComputedStyle) { + // attempt to determine if body or user-specified snow parent element is relatlively-positioned. + try { + targetElementIsRelative = (window.getComputedStyle(storm.targetElement, null).getPropertyValue('position') === 'relative'); + } catch(e) { + // oh well + targetElementIsRelative = false; + } + } + fixedForEverything = storm.usePositionFixed; + if (screenX && screenY && !storm.disabled) { + storm.init(); + storm.active = true; + } + }; + + function doDelayedStart() { + window.setTimeout(function() { + storm.start(true); + }, 20); + // event cleanup + storm.events.remove(isIE?document:window,'mousemove',doDelayedStart); + } + + function doStart() { + if (!storm.excludeMobile || !isMobile) { + doDelayedStart(); + } + // event cleanup + storm.events.remove(window, 'load', doStart); + } + + // hooks for starting the snow + if (storm.autoStart) { + storm.events.add(window, 'load', doStart, false); + } + + return this; + +}(window, document));
\ No newline at end of file diff --git a/views/script/core_chart.js b/views/script/core_chart.js index 059c818..2f8a521 100644 --- a/views/script/core_chart.js +++ b/views/script/core_chart.js @@ -2,7 +2,7 @@ setInterval(() => { try { currentMemory = process.memoryUsage().rss; currentMemoryMib = (((currentMemory)/1024)/1024).toFixed(2); - if ((((currentMemory)/1024)/1024) > 250) { + if ((((currentMemory)/1024)/1024) > ((require('os').totalmem() / 1000000) / 4)) { throw new Error("Out of memory"); } @@ -66,5 +66,9 @@ setInterval(() => { } else { document.title="Kartik"+require('@electron/remote').getCurrentWindow().channel+require('./package.json').version + eaid; } - } catch (e) {} + } catch (e) { + if (e.message === "Out of memory") { + throw e; + } + } }, 1000)
\ No newline at end of file diff --git a/views/script/core_crash.js b/views/script/core_crash.js new file mode 100644 index 0000000..d24ec2d --- /dev/null +++ b/views/script/core_crash.js @@ -0,0 +1,21 @@ +global.gameCrashed = false; +crashSound = new Audio("./sfx/gamecrash.wav"); + +function destroy() { + global.gameCrashed = true; + crashSound.play(); + require('@electron/remote').webContents.fromId(webview.getWebContentsId()).forcefullyCrashRenderer(); + try { musicElement.pause(); } catch (e) {} +} + +function spawnError(crashReport) { + document.getElementById("error-outer").style.display = "flex"; + document.getElementById("crash-dump").value = crashReport; + destroy(); +} + +const crashHandler = require('electron').ipcRenderer; + +crashHandler.on('crashreport', (event, args) => { + spawnError(args); +})
\ No newline at end of file diff --git a/views/script/core_fullscreen.js b/views/script/core_fullscreen.js index 69f9e45..f2c540d 100644 --- a/views/script/core_fullscreen.js +++ b/views/script/core_fullscreen.js @@ -1,9 +1,40 @@ -$(document).keydown(function(e) { - if (e.keyCode === 122 || e.keyCode === 121 || e.keyCode === 112) { // F11/F1/F10 - if (!require('@electron/remote').getCurrentWindow().fullScreen && require('@electron/remote').getCurrentWindow().fullScreenable) { - require('@electron/remote').getCurrentWindow().setFullScreen(true); - } else { - require('@electron/remote').getCurrentWindow().setFullScreen(false); +window.addEventListener("load", () => { + require('@electron/remote').getCurrentWindow().show(); + + const Nest = require("./nest/abi"); + + $(document).keydown(function(e) { + if (e.keyCode === 122 || e.keyCode === 121 || e.keyCode === 112) { // F11/F1/F10 + if (!require('@electron/remote').getCurrentWindow().fullScreen && require('@electron/remote').getCurrentWindow().fullScreenable) { + require('@electron/remote').getCurrentWindow().setFullScreen(true); + } else { + require('@electron/remote').getCurrentWindow().setFullScreen(false); + } } + }) + + $(document).keydown(function(e) { + currentNest = Nest.load(homedir + "/.kartik/current.kfn"); + + if (e.keyCode === 122 || e.keyCode === 121 || e.keyCode === 112) { + if (currentNest.config.fullscreen) { + currentNest.config.fullscreen = false; + Nest.export(homedir + "/.kartik/current.kfn", currentNest); + require('electron').ipcRenderer.send("reloadNest") + } else { + currentNest.config.fullscreen = true; + Nest.export(homedir + "/.kartik/current.kfn", currentNest); + require('electron').ipcRenderer.send("reloadNest"); + } + } + }) + + currentNest = Nest.load(homedir + "/.kartik/current.kfn"); + if (currentNest.config.fullscreen) { + require('@electron/remote').getCurrentWindow().setFullScreen(true); + } else { + currentNest.config.fullscreen = false; + Nest.export(homedir + "/.kartik/current.kfn", currentNest); + require('electron').ipcRenderer.send("reloadNest") } })
\ No newline at end of file diff --git a/views/script/core_stats.js b/views/script/core_stats.js index c8d26df..930c776 100644 --- a/views/script/core_stats.js +++ b/views/script/core_stats.js @@ -6,42 +6,46 @@ timer = null; current = null; webview.addEventListener('dom-ready', () => { - if (webview.getURL() !== current) { - if (session !== null) { - require('electron').ipcRenderer.send('addstats', { catalog: "times", key: session, add: Math.floor((new Date() - timer)/1000) }); + try { + if (webview.getURL() !== current) { + if (session !== null) { + require('electron').ipcRenderer.send('addstats', { catalog: "times", key: session, add: Math.floor((new Date() - timer)/1000) }); - session = null; - timer = null; - current = null; + session = null; + timer = null; + current = null; + } } - } - if (webview.getURL().endsWith("game.html")) { // Local - session = "local"; - timer = new Date(); - current = webview.getURL(); - } - if (webview.getURL().endsWith("game.html?sp")) { // Singleplayer - session = "single"; - timer = new Date(); - current = webview.getURL(); - } - if (webview.getURL().endsWith("game.html?online")) { // Online - session = "online"; - timer = new Date(); - current = webview.getURL(); - } + if (webview.getURL().endsWith("game.html")) { // Local + session = "local"; + timer = new Date(); + current = webview.getURL(); + } + if (webview.getURL().endsWith("game.html?sp")) { // Singleplayer + session = "single"; + timer = new Date(); + current = webview.getURL(); + } + if (webview.getURL().endsWith("game.html?online")) { // Online + session = "online"; + timer = new Date(); + current = webview.getURL(); + } + } catch (e) {} }) window.addEventListener("beforeunload", function(e){ - if (session !== null) { - require('electron').ipcRenderer.send('addstatsandclose', { catalog: "times", key: session, add: Math.floor((new Date() - timer)/1000) }); + try { + if (session !== null) { + require('electron').ipcRenderer.send('addstatsandclose', { catalog: "times", key: session, add: Math.floor((new Date() - timer)/1000) }); - session = null; - timer = null; - current = null; + session = null; + timer = null; + current = null; - e.preventDefault(); - return false; - } + e.preventDefault(); + return false; + } + } catch (e) {} }, false);
\ No newline at end of file diff --git a/views/script/core_viewer.js b/views/script/core_viewer.js index 389bf41..eac3766 100644 --- a/views/script/core_viewer.js +++ b/views/script/core_viewer.js @@ -1,24 +1,28 @@ const webview = document.getElementById('wb'); -webview.addEventListener('dom-ready', () => { - document.getElementById('dummyloader').style.display = "none"; - require('@electron/remote').getCurrentWindow().log(" * " + webview.getURL()); - try { - if (require('@electron/remote').getCurrentWindow().debug) { - info("MainWindow", "Opening debugging tools..."); - webview.openDevTools(); - } - } catch (e) {} -}) - -webview.addEventListener('dom-ready', () => { - setInterval(() => { +try { + webview.addEventListener('dom-ready', () => { + document.getElementById('dummyloader').style.display = "none"; + require('@electron/remote').getCurrentWindow().log(" * " + webview.getURL()); + require('@electron/remote').getCurrentWindow().focus(); + webview.focus(); try { - if (webview.isCrashed()) { - require('@electron/remote').getCurrentWindow().log(" * Compositing engine crashed!"); - error("MainWindow", "Subcontainer crashed"); - crash(new Error("Webview crashed")); + if (require('@electron/remote').getCurrentWindow().debug) { + info("MainWindow", "Opening debugging tools..."); + webview.openDevTools(); } } catch (e) {} - }, 2000) -})
\ No newline at end of file + }) + + webview.addEventListener('dom-ready', () => { + setInterval(() => { + try { + if (webview.isCrashed() && !gameCrashed) { + require('@electron/remote').getCurrentWindow().log(" * Compositing engine crashed!"); + error("MainWindow", "Subcontainer crashed"); + crash(new Error("Webview crashed")); + } + } catch (e) {} + }, 2000) + }) +} catch (e) {}
\ No newline at end of file diff --git a/views/script/loader_global.js b/views/script/loader_global.js index db70d3b..7543268 100644 --- a/views/script/loader_global.js +++ b/views/script/loader_global.js @@ -3,7 +3,7 @@ window.addEventListener('load', () => { if (native) { setTimeout(() => { setTimeout(() => { - if (native) {global.$ = require('jquery');} else {var script = document.createElement('script');script.src = '../webinit/jquery.js';script.type = 'text/javascript';document.getElementsByTagName('head')[0].appendChild(script);} + $("#progress").fadeOut(500); setTimeout(() => { window.fetch("https://kartik.hopto.org/latest.php?v=" + require('@electron/remote').getCurrentWindow().update).then((data) => { @@ -25,18 +25,19 @@ window.addEventListener('load', () => { } } setTimeout(() => { - document.getElementById('banner').style.width = "380px"; - document.getElementById('banner').style.height = "auto"; - document.getElementById('banner').src = "common/banner.gif"; - introsfx = new Audio("../sfx/newintro.mp3"); - introsfx.play() - introsfx.onended = () => { - $("body").fadeOut(500); - setTimeout(() => { - info("LoadWindow", "Switching control to MenuWindow"); - location.href = "intro.html"; - }, 1000) - } + $("#banner-outer").fadeOut(200); + $("#intro-video").fadeIn(200); + setTimeout(() => { + introsfx = document.getElementById("intro-video"); + introsfx.play() + introsfx.onended = () => { + $("body").fadeOut(500); + setTimeout(() => { + info("LoadWindow", "Switching control to MenuWindow"); + location.href = "intro.html"; + }, 1000) + } + }, 200) }, 2000) }).catch((e) => { console.warn(e); @@ -44,10 +45,31 @@ window.addEventListener('load', () => { document.getElementById('updates').innerText = lang.updates.error; require('@electron/remote').getCurrentWindow().webContents.send("notification", {title: lang.polymer.updateError[0], message: lang.polymer.updateError[1]}); setTimeout(() => { - document.getElementById('banner').style.width = "380px"; - document.getElementById('banner').style.height = "auto"; - document.getElementById('banner').src = "common/banner.gif"; - introsfx = new Audio("../sfx/newintro.mp3"); + $("#banner-outer").fadeOut(200); + $("#intro-video").fadeIn(200); + setTimeout(() => { + introsfx = document.getElementById("intro-video"); + introsfx.play() + introsfx.onended = () => { + $("body").fadeOut(500); + setTimeout(() => { + info("LoadWindow", "Switching control to MenuWindow"); + location.href = "intro.html"; + }, 1000) + } + }, 200) + }, 2000) + }); + }).catch((e) => { + console.warn(e); + document.getElementById('updates').style.backgroundColor = "lightcoral"; + document.getElementById('updates').innerText = lang.updates.error; + require('@electron/remote').getCurrentWindow().webContents.send("notification", {title: lang.polymer.updateError[0], message: lang.polymer.updateError[1]}); + setTimeout(() => { + $("#banner-outer").fadeOut(200); + $("#intro-video").fadeIn(200); + setTimeout(() => { + introsfx = document.getElementById("intro-video"); introsfx.play() introsfx.onended = () => { $("body").fadeOut(500); @@ -56,18 +78,19 @@ window.addEventListener('load', () => { location.href = "intro.html"; }, 1000) } - }, 2000) - }); - }).catch((e) => { - console.warn(e); - document.getElementById('updates').style.backgroundColor = "lightcoral"; - document.getElementById('updates').innerText = lang.updates.error; - require('@electron/remote').getCurrentWindow().webContents.send("notification", {title: lang.polymer.updateError[0], message: lang.polymer.updateError[1]}); + }, 200) + }, 2000) + }); + }).catch((e) => { + console.warn(e); + document.getElementById('updates').style.backgroundColor = "lightcoral"; + document.getElementById('updates').innerText = lang.updates.error; + require('@electron/remote').getCurrentWindow().webContents.send("notification", {title: lang.polymer.updateError[0], message: lang.polymer.updateError[1]}); + setTimeout(() => { + $("#banner-outer").fadeOut(200); + $("#intro-video").fadeIn(200); setTimeout(() => { - document.getElementById('banner').style.width = "380px"; - document.getElementById('banner').style.height = "auto"; - document.getElementById('banner').src = "common/banner.gif"; - introsfx = new Audio("../sfx/newintro.mp3"); + introsfx = document.getElementById("intro-video"); introsfx.play() introsfx.onended = () => { $("body").fadeOut(500); @@ -76,46 +99,28 @@ window.addEventListener('load', () => { location.href = "intro.html"; }, 1000) } - }, 2000) - }); - }).catch((e) => { - console.warn(e); - document.getElementById('updates').style.backgroundColor = "lightcoral"; - document.getElementById('updates').innerText = lang.updates.error; - require('@electron/remote').getCurrentWindow().webContents.send("notification", {title: lang.polymer.updateError[0], message: lang.polymer.updateError[1]}); - setTimeout(() => { - document.getElementById('banner').style.width = "380px"; - document.getElementById('banner').style.height = "auto"; - document.getElementById('banner').src = "common/banner.gif"; - introsfx = new Audio("../sfx/newintro.mp3"); - introsfx.play() - introsfx.onended = () => { - $("body").fadeOut(500); - setTimeout(() => { - info("LoadWindow", "Switching control to MenuWindow"); - location.href = "intro.html"; - }, 1000) - } + }, 200) }, 2000) }); }, 2000) }, 3000) }, 1000) } else { - if (native) {global.$ = require('jquery');} else {var script = document.createElement('script');script.src = '../webinit/jquery.js';script.type = 'text/javascript';document.getElementsByTagName('head')[0].appendChild(script);} + setTimeout(() => { - document.getElementById('banner').style.width = "380px"; - document.getElementById('banner').style.height = "auto"; - document.getElementById('banner').src = "common/banner.gif"; - introsfx = new Audio("../sfx/newintro.mp3"); - introsfx.play() - introsfx.onended = () => { - $("body").fadeOut(500); - setTimeout(() => { - info("LoadWindow", "Switching control to MenuWindow"); - location.href = "intro.html"; - }, 1000) - } + $("#banner-outer").fadeOut(200); + $("#intro-video").fadeIn(200); + setTimeout(() => { + introsfx = document.getElementById("intro-video"); + introsfx.play() + introsfx.onended = () => { + $("body").fadeOut(500); + setTimeout(() => { + info("LoadWindow", "Switching control to MenuWindow"); + location.href = "intro.html"; + }, 1000) + } + }, 200) }, 5000) } }, 2000) diff --git a/views/script/menu_copyright.js b/views/script/menu_copyright.js index 35b322a..2b38844 100644 --- a/views/script/menu_copyright.js +++ b/views/script/menu_copyright.js @@ -1,5 +1,5 @@ if (new Date().getFullYear() === 2021) { - document.write(new Date().getFullYear() + " Minteck Projects"); + document.write(new Date().getFullYear() + " Minteck"); } else { - document.write("2021-" + new Date().getFullYear() + " Minteck Projects"); + document.write("2021-" + new Date().getFullYear() + " Minteck"); }
\ No newline at end of file diff --git a/views/script/menu_global.js b/views/script/menu_global.js index 8561fe3..14a924f 100644 --- a/views/script/menu_global.js +++ b/views/script/menu_global.js @@ -14,6 +14,9 @@ $(document).keydown(function(e) { if (loggingIn) { return; } if (keysEnabled) { + if (e.ctrlKey && e.keyCode === 13) { // ctrl+enter + throw new RangeError("Manually initiated crash"); + } if (e.keyCode === 13 || e.keyCode === 88 || e.keyCode === 32) { // enter if ($(".services").is(":visible")) { selectOption(); diff --git a/views/script/menu_login.js b/views/script/menu_login.js index 7f50101..2af88b2 100644 --- a/views/script/menu_login.js +++ b/views/script/menu_login.js @@ -54,7 +54,7 @@ function startLogin() { loggingIn = false; document.getElementById('loggingIn').style.display = "none"; currentNest.auth = playerData; - Nest.export(homedir + "/.kartik/current.kfn", currentNest); + Nest.export(homedir + "/.kartik/current.kfn", currentNest);require('electron').ipcRenderer.send("reloadNest") keysEnabled = false; require('electron').ipcRenderer.send('prefademusic', ""); $("#box").fadeOut(500); @@ -109,49 +109,101 @@ window.addEventListener('load', () => { }) function postOnlineMode() { - if (currentNest.auth === null || !onlineMode) { - $(document).keydown(function(e) { - if (e.keyCode === 76 && !loggingIn && onlineMode) { - startLogin(); + try { + if (currentNest.auth === null || !onlineMode) { + $(document).keydown(function(e) { + if (e.keyCode === 76 && !loggingIn && onlineMode) { + startLogin(); + } + }) + } else { + authData = currentNest.auth; + + document.getElementById('loginIntro').style.display = "none"; + document.getElementById('loginUser').style.display = "grid"; + + olevel = $.ajax({ + type: "GET", + url: 'https://kartik.hopto.org/online/ingame/api/profile.level.php?kartik_online_token=' + authData.token, + async: false, + error: (e) => { throw e; } + }).responseText.trim() - 1 + 1; + + if (authData.level > olevel) { + $.ajax({ + type: "GET", + url: 'https://kartik.hopto.org/online/ingame/api/set.level.php?kartik_online_token=' + authData.token + "&level=" + authData.level, + async: false, + error: (e) => { throw e; } + }); + } else if (authData.level < olevel) { + authData.level = $.ajax({ + type: "GET", + url: 'https://kartik.hopto.org/online/ingame/api/profile.level.php?kartik_online_token=' + authData.token, + async: false, + error: (e) => { throw e; } + }).responseText.trim() - 1 + 1; + currentNest.auth = authData; + Nest.export(homedir + "/.kartik/current.kfn", currentNest);require('electron').ipcRenderer.send("reloadNest") } - }) - } else { - authData = currentNest.auth; - document.getElementById('loginIntro').style.display = "none"; - document.getElementById('loginUser').style.display = "grid"; + ostats = JSON.parse($.ajax({ + type: "GET", + url: 'https://kartik.hopto.org/online/ingame/api/profile.stats.php?kartik_online_token=' + authData.token, + async: false, + error: (e) => { throw e; } + }).responseText.trim()) - olevel = $.ajax({ - type: "GET", - url: 'https://kartik.hopto.org/online/ingame/api/profile.level.php?kartik_online_token=' + authData.token, - async: false, - error: (e) => { throw e; } - }).responseText.trim() - 1 + 1; + if (ostats === null) { + cstats = currentNest.stats; + } else { + cstats = {}; + + for (group in currentNest.stats) { + cstats[group] = {}; + + for (item in currentNest.stats[group]) { + if (ostats[group][item]) { + if (ostats[group][item] > currentNest.stats[group][item]) { + cstats[group][item] = ostats[group][item]; + } else { + cstats[group][item] = currentNest.stats[group][item]; + } + } else { + cstats[group][item] = currentNest.stats[group][item]; + } + } + } + } - if (authData.level > olevel) { $.ajax({ type: "GET", - url: 'https://kartik.hopto.org/online/ingame/api/set.level.php?kartik_online_token=' + authData.token + "&level=" + authData.level, + url: 'https://kartik.hopto.org/online/ingame/api/set.stats.php?kartik_online_token=' + authData.token + "&stats=" + Buffer.from(JSON.stringify(cstats)).toString("base64"), async: false, error: (e) => { throw e; } }); - } else if (authData.level < olevel) { - authData.level = $.ajax({ + + currentNest.stats = JSON.parse($.ajax({ type: "GET", - url: 'https://kartik.hopto.org/online/ingame/api/profile.level.php?kartik_online_token=' + authData.token, + url: 'https://kartik.hopto.org/online/ingame/api/profile.stats.php?kartik_online_token=' + authData.token, async: false, error: (e) => { throw e; } - }).responseText.trim() - 1 + 1; - currentNest.auth = authData; - Nest.export(homedir + "/.kartik/current.kfn", currentNest); - } + }).responseText.trim()); + Nest.export(homedir + "/.kartik/current.kfn", currentNest);require('electron').ipcRenderer.send("reloadNest") - document.getElementById('kto-picture').src = authData.picture; - document.getElementById('kto-username').innerText = authData.name; - if (authData.level < 200) { - document.getElementById('kto-level').innerText = authData.level; - } else { - document.getElementById('kto-level').innerText = lang.polymer.ktoMaxLevel; + document.getElementById('kto-picture').src = authData.picture; + document.getElementById('kto-username').innerText = authData.name; + if (authData.level < 200) { + document.getElementById('kto-level').innerText = authData.level; + } else { + document.getElementById('kto-level').innerText = lang.polymer.ktoMaxLevel; + } } + } catch (e) { + require('@electron/remote').getCurrentWindow().webContents.send("notification", {title: lang.polymer.error[0], message: lang.polymer.error[1]}); + console.error(e); + onlineMode = false; + document.getElementById("loginIntro").innerText = lang.polymer.error[2]; + document.getElementById("online").parentElement.parentElement.outerHTML = ""; } }
\ No newline at end of file diff --git a/views/script/settings_global.js b/views/script/settings_global.js index e284585..90f1f6e 100644 --- a/views/script/settings_global.js +++ b/views/script/settings_global.js @@ -46,22 +46,22 @@ $(document).keydown(function(e) { if (document.getElementById("setting-music").innerText === "1") { document.getElementById("setting-music").innerText = "0"; currentNest.config.music = false; - Nest.export(homedir + "/.kartik/current.kfn", currentNest); + Nest.export(homedir + "/.kartik/current.kfn", currentNest);require('electron').ipcRenderer.send("reloadNest") } else { document.getElementById("setting-music").innerText = "1"; currentNest.config.music = true; - Nest.export(homedir + "/.kartik/current.kfn", currentNest); + Nest.export(homedir + "/.kartik/current.kfn", currentNest);require('electron').ipcRenderer.send("reloadNest") } } if (id === "voice") { if (document.getElementById("setting-voice").innerText === "1") { document.getElementById("setting-voice").innerText = "0"; currentNest.config.music = false; - Nest.export(homedir + "/.kartik/current.kfn", currentNest); + Nest.export(homedir + "/.kartik/current.kfn", currentNest);require('electron').ipcRenderer.send("reloadNest") } else { document.getElementById("setting-voice").innerText = "1"; currentNest.config.music = true; - Nest.export(homedir + "/.kartik/current.kfn", currentNest); + Nest.export(homedir + "/.kartik/current.kfn", currentNest);require('electron').ipcRenderer.send("reloadNest") } } if (id === "lang") { @@ -86,7 +86,7 @@ $(document).keydown(function(e) { if (ci !== -1 && ni !== -1) { document.getElementById("setting-lang").innerText = slng[slst[ni]]; currentNest.config.lang = slst[ni]; - Nest.export(homedir + "/.kartik/current.kfn", currentNest); + Nest.export(homedir + "/.kartik/current.kfn", currentNest);require('electron').ipcRenderer.send("reloadNest") require('@electron/remote').getCurrentWindow().lp = slst[ni]; } } diff --git a/views/settings.html b/views/settings.html index 4799527..0addaf3 100644 --- a/views/settings.html +++ b/views/settings.html @@ -10,7 +10,7 @@ <link rel="stylesheet" href="menu.css"> <title>Kartik</title> <script src="../crash/client.js"></script> - <script src="./script/global_compatlayer.js"></script> + <script src="./script/global_compatlayer.js"></script><script src="../typescript/mainloader.js"></script> <script src="../sfx/sfx.js"></script> <script> if (!require('@electron/remote').getCurrentWindow().debug) { diff --git a/views/stats.html b/views/stats.html index 92183ab..3b23571 100644 --- a/views/stats.html +++ b/views/stats.html @@ -9,7 +9,7 @@ <link rel="stylesheet" href="common/fonts.css"> <link rel="stylesheet" href="common/blur.css"> <script src="../crash/client.js"></script> - <script src="./script/global_compatlayer.js"></script> + <script src="./script/global_compatlayer.js"></script><script src="../typescript/mainloader.js"></script> <script src="../sfx/sfx.js"></script> <script> if (!require('@electron/remote').getCurrentWindow().debug) { diff --git a/views/win.html b/views/win.html index 9b0cafb..c9892e7 100644 --- a/views/win.html +++ b/views/win.html @@ -9,7 +9,7 @@ <link rel="stylesheet" href="common/fonts.css"> <link rel="stylesheet" href="common/blur.css"> <script src="../crash/client.js"></script> - <script src="./script/global_compatlayer.js"></script> + <script src="./script/global_compatlayer.js"></script><script src="../typescript/mainloader.js"></script> <script src="../sfx/sfx.js"></script> <script> if (!require('@electron/remote').getCurrentWindow().debug) { |