Skip to content

Commit

Permalink
Added support for Windows mod config
Browse files Browse the repository at this point in the history
  • Loading branch information
CreepPork committed Sep 29, 2020
1 parent 771a02b commit a2aad11
Show file tree
Hide file tree
Showing 10 changed files with 140 additions and 14 deletions.
12 changes: 12 additions & 0 deletions src/commands/configure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export default class ConfigureCommand extends Command {
'magma configure -n -u UserName',
];
public static flags = {
batchScript: setFlag.batchScript,
linuxGsmInstanceConfig: setFlag.linuxGsmInstanceConfig,
nonInteractive: setFlag.nonInteractive,
password: setFlag.password,
Expand Down Expand Up @@ -62,6 +63,13 @@ export default class ConfigureCommand extends Command {
let value;

switch (key) {
case 'batchScript':
configKey = 'batchScript';
value = await this.validateEntry(
this.convertFlagToEntry('batchScript'), flags.batchScript
);
break;

case 'linuxGsmInstanceConfig':
configKey = 'linuxGsm';
value = await this.validateEntry(
Expand Down Expand Up @@ -154,6 +162,10 @@ export default class ConfigureCommand extends Command {

break;

case 'batchScript':
output = await this.insurer.ensureValidBatchScript(...values) as K;
break;

case 'linuxGsm':
output = await this.insurer.ensureValidLinuxGsm(...values) as K;
break;
Expand Down
3 changes: 3 additions & 0 deletions src/commands/initialize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export default class InitializeCommand extends Command {
description: 'Skip the check for the magma.json file. If it exists, it will be overwritten.',
}),
linuxGsmInstanceConfig: setFlag.linuxGsmInstanceConfig,
batchScript: setFlag.batchScript,
nonInteractive: setFlag.nonInteractive,
password: setFlag.password,
server: setFlag.server,
Expand Down Expand Up @@ -57,6 +58,7 @@ export default class InitializeCommand extends Command {
spinner.succeed('Logged in');

const linuxGsm = await insurer.ensureValidLinuxGsm(flags.linuxGsmInstanceConfig);
const batchScript = await insurer.ensureValidBatchScript(flags.batchScript);

const webhookUrl = await insurer.ensureValidWebhookUrl(flags.webhookUrl);

Expand All @@ -69,6 +71,7 @@ export default class InitializeCommand extends Command {
},
key,
linuxGsm,
batchScript,
mods: [],
serverPath,
steamCmdPath,
Expand Down
1 change: 0 additions & 1 deletion src/commands/install.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ export default class InstallCommand extends Command {

this.updateConfigFile(mods);

// Update LinuxGSM config
Processor.updateServerConfigFile(Config.get('mods'));
}

Expand Down
4 changes: 2 additions & 2 deletions src/constants/configEntries.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import IConfigEntry from '../interfaces/iConfigEntry';

import * as os from 'os';
import IConfigEntry from '../interfaces/iConfigEntry';

const configEntries: IConfigEntry[] = [
{ config: 'credentials', displayName: 'Steam credentials' },
{ config: 'linuxGsm', displayName: 'LinuxGSM instance configuration file', condition: () => os.platform() === 'linux' },
{ config: 'batchScript', displayName: 'Batch file (*.bat) where your mods are listed in', condition: () => os.platform() === 'win32' },
{ config: 'serverPath', displayName: 'Server path' },
{ config: 'steamCmdPath', displayName: 'SteamCMD path' },
{ config: 'webhookUrl', displayName: 'Webhook URL' },
Expand Down
8 changes: 8 additions & 0 deletions src/filesystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@ export default class Filesystem {
return false;
}

public static hasExtension(filepath: string, extension: string): boolean {
if (fs.existsSync(filepath)) {
return path.parse(filepath).ext === extension;
}

return false;
}

public static isDirectory(filepath: string, includeSymLinks?: boolean): boolean {
if (fs.existsSync(filepath)) {
const stats = fs.lstatSync(filepath);
Expand Down
5 changes: 5 additions & 0 deletions src/flags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ export const linuxGsmInstanceConfig = flags.string({
description: 'Absolute path to the LinuxGSM instance configuration file (where it handles mods/servermods) (only supported on Linux)',
});

export const batchScript = flags.string({
char: 'b',
description: 'Absolute path to the Batch script starting your server, where it has your mods (only supported on Windows)',
});

export const password = flags.string({
char: 'p',
description: 'Steam user password.',
Expand Down
37 changes: 32 additions & 5 deletions src/insurer.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { prompt } from 'inquirer';

import ora = require('ora');

import Config from './config';
import Filesystem from './filesystem';
import Prompt from './prompt';
import Validate from './validator';
import IMod from './interfaces/iMod';
import ISteamCredentials from './interfaces/iSteamCredentials';
import Prompt from './prompt';
import Validate from './validator';

import ora = require('ora');

export default class Insurer {
public validate: Validate;
Expand Down Expand Up @@ -168,6 +167,34 @@ export default class Insurer {
}
}

public async ensureValidBatchScript(path?: string): Promise<string | undefined | never> {
if (process.platform === 'linux') { return; }

if (path) {
if (Filesystem.isFile(path)) {
return path;
} else {
if (this.nonInteractive) {
throw new Error('The Batch script file path is invalid. Did you include the file?');
}

return await this.prompt.forBatchScript();
}
} else {
if (!this.nonInteractive) {
const response: { uses: boolean } = await prompt({
message: 'Are you using a Batch script to start your server?',
name: 'uses',
type: 'confirm',
});

if (response.uses) {
return await this.prompt.forBatchScript();
}
}
}
}

public async ensureValidWebhookUrl(url?: string): Promise<string | undefined | never> {
if (url) {
return url;
Expand Down
1 change: 1 addition & 0 deletions src/interfaces/iConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import IMod from './iMod';
import ISteamCredentials from './iSteamCredentials';

export default interface IConfig {
batchScript?: string;
version: number;
lastId: number;
mods: IMod[];
Expand Down
62 changes: 61 additions & 1 deletion src/processor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,68 @@ export default class Processor {
}

public static updateServerConfigFile(mods: IMod[]): void {
if (process.platform === 'win32') { return; }
if (process.platform === 'win32') {
this.handleConfigForWindows(mods);
} else {
this.handleConfigForLinux(mods);
}
}

private static handleConfigForWindows(mods: IMod[]): void {
const requiredMods = mods.filter(mod => mod.type === EModType.all && mod.isActive === true);
const serverMods = mods.filter(mod => mod.type === EModType.server && mod.isActive === true);

const serverConfigPath = Config.get('batchScript');

if (!serverConfigPath) { return; }

let requiredModString = '-mod=';
let serverModString = '-serverMod=';

for (const mod of requiredMods) {
requiredModString += `mods\\@${_.snakeCase(mod.name)}`;

if (requiredMods.indexOf(mod) !== requiredMods.length - 1) {
requiredModString += ';';
}
}

for (const mod of serverMods) {
serverModString += `servermods\\@${_.snakeCase(mod.name)}`;

if (serverMods.indexOf(mod) !== serverMods.length - 1) {
serverModString += ';';
}
}

// Read config file and transform it into a line array
const configText = fs.readFileSync(serverConfigPath).toString().replace(/[\r]/g, '').trim().split('\n');

let requiredModStringAdded = false;
let serverModStringAdded = false;

const regexMod = /-mod=(([a-zA-Z]\w+\\@[a-zA-Z0-9_-]\w+[;]?)*|(@[a-zA-Z0-9_-]\w+[;]?))*/g;
const regexServerMod = /-serverMod=(([a-zA-Z]\w+\\@[a-zA-Z0-9_-]\w+[;]?)*|(@[a-zA-Z0-9_-]\w+[;]?))*/g;

for (const [index, line] of configText.entries()) {
// If the line is commented out or empty, we ignore it
if (line.charAt(0) === 'rem' || line === '') { continue; }

if (line.match(regexMod)) {
configText[index] = configText[index].replace(new RegExp(regexMod), requiredModString);
requiredModStringAdded = true;
}

if (line.match(regexServerMod)) {
configText[index] = configText[index].replace(regexServerMod, serverModString);
serverModStringAdded = true;
}
}

fs.writeFileSync(serverConfigPath, configText.join('\n'));
}

private static handleConfigForLinux(mods: IMod[]): void {
const requiredMods = mods.filter(mod => mod.type === EModType.all && mod.isActive === true);
const serverMods = mods.filter(mod => mod.type === EModType.server && mod.isActive === true);

Expand Down
21 changes: 16 additions & 5 deletions src/prompt.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { prompt } from 'inquirer';
import ConfigEntries from './constants/configEntries';
import Filesystem from './filesystem';
import IConfigEntry from './interfaces/iConfigEntry';
import ISteamCredentials from './interfaces/iSteamCredentials';
import Validate from './validator';

import ora = require('ora');

import Filesystem from './filesystem';
import Validate from './validator';
import ConfigEntries from './constants/configEntries';
import ISteamCredentials from './interfaces/iSteamCredentials';
import IConfigEntry from './interfaces/iConfigEntry';

export default class Prompt {
private nonInteractive: boolean;
Expand Down Expand Up @@ -88,6 +88,17 @@ export default class Prompt {
return response.path;
}

public async forBatchScript(): Promise<string> {
const response: { path: string } = await prompt({
message: 'Absolute path to the Batch script starting your server, where it has your mods',
name: 'path',
type: 'input',
validate: path => { return Filesystem.hasExtension(path, '.bat') }
});

return response.path;
}

public async forWebhookUrl(): Promise<string> {
const response: { url: string } = await prompt({
message: 'A webhook URL for the cron command to use?',
Expand Down

0 comments on commit a2aad11

Please sign in to comment.