diff options
author | Minteck <nekostarfan@gmail.com> | 2021-06-05 19:27:48 +0200 |
---|---|---|
committer | Minteck <nekostarfan@gmail.com> | 2021-06-05 19:27:48 +0200 |
commit | 8cf5cefe6e91a5a1ed6eeaae4d94760d84c304a6 (patch) | |
tree | 7096b67b189c0220826123c7d5b121752545d140 /modding | |
download | kartik-client-8cf5cefe6e91a5a1ed6eeaae4d94760d84c304a6.tar.gz kartik-client-8cf5cefe6e91a5a1ed6eeaae4d94760d84c304a6.tar.bz2 kartik-client-8cf5cefe6e91a5a1ed6eeaae4d94760d84c304a6.zip |
Presque sortie du jeu
Diffstat (limited to 'modding')
-rw-r--r-- | modding/hooks.js | 201 | ||||
-rw-r--r-- | modding/parser.js | 277 | ||||
-rw-r--r-- | modding/resources.js | 65 |
3 files changed, 543 insertions, 0 deletions
diff --git a/modding/hooks.js b/modding/hooks.js new file mode 100644 index 0000000..d0ee779 --- /dev/null +++ b/modding/hooks.js @@ -0,0 +1,201 @@ +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") { + dialog.showMessageBoxSync( + { + type: "error", + title: "Illegal Instruction", + message: "On package " + item + ": hook " + hname + " (" + type + "): invalid hook data, EXITING" + } + ) + process.exit(2); + } else { + switch (name) { + case "Music.Start": + resources.music['start'].file = mod["_Path"] + "/" + mod["Hook"][hname][name]; + resources.music['start'].original = false; + break; + case "Music.Title": + 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; + break; + case "Music.Win": + resources.music['win'].file = mod["_Path"] + "/" + mod["Hook"][hname][name]; + resources.music['win'].original = false; + break; + case "Music.Prepare": + resources.music['prepare'].file = mod["_Path"] + "/" + mod["Hook"][hname][name]; + resources.music['prepare'].original = false; + break; + case "Music.Game1": + resources.music['game1'].file = mod["_Path"] + "/" + mod["Hook"][hname][name]; + resources.music['game1'].original = false; + break; + case "Music.Game2": + resources.music['game2'].file = mod["_Path"] + "/" + mod["Hook"][hname][name]; + resources.music['game2'].original = false; + break; + case "Music.Game3": + resources.music['game3'].file = mod["_Path"] + "/" + mod["Hook"][hname][name]; + resources.music['game3'].original = false; + break; + case "Music.Game4": + resources.music['game4'].file = mod["_Path"] + "/" + mod["Hook"][hname][name]; + resources.music['game4'].original = false; + break; + case "Music.Game5": + resources.music['game5'].file = mod["_Path"] + "/" + mod["Hook"][hname][name]; + resources.music['game5'].original = false; + break; + case "Music.Game6": + resources.music['game6'].file = mod["_Path"] + "/" + mod["Hook"][hname][name]; + resources.music['game6'].original = false; + break; + case "Music.Game7": + resources.music['game7'].file = mod["_Path"] + "/" + mod["Hook"][hname][name]; + resources.music['game7'].original = false; + break; + case "Music.Game8": + resources.music['game8'].file = mod["_Path"] + "/" + mod["Hook"][hname][name]; + resources.music['game8'].original = false; + break; + case "Music.Game9": + resources.music['game9'].file = mod["_Path"] + "/" + mod["Hook"][hname][name]; + resources.music['game9'].original = false; + break; + } + } + } +} + +function hook_SoundFX(mod, type, hname) { + hook = mod["Hook"][hname]; + names = Object.keys(hook); + + for (i in names) { + name = names[i]; + if (name !== "SFX.Click" && name !== "SFX.Crash" && name !== "SFX.Intro" && name !== "SFX.Last" && name !== "SFX.Menu" && name !== "SFX.Pass" && name !== "SFX.Pause" && name !== "SFX.Start" && name !== "SFX.Win") { + dialog.showMessageBoxSync( + { + type: "error", + title: "Illegal Instruction", + message: "On package " + item + ": hook " + hname + " (" + type + "): invalid hook data, EXITING" + } + ) + process.exit(2); + } else { + switch (name) { + case "SFX.Click": + resources.sfx['click'] = mod["_Path"] + "/" + mod["Hook"][hname][name]; + break; + case "SFX.Crash": + resources.sfx['crash'] = mod["_Path"] + "/" + mod["Hook"][hname][name]; + break; + case "SFX.Intro": + resources.sfx['intro'] = mod["_Path"] + "/" + mod["Hook"][hname][name]; + break; + case "SFX.Last": + resources.sfx['last'] = mod["_Path"] + "/" + mod["Hook"][hname][name]; + break; + case "SFX.Menu": + resources.sfx['menu'] = mod["_Path"] + "/" + mod["Hook"][hname][name]; + break; + case "SFX.Pass": + resources.sfx['pass'] = mod["_Path"] + "/" + mod["Hook"][hname][name]; + break; + case "SFX.Pause": + resources.sfx['pause'] = mod["_Path"] + "/" + mod["Hook"][hname][name]; + break; + case "SFX.Start": + resources.sfx['start'] = mod["_Path"] + "/" + mod["Hook"][hname][name]; + break; + case "SFX.Win": + resources.sfx['win'] = mod["_Path"] + "/" + mod["Hook"][hname][name]; + break; + } + } + } +} + +function hook_Car(mod, type, hname) { + hook = mod["Hook"][hname]; + names = Object.keys(hook); + + for (i in names) { + name = names[i]; + + if (name.startsWith("Car.")) { + resources.cars[name.substr(4)] = mod["_Path"] + "/" + mod["Hook"][hname][name]; + } else { + dialog.showMessageBoxSync( + { + type: "error", + title: "Illegal Instruction", + message: "On package " + item + ": hook " + hname + " (" + type + "): invalid hook data, EXITING" + } + ) + process.exit(2); + } + } +} + +function hook_Circuit(mod, type, hname) { + hook = mod["Hook"][hname]; + names = Object.keys(hook); + + for (i in names) { + name = names[i]; + + if (name.startsWith("Circuit.")) { + resources.races[name.substr(4)] = mod["_Path"] + "/" + mod["Hook"][hname][name] + ".html"; + } else { + dialog.showMessageBoxSync( + { + type: "error", + title: "Illegal Instruction", + message: "On package " + item + ": hook " + hname + " (" + type + "): invalid hook data, EXITING" + } + ) + process.exit(2); + } + } +} + +module.exports = (mod, type, name) => { + hook = mod["Hook"][name]; + + if (type !== "Kartik.Music" && type !== "Kartik.SoundFX" && type !== "Kartik.Circuit" && type !== "Kartik.Car") { + dialog.showMessageBoxSync( + { + type: "error", + title: "Illegal Instruction", + message: "On package " + item + ": invalid hook type, EXITING" + } + ) + process.exit(2); + } + + switch (type) { + case "Kartik.Music": + hook_Music(mod, type, name); + break; + case "Kartik.SoundFX": + hook_SoundFX(mod, type, name); + break; + case "Kartik.Car": + hook_Car(mod, type, name); + break; + break; + case "Kartik.Circuit": + hook_Circuit(mod, type, name); + break; + } +} diff --git a/modding/parser.js b/modding/parser.js new file mode 100644 index 0000000..26f5320 --- /dev/null +++ b/modding/parser.js @@ -0,0 +1,277 @@ +const fs = require('fs'); +const os = require('os'); +const ini = require('ini'); +const YAML = require('yaml'); +const { dialog } = require('electron'); +const semver = require('semver'); + +function unload(arr) { + var what, a = arguments, L = a.length, ax; + while (L > 1 && arr.length) { + what = a[--L]; + while ((ax= arr.indexOf(what)) !== -1) { + arr.splice(ax, 1); + } + } + return arr; +} + +list = fs.readdirSync(homedir + "/.kartik/mods"); + +for (index in list) { + item = list[index]; + + if (!fs.existsSync(homedir + "/.kartik/mods/" + item + "/kartik.ini") && !fs.existsSync(homedir + "/.kartik/mods/" + item + "/kartik.yml")) { + unload(list, item); + dialog.showMessageBoxSync( + { + type: "error", + title: "Illegal Instruction", + message: "On package " + item + ": no kartik.ini or kartik.yml file found" + } + ) + } +} + +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)) { + unload(list, item); + if (parts.length < 2) { + dialog.showMessageBoxSync( + { + type: "error", + title: "Illegal Instruction", + message: "On package " + item + ": invalid package name: not enough parts" + } + ) + } + if (parts[0].length > 5) { + dialog.showMessageBoxSync( + { + type: "error", + title: "Illegal Instruction", + message: "On package " + item + ": invalid package name: tld too long" + } + ) + } + if (item.length > 49) { + dialog.showMessageBoxSync( + { + type: "error", + title: "Illegal Instruction", + message: "On package " + item + ": invalid package name: too long" + } + ) + } + if (parts.length > 5) { + dialog.showMessageBoxSync( + { + type: "error", + title: "Illegal Instruction", + message: "On package " + item + ": invalid package name: too many parts" + } + ) + } + if (!/^[a-zA-Z0-9.]*$/gm.test(item)) { + dialog.showMessageBoxSync( + { + type: "error", + title: "Illegal Instruction", + message: "On package " + item + ": invalid package name: invalid format" + } + ) + } + } +} + +for (index in list) { + item = list[index]; + + if (fs.existsSync(homedir + "/.kartik/mods/" + item + "/kartik.ini") && fs.existsSync(homedir + "/.kartik/mods/" + item + "/kartik.yml")) { + unload(list, item); + dialog.showMessageBoxSync( + { + type: "error", + title: "Illegal Instruction", + message: "On package " + item + ": both kartik.ini and kartik.yml found" + } + ) + } +} + +global.moddata = {}; + +for (index in list) { + if (fs.existsSync(homedir + "/.kartik/mods/" + item + "/kartik.ini")) { + try { + moddata[list] = ini.parse(fs.readFileSync(homedir + "/.kartik/mods/" + item + "/kartik.ini", "utf-8")); + } catch (e) { + unload(list, item); + console.error(e); + dialog.showMessageBoxSync( + { + type: "error", + title: "Illegal Instruction", + message: "On package " + item + ": ini parser error" + } + ) + } + } else { + try { + moddata[list] = YAML.parse(fs.readFileSync(homedir + "/.kartik/mods/" + item + "/kartik.yml", "utf-8")); + } catch (e) { + unload(list, item); + console.error(e); + dialog.showMessageBoxSync( + { + type: "error", + title: "Illegal Instruction", + message: "On package " + item + ": yaml parser error" + } + ) + } + } +} + +for (index in list) { + item = list[index]; + mod = moddata[item]; + + roots = Object.keys(mod); + + for (i1 in roots) { + r = roots[i1]; + if (r !== "Meta" && r !== "Hook") { + unload(list, item); + dialog.showMessageBoxSync( + { + type: "error", + title: "Illegal Instruction", + message: "On package " + item + ": invalid root section: " + r + } + ) + } + } + + for (i2 in Object.keys(mod["Meta"])) { + r = Object.keys(mod["Meta"])[i2]; + if (r !== "Properties" && r !== "Hooks") { + unload(list, item); + dialog.showMessageBoxSync( + { + type: "error", + title: "Illegal Instruction", + message: "On package " + item + ": invalid meta section: " + r + } + ) + } + } + + if (Object.keys(mod["Meta"]).length < 2) { + unload(list, item); + dialog.showMessageBoxSync( + { + type: "error", + title: "Illegal Instruction", + message: "On package " + item + ": meta sections incomplete" + } + ) + } + + meta = mod["Meta"]; + + for (i3 in Object.keys(meta["Properties"])) { + r = Object.keys(meta["Properties"])[i3]; + if (r !== "Mod.Name" && r !== "Mod.Version" && r !== "Mod.Author" && r !== "Mod.Required") { + unload(list, item); + dialog.showMessageBoxSync( + { + type: "error", + title: "Illegal Instruction", + message: "On package " + item + ": invalid property: " + r + } + ) + } + } + + if (Object.keys(meta["Properties"]).length < 4) { + unload(list, item); + dialog.showMessageBoxSync( + { + type: "error", + title: "Illegal Instruction", + message: "On package " + item + ": properties incomplete" + } + ) + } + + props = meta.Properties; + + if (props["Mod.Required"].trim() !== "*") { + sver = require('../package.json').version.split(".").map((i) => { if (!isNaN((i - 1 + 1))) { return (i - 1 + 1).toString(); } else { return i; } }).join("."); + if (semver.valid(sver)) { + if (!semver.satisfies(sver, props["Mod.Required"].trim())) { + unload(list, item); + dialog.showMessageBoxSync( + { + type: "error", + title: "Illegal Instruction", + message: "On package " + item + ": mod made for another version of Kartik" + } + ) + } + } else { + if (require('../package.json').channel !== "git" && require('../package.json').channel !== "nightly") { + unload(list, item); + dialog.showMessageBoxSync( + { + type: "error", + title: "Illegal Instruction", + message: "On package " + item + ": invalid game version" + } + ) + } + } + } + + hooks = meta["Hooks"]; + hname = Object.keys(hooks); + + for (i4 in hname) { + hookn = hname[i4]; + hook = hooks[hookn]; + if (typeof mod["Hook"][hook] === "undefined") { + unload(list, item); + dialog.showMessageBoxSync( + { + type: "error", + title: "Illegal Instruction", + message: "On package " + item + ": block " + hook + " required by hook " + hookn + " not found" + } + ) + } + } +} + +for (index in list) { + item = list[index]; + mod = moddata[item]; + meta = mod["Meta"]; + + hooks = meta["Hooks"]; + hname = Object.keys(hooks); + + for (i4 in hname) { + hookn = hname[i4]; + hook = hooks[hookn]; + + mod["_Path"] = homedir + "/.kartik/mods/" + item; + + require('./hooks')(mod, hookn, hook); + } +} + +global.mods = list; diff --git a/modding/resources.js b/modding/resources.js new file mode 100644 index 0000000..7301901 --- /dev/null +++ b/modding/resources.js @@ -0,0 +1,65 @@ +const fs = require('fs'); + +global.resources = { + music: {}, + sfx: {}, + races: {}, + cars: {}, + scenario: { + voice: {}, + averi: {} + } +}; + +music_list = fs.readdirSync("./music"); +for (index in music_list) { + music = music_list[index]; + name = music.split(".")[0]; + resources.music[name] = { + file: KartikRoot + "/music/" + music, + original: true + }; +} + +sfx_list = fs.readdirSync("./sfx"); +for (index in sfx_list) { + sfx = sfx_list[index]; + name = sfx.split(".")[0]; + if (sfx.split(".")[1] === "mp3") { + resources.sfx[name] = KartikRoot + "/sfx/" + sfx; + } +} + +races_list = fs.readdirSync("./race/circuits"); +for (index in races_list) { + races = races_list[index]; + name = races.split(".")[0]; + if (races.split(".")[1] === "html") { + resources.races[name] = "./race/circuits/" + races; + } +} + +cars_list = fs.readdirSync("./race/models"); +for (index in cars_list) { + cars = cars_list[index]; + name = cars.split(".")[0]; + resources.cars[name] = KartikRoot + "/race/models/" + cars; +} + +scvoice_list = fs.readdirSync("./scenario/voice"); +for (index in scvoice_list) { + scvoice = scvoice_list[index]; + name = scvoice.split(".")[0]; + resources.scenario.voice[name] = KartikRoot + "/scenario/voice/" + scvoice; +} + +scchar_list = fs.readdirSync("./scenario/character"); +for (index in scchar_list) { + scchar = scchar_list[index]; + name = scchar.split(".")[0]; + resources.scenario.averi[name] = KartikRoot + "/scenario/character/" + scchar; +} + +if (typeof building !== "undefined" && building) { + global.targetResources = JSON.stringify(resources); +} |