UMM installed successfully
+ +diff --git a/.gitignore b/.gitignore
index 07d2252..e5efb4f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,4 @@
node_modules
-out
\ No newline at end of file
+out
+app.log
+config.json
\ No newline at end of file
diff --git a/config.js b/config.js
new file mode 100644
index 0000000..594270d
--- /dev/null
+++ b/config.js
@@ -0,0 +1,18 @@
+const fs = require("fs"), path = require("path");
+let p = path.resolve(__dirname, 'config.json')
+global.config = {};
+
+fs.stat(p, (err, stats) => {
+ if(!err) {
+ global.config = require('./config.json');
+ }
+})
+
+global.set = function(key, value) {
+ global.config[key] = value;
+ save();
+}
+
+function save() {
+ fs.writeFile(p, JSON.stringify(global.config, null, 4), err => {if(err) console.log(err);})
+}
\ No newline at end of file
diff --git a/index.js b/index.js
index 36a5656..9d54448 100644
--- a/index.js
+++ b/index.js
@@ -1,4 +1,5 @@
const request = require("request");
+
module.exports = (app_path, notification) => {
const os = require("os");
const fs = require("fs");
@@ -49,7 +50,6 @@ module.exports = (app_path, notification) => {
if(filter == "downloads" || filter == "rating") sorting = sorting == "desc" ? "asc" : "desc";
let sort = (sorting == "desc" ? "-" : "") + filter, offset = 20 * page, limit = 20;
return new Promise((resolve, reject) => {
- //console.log(`https://api.mod.io/v1/games/629/mods?tags=Map&tags-not-in=${ignore}&_sort=${sort}&_offset=${offset}&_limit=${limit}&name-not-lk=*dropper*&name-lk=*${search}*`);
request(`https://api.mod.io/v1/games/629/mods?tags=Map&tags-not-in=${ignore}&_sort=${sort}&_offset=${offset}&_limit=${limit}&name-not-lk=*dropper*&name-lk=*${search}*`, {headers: {Authorization: "Bearer " + token}, timeout: 20e3}, (err, res, body) => {
try {
body = JSON.parse(body);
@@ -70,51 +70,51 @@ module.exports = (app_path, notification) => {
function getUserLikes(token) {
return new Promise((resolve, reject) => {
request('https://api.mod.io/v1/me/ratings', { headers: { Authorization: "Bearer " + token }, timeout: 20e3 }, (err, res, body) => {
- try {
- body = JSON.parse(body);
- } catch(err) {
- console.log(err);
- }
-
- if(!err && res.statusCode == 200) {
- let result = {};
- for(let i = 0; i < body.data.length; i++) {
- if(body.data[i].game_id == "629") {
- result[body.data[i].mod_id] = body.data[i].rating;
- }
+ try {
+ body = JSON.parse(body);
+ } catch(err) {
+ console.log(err);
+ }
+
+ if(!err && res.statusCode == 200) {
+ let result = {};
+ for(let i = 0; i < body.data.length; i++) {
+ if(body.data[i].game_id == "629") {
+ result[body.data[i].mod_id] = body.data[i].rating;
}
- resolve(result);
}
- else {
- reject({...body, response_status: res.statusCode});
- }
- });
+ resolve(result);
+ }
+ else {
+ reject({...body, response_status: res.statusCode});
+ }
});
+});
}
function getUserSubscriptions(token) {
return new Promise((resolve, reject) => {
request('https://api.mod.io/v1/me/subscribed', { headers: { Authorization: "Bearer " + token }, timeout: 20e3 }, (err, res, body) => {
- try {
- body = JSON.parse(body);
- } catch(err) {
- console.log(err);
- }
-
- if(!err && res.statusCode == 200) {
- let result = {};
- for(let i = 0; i < body.data.length; i++) {
- if(body.data[i].game_id == "629") {
- result[body.data[i].id] = true;
- }
+ try {
+ body = JSON.parse(body);
+ } catch(err) {
+ console.log(err);
+ }
+
+ if(!err && res.statusCode == 200) {
+ let result = {};
+ for(let i = 0; i < body.data.length; i++) {
+ if(body.data[i].game_id == "629") {
+ result[body.data[i].id] = true;
}
- resolve(result);
}
- else {
- reject({...body, response_status: res.statusCode});
- }
- });
+ resolve(result);
+ }
+ else {
+ reject({...body, response_status: res.statusCode});
+ }
});
+});
}
function rateModio(id, rating, token) {
@@ -336,6 +336,9 @@ app.get('/internal/open', (req, res) => {
});
});
+app.get('/internal/config', (req, res) => {
+ res.status(200).send(global.config);
+});
app.post('/modio/download', (req, res) => {
if(req.body.id) {
@@ -458,7 +461,7 @@ io.on('connection', function(socket) {
http.listen(port, () => {
- console.log(`Map manager server listening on port ${port}`)
+ console.log(`XLhub server listening on port ${port}`)
})
return app;
diff --git a/logger.js b/logger.js
new file mode 100644
index 0000000..28226b6
--- /dev/null
+++ b/logger.js
@@ -0,0 +1,61 @@
+var log = console.log;
+var fs = require('fs');
+var log_file = fs.createWriteStream(__dirname + '/app.log', {flags : 'a'});
+
+console.log = function () {
+ let l = [getDate(), ...arguments];
+ log_file.write(l.join(" ") + '\n');
+ log.apply(console, l);
+};
+
+function getDate() {
+ var now = new Date();
+
+ let day = ('0' + now.getDate()).slice(-2);
+ let month = ('0' + (now.getMonth() + 1)).slice(-2);
+ let year = ('0' + now.getFullYear()).slice(-2);
+
+ let hour = ('0' + now.getHours()).slice(-2);
+ let minute = ('0' + now.getMinutes()).slice(-2);
+ let seconds = ('0' + now.getSeconds()).slice(-2);
+
+ return `${day}/${month}/${year} ${hour}:${minute}:${seconds}`;
+}
+
+['log', 'warn', 'error'].forEach((methodName) => {
+ const originalMethod = console[methodName];
+ console[methodName] = (...args) => {
+ let initiator = 'unknown place';
+ try {
+ throw new Error();
+ } catch (e) {
+ if (typeof e.stack === 'string') {
+ let isFirst = true;
+ for (const line of e.stack.split('\n')) {
+ const matches = line.match(/^\s+at\s+(.*)/);
+ if (matches) {
+ if (!isFirst) {
+ initiator = matches[1];
+ break;
+ }
+ isFirst = false;
+ }
+ }
+ }
+ }
+ initiator = initiator.split('\\');
+ initiator = '(' + initiator[initiator.length - 1];
+
+ if (initiator[initiator.length - 1] != ')') {
+ initiator += ')';
+ }
+
+ originalMethod.apply(console, [initiator, ...args]);
+ };
+});
+
+process.on('unhandledRejection', (reason, p) => {
+ console.error(reason, 'Unhandled Rejection at Promise', p);
+}).on('uncaughtException', err => {
+ console.error(err, 'Uncaught Exception thrown');
+});
\ No newline at end of file
diff --git a/main.js b/main.js
index 47d98d4..16e027a 100644
--- a/main.js
+++ b/main.js
@@ -1,6 +1,11 @@
let found = false;
if (require('electron-squirrel-startup')) return;
+require("./logger.js");
+const { app, Tray, Menu, nativeImage, BrowserWindow, Notification } = require('electron')
+const fs = require('fs');
+const os = require('os');
+
require('node-netstat')({
limit: 1,
filter: {
@@ -21,11 +26,67 @@ require('node-netstat')({
}
});
+require("./config.js");
+
+const steamPath = require("steam-path");
+let searching = false;
+function findGameSteam() {
+ if (global.config.gamePath) {
+ getGameVersion();
+ }
+
+ searching = true;
+ steamPath.getAppPath(962730).then(result => {
+ global.set('gamePath', result.path);
+
+ getGameVersion();
+ searching = false;
+ }).catch(err => {
+ console.log(err, "Game not found via steam");
+ searching = false;
+ });
+}
+
+function getGameVersion() {
+ require('child_process').exec(`wmic datafile where name='${global.config.gamePath.split('\\').join('\\\\')}\\\\SkaterXL.exe' get Version`, (err, stdout) => {
+ if(!err) {
+ if(stdout.split('2019.4.40').length > 1) return global.set('gameVersion', '1.2.6.0');
+ if(stdout.split('2019.3.15').length > 1) return global.set('gameVersion', '1.2.2.8');
+ global.set('gameVersion', 'unknown');
+ }
+ else console.log(err);
+ })
+}
+
+function getMods(menu) {
+ fs.stat(global.config.gamePath + '\\Mods', (err, stats) => {
+ if(!err) {
+ fs.readdir(global.config.gamePath + '\\Mods', { withFileTypes: true }, (err, files) => {
+ let folders = files.filter(dirent => dirent.isDirectory()).map(dirent => dirent.name)
+ let keys = {}
+
+ for(let i = 0; i < folders.length;i++) {
+ if(folders[i].toLowerCase().split('xlgearmodifier').length > 1) keys['xlgm'] = true;
+ else keys[folders[i]] = true;
+ }
+
+ console.log(keys);
+
+ if(!keys['SoundMod']) menu.getMenuItemById('SoundMod').enabled = false;
+ if(!keys['walking-mod']) menu.getMenuItemById('walking-mod').enabled = false;
+ if(!keys['xlgm']) menu.getMenuItemById('xlgm').enabled = false;
+ });
+ }
+ });
+}
+
+findGameSteam();
+
function init() {
- const { app, Tray, Menu, nativeImage, BrowserWindow, Notification } = require('electron')
const app_path = app.getAppPath();
const express_app = require("./index.js")(app_path, Notification);
+ const umm = require('./umm.js');
let tray;
@@ -65,9 +126,71 @@ function init() {
const menu = Menu.buildFromTemplate([
{
- label: 'Open',
+ label: 'Open XLHub',
click() { show(); }
},
+ {
+ label: 'Actions',
+ submenu: [
+ {
+ label: 'Install UnityModManager',
+ click() {
+ show();
+ mainWindow.webContents.executeJavaScript('UMMInstall()');
+ umm.applyUMM().then(() => {
+ mainWindow.webContents.executeJavaScript('UMMInstallFinish()');
+ }).catch((err) => {
+ console.log(err);
+ mainWindow.webContents.executeJavaScript('UMMInstallError()');
+ });
+ }
+ }
+ ]
+ },
+ {
+ label: 'Folders',
+ submenu: [
+ {
+ label: 'Game path',
+ click() {
+ openPath(global.config.gamePath);
+ }
+ },
+ {
+ label: 'Gear textures',
+ click() {
+ openPath(os.homedir() + "\\Documents\\SkaterXL\\Gear")
+ }
+ },
+ {
+ label: 'Mods',
+ click() {
+ openPath(global.config.gamePath + '\\Mods');
+ }
+ },
+ {
+ id: 'SoundMod',
+ label: 'Soundmod sounds',
+ click() {
+ openPath(global.config.gamePath + '\\Mods\\SoundMod\\Sounds');
+ }
+ },
+ {
+ id: 'walking-mod',
+ label: 'Walking mod animations',
+ click() {
+ openPath(os.homedir() + "\\Documents\\SkaterXL\\walking-mod\\animations")
+ }
+ },
+ {
+ id: 'xlgm',
+ label: 'XLGM gear',
+ click() {
+ openPath(os.homedir() + "\\Documents\\SkaterXL\\XLGearModifier\\Asset Packs")
+ }
+ }
+ ]
+ },
{
label: 'Quit',
click() { app.quit(); }
@@ -76,6 +199,8 @@ function init() {
tray.setToolTip('XLhub')
tray.setContextMenu(menu)
+
+ getMods(menu);
tray.on('double-click', (e) => {
show();
@@ -97,3 +222,11 @@ function init() {
res.status(200).send();
});
}
+
+function openPath(path) {
+ fs.stat(path, err => {
+ if(!err) {
+ require('child_process').exec(`explorer.exe "${path.split("/").join("\\")}"`);
+ }
+ })
+}
\ No newline at end of file
diff --git a/package.json b/package.json
index 7c5027f..c2a3334 100644
--- a/package.json
+++ b/package.json
@@ -4,7 +4,7 @@
"description": "XLhub",
"keywords": [],
"main": "./main.js",
- "version": "1.2.1",
+ "version": "1.3.0",
"author": "froquede",
"scripts": {
"start": "electron-forge start",
@@ -18,11 +18,13 @@
"decompress-zip": "0.3.3",
"electron-squirrel-startup": "^1.0.0",
"express": "4.18.1",
+ "fs-extra": "^11.1.1",
"glob": "7.2.3",
"lit": "2.3.1",
"node-netstat": "^1.8.0",
"request": "2.88.2",
- "socket.io": "4.5.2"
+ "socket.io": "4.5.2",
+ "steam-path": "^1.0.2"
},
"devDependencies": {
"@electron-forge/cli": "^6.0.0-beta.66",
diff --git a/resources/UMM_1228/Assembly-CSharp.dll b/resources/UMM_1228/Assembly-CSharp.dll
new file mode 100644
index 0000000..87134e9
Binary files /dev/null and b/resources/UMM_1228/Assembly-CSharp.dll differ
diff --git a/resources/UMM_1228/UnityModManager/0Harmony-1.2.dll b/resources/UMM_1228/UnityModManager/0Harmony-1.2.dll
new file mode 100644
index 0000000..56becd7
Binary files /dev/null and b/resources/UMM_1228/UnityModManager/0Harmony-1.2.dll differ
diff --git a/resources/UMM_1228/UnityModManager/0Harmony.dll b/resources/UMM_1228/UnityModManager/0Harmony.dll
new file mode 100644
index 0000000..2c66289
Binary files /dev/null and b/resources/UMM_1228/UnityModManager/0Harmony.dll differ
diff --git a/resources/UMM_1228/UnityModManager/0Harmony12.dll b/resources/UMM_1228/UnityModManager/0Harmony12.dll
new file mode 100644
index 0000000..d22f068
Binary files /dev/null and b/resources/UMM_1228/UnityModManager/0Harmony12.dll differ
diff --git a/resources/UMM_1228/UnityModManager/Config.xml b/resources/UMM_1228/UnityModManager/Config.xml
new file mode 100644
index 0000000..d73390d
--- /dev/null
+++ b/resources/UMM_1228/UnityModManager/Config.xml
@@ -0,0 +1,9 @@
+
+
Installing UMM
+UMM installed successfully
+ +An error happenend while installing UMM
+ +v1.2.1
+SkaterXL v | XLhub v1.3.0