Skip to content

Commit

Permalink
feat(launch): record launch error
Browse files Browse the repository at this point in the history
  • Loading branch information
ci010 committed Sep 4, 2019
1 parent fa84f2d commit ca2686c
Show file tree
Hide file tree
Showing 3 changed files with 175 additions and 156 deletions.
316 changes: 163 additions & 153 deletions src/main/store/modules/launch.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,174 +27,184 @@ const mod = {
...base,
actions: {
async launch({ state, rootGetters, rootState, commit, dispatch }) {
if (state.status !== 'ready') {
return false;
}
/**
* current selected profile
*/
const profile = rootGetters.selectedProfile;
const user = rootGetters.selectedUser;
const gameProfile = rootGetters.selectedGameProfile;
if (!profile) return Promise.reject(new Error('launch.profile.empty'));
if (user.accessToken === '' || gameProfile.name === '' || gameProfile.id === '') return Promise.reject(new Error('launch.auth.illegal'));

commit('launchStatus', 'checkingProblems');

for (let problems = rootState.profile.problems.filter(p => p.autofix), i = 0;
problems.length !== 0 && i < 3;
problems = rootState.profile.problems.filter(p => p.autofix), i += 1) {
await dispatch('fixProfile', rootState.profile.problems.filter(p => p.autofix));
}
try {
if (state.status !== 'ready' && state.status !== 'error') {
return false;
}

if (rootState.profile.problems.some(p => !p.optional)) {
commit('launchStatus', 'ready');
return false;
}
commit('launchStatus', 'checkingProblems');

/**
* current selected profile
*/
const profile = rootGetters.selectedProfile;
const user = rootGetters.selectedUser;
const gameProfile = rootGetters.selectedGameProfile;
if (!profile) {
commit('launchErrors', { type: 'selectProfileEmpty', content: [] });
return false;
}
if (user.accessToken === '' || gameProfile.name === '' || gameProfile.id === '') {
commit('launchErrors', { type: 'illegalAuth', content: [] });
return false;
}

if (state.status === 'ready') { // check if we have cancel (set to ready) this launch
return false;
}
for (let problems = rootState.profile.problems.filter(p => p.autofix), i = 0;
problems.length !== 0 && i < 3;
problems = rootState.profile.problems.filter(p => p.autofix), i += 1) {
await dispatch('fixProfile', rootState.profile.problems.filter(p => p.autofix));
}

commit('launchStatus', 'launching');

const debug = profile.showLog;
const minecraftFolder = new Util.MinecraftFolder(paths.join(rootState.root, 'profiles', profile.id));

/**
* real version name
*/
const version = await dispatch('resolveVersion', {
folder: '',
...profile.version,
});

console.log(`Will launch with ${version} version.`);

const java = profile.java || rootGetters.defaultJava;
/**
* Build launch condition
* @type {Launcher.Option}
*/
const option = {
auth: {
selectedProfile: gameProfile,
accessToken: user.accessToken,
userType: UserType.Mojang,
properties: {},
},
gamePath: minecraftFolder.root,
resourcePath: rootState.root,
javaPath: java.path,
minMemory: profile.minMemory,
maxMemory: profile.maxMemory,
version,
extraExecOption: {
detached: true,
cwd: minecraftFolder.root,
},
yggdrasilAgent: user.authService !== 'mojang' && user.authService !== 'offline' ? {
jar: await dispatch('ensureAuthlibInjection'),
server: rootGetters.authService.hostName,
} : undefined,
};

console.log('Launching a server');
if (profile.type === 'server') {
option.server = { ip: profile.host, port: profile.port };
}
if (rootState.profile.problems.some(p => !p.optional)) {
commit('launchErrors', { type: 'unresolvableProblems', content: rootState.profile.problems.filter(p => !p.optional) });
return false;
}

console.log('Deploy all resources...');
for (const domain of Object.keys(profile.deployments)) {
try {
console.log(`Deploying ${profile.deployments[domain].length} resources for ${domain}`);
const dir = join(option.gamePath, domain);
if (await fs.missing(dir)) {
await fs.mkdir(dir);
}
const files = await fs.readdir(dir);
for (const file of files) {
const fp = join(dir, file);
const isLink = await fs.stat(fp).then(s => s.isSymbolicLink());
if (isLink) {
await fs.unlink(fp);
if (state.status === 'ready') { // check if we have cancel (set to ready) this launch
return false;
}

commit('launchStatus', 'launching');

const debug = profile.showLog;
const minecraftFolder = new Util.MinecraftFolder(paths.join(rootState.root, 'profiles', profile.id));

/**
* real version name
*/
const version = await dispatch('resolveVersion', {
folder: '',
...profile.version,
});

console.log(`Will launch with ${version} version.`);

const java = profile.java || rootGetters.defaultJava;
/**
* Build launch condition
* @type {Launcher.Option}
*/
const option = {
auth: {
selectedProfile: gameProfile,
accessToken: user.accessToken,
userType: UserType.Mojang,
properties: {},
},
gamePath: minecraftFolder.root,
resourcePath: rootState.root,
javaPath: java.path,
minMemory: profile.minMemory,
maxMemory: profile.maxMemory,
version,
extraExecOption: {
detached: true,
cwd: minecraftFolder.root,
},
yggdrasilAgent: user.authService !== 'mojang' && user.authService !== 'offline' ? {
jar: await dispatch('ensureAuthlibInjection'),
server: rootGetters.authService.hostName,
} : undefined,
};

console.log('Launching a server');
if (profile.type === 'server') {
option.server = { ip: profile.host, port: profile.port };
}

console.log('Deploy all resources...');
for (const domain of Object.keys(profile.deployments)) {
try {
console.log(`Deploying ${profile.deployments[domain].length} resources for ${domain}`);
const dir = join(option.gamePath, domain);
if (await fs.missing(dir)) {
await fs.mkdir(dir);
}
const files = await fs.readdir(dir);
for (const file of files) {
const fp = join(dir, file);
const isLink = await fs.stat(fp).then(s => s.isSymbolicLink());
if (isLink) {
await fs.unlink(fp);
}
}
await dispatch('deployResources', {
resourceUrls: profile.deployments[domain],
profile: profile.id,
});
} catch (e) {
console.error(`Cannot deploy ${domain}`);
console.error(e);
}
}

try {
// we link the resource pack whatever
await dispatch('deployResources', {
resourceUrls: profile.deployments[domain],
resourceUrls: rootGetters.resourcepacks.map(r => r.hash),
profile: profile.id,
});
} catch (e) {
console.error(`Cannot deploy ${domain}`);
console.error('Cannot deploy resource packs');
console.error(e);
}
}

try {
// we link the resource pack whatever
await dispatch('deployResources', {
resourceUrls: rootGetters.resourcepacks.map(r => r.hash),
profile: profile.id,
console.log('Launching with these option...');
console.log(JSON.stringify(option));

// Launch
return Launcher.launch(option).then((process) => {
commit('launchStatus', 'launched');
let crashReport = '';
let crashReportLocation = '';
let waitForReady = true;
ipcMain.emit('minecraft-start', debug);
process.on('error', (err) => {
console.log(err);
});
process.on('exit', (code, signal) => {
console.log(`exit: ${code}, signal: ${signal}`);
if (signal === 'SIGKILL') {
ipcMain.emit('minecraft-killed');
}
if (code !== 0 && (crashReport || crashReportLocation)) {
ipcMain.emit('minecraft-crash-report', {
crashReport,
crashReportLocation,
});
ipcMain.emit('minecraft-exit', {
code,
signal,
crashReport,
crashReportLocation,
});
} else {
ipcMain.emit('minecraft-exit', { code, signal });
}
commit('launchStatus', 'ready');
});
process.stdout.on('data', (s) => {
const string = s.toString();
if (string.indexOf('---- Minecraft Crash Report ----') !== -1) {
crashReport = string;
} else if (string.indexOf('Crash report saved to:') !== -1) {
crashReportLocation = string.substring(string.indexOf('Crash report saved to:') + 'Crash report saved to: #@!@# '.length);
} else if (waitForReady && string.indexOf('Reloading ResourceManager') !== -1 || string.indexOf('LWJGL Version: ') !== -1) {
waitForReady = false;
ipcMain.emit('minecraft-window-ready');
commit('launchStatus', 'minecraftReady');
}
ipcMain.emit('minecraft-stdout', string);
});
process.stderr.on('data', (s) => {
ipcMain.emit('minecraft-stderr', s.toString());
});
process.unref();
return true;
});
} catch (e) {
console.error('Cannot deploy resource packs');
console.error(e);
commit('launchErrors', { type: 'general', content: [e] });
return false;
}
console.log('Launching with these option...');
console.log(JSON.stringify(option));

// Launch
return Launcher.launch(option).then((process) => {
commit('launchStatus', 'launched');
let crashReport = '';
let crashReportLocation = '';
let waitForReady = true;
ipcMain.emit('minecraft-start', debug);
process.on('error', (err) => {
console.log(err);
});
process.on('exit', (code, signal) => {
console.log(`exit: ${code}, signal: ${signal}`);
if (signal === 'SIGKILL') {
ipcMain.emit('minecraft-killed');
}
if (code !== 0 && (crashReport || crashReportLocation)) {
ipcMain.emit('minecraft-crash-report', {
crashReport,
crashReportLocation,
});
ipcMain.emit('minecraft-exit', {
code,
signal,
crashReport,
crashReportLocation,
});
} else {
ipcMain.emit('minecraft-exit', { code, signal });
}
commit('launchStatus', 'ready');
});
process.stdout.on('data', (s) => {
const string = s.toString();
if (string.indexOf('---- Minecraft Crash Report ----') !== -1) {
crashReport = string;
} else if (string.indexOf('Crash report saved to:') !== -1) {
crashReportLocation = string.substring(string.indexOf('Crash report saved to:') + 'Crash report saved to: #@!@# '.length);
} else if (waitForReady && string.indexOf('Reloading ResourceManager') !== -1 || string.indexOf('LWJGL Version: ') !== -1) {
waitForReady = false;
ipcMain.emit('minecraft-window-ready');
commit('launchStatus', 'minecraftReady');
}
ipcMain.emit('minecraft-stdout', string);
});
process.stderr.on('data', (s) => {
ipcMain.emit('minecraft-stderr', s.toString());
});
process.unref();
return true;
}).catch((e) => {
throw (e);
});
},
},
};
Expand Down
9 changes: 6 additions & 3 deletions src/universal/store/modules/launch.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ export interface Actions {
launch(context: C, profileId?: string): Promise<boolean>;
}

type Status = 'ready' | 'checkingProblems' | 'launching' | 'launched' | 'minecraftReady';
type Status = 'ready' | 'checkingProblems' | 'launching' | 'launched' | 'minecraftReady' | 'error';
export interface State {
status: Status
status: Status;
errorType: string;
errors: any[];
}

export interface Mutations {
launchStatus(state: State, status: Status): void
launchStatus(state: State, status: Status): void;
launchErrors(state: State, error: { type: string; content: any[] }): void;
}

export type LauncherModule = Module<"launch", State, {}, Mutations, Actions>;
Expand Down
6 changes: 6 additions & 0 deletions src/universal/store/modules/launch.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,17 @@
const mod = {
state: {
status: 'ready',
errorType: '',
errors: [],
},
mutations: {
launchStatus(state, status) {
state.status = status;
},
launchErrors(state, error) {
state.errorType = error.type;
state.errors = error.content;
},
},
};

Expand Down

0 comments on commit ca2686c

Please sign in to comment.