Various fixes; allow direct import from URL

This commit is contained in:
Cmdr McDonald
2016-11-13 16:42:59 +00:00
parent 7d4c534956
commit a65dae1631
8 changed files with 103 additions and 33 deletions

View File

@@ -16,4 +16,5 @@
* Enable boost display even if power distributor is disabled
* Calculate breakdown of ship offensive and defensive stats
* Add 'Offence summary' and 'Defence summary' components
* Add ability to import directly from companion API output
* Add ability to import from companion API output through import feature
* Add ability to import from companion API output through URL

View File

@@ -7,6 +7,8 @@ import Persist from './stores/Persist';
import Header from './components/Header';
import Tooltip from './components/Tooltip';
import ModalImport from './components/ModalImport';
import * as CompanionApiUtils from './utils/CompanionApiUtils';
import * as Utils from './utils/UtilityFunctions';
import AboutPage from './pages/AboutPage';
import NotFoundPage from './pages/NotFoundPage';
@@ -15,6 +17,8 @@ import ComparisonPage from './pages/ComparisonPage';
import ShipyardPage from './pages/ShipyardPage';
import ErrorDetails from './pages/ErrorDetails';
const zlib = require('zlib');
/**
* Coriolis App
*/
@@ -52,6 +56,7 @@ export default class Coriolis extends React.Component {
this._onLanguageChange = this._onLanguageChange.bind(this);
this._onSizeRatioChange = this._onSizeRatioChange.bind(this);
this._keyDown = this._keyDown.bind(this);
this._importBuild = this._importBuild.bind(this);
this.emitter = new EventEmitter();
this.state = {
@@ -63,6 +68,7 @@ export default class Coriolis extends React.Component {
};
Router('', (r) => this._setPage(ShipyardPage, r));
Router('/import/:data', (r) => this._importBuild(r));
Router('/outfit/:ship/:code?', (r) => this._setPage(OutfittingPage, r));
Router('/compare/:name?', (r) => this._setPage(ComparisonPage, r));
Router('/comparison/:code', (r) => this._setPage(ComparisonPage, r));
@@ -70,6 +76,23 @@ export default class Coriolis extends React.Component {
Router('*', (r) => this._setPage(null, r));
}
/**
* Import a build directly
*/
_importBuild(r) {
try {
// Need to decode and gunzip the data
const data = zlib.gunzipSync(new Buffer(Utils.fromUrlSafe(r.params.data), 'base64'))
const json = JSON.parse(data);
const ship = CompanionApiUtils.shipFromJson(json);
r.params.ship = ship.id;
r.params.code = ship.toString();
this._setPage(OutfittingPage, r);
} catch (err) {
this.setState({ error: err });
}
}
/**
* Updates / Sets the page and route context
* @param {[type]} page The page to be shown

View File

@@ -64,7 +64,7 @@ export default class HardpointSlot extends Slot {
{ m.getHps() ? <div className={'l'} onMouseOver={termtip.bind(null, m.getClip() ? 'hpsshps' : 'hps')} onMouseOut={tooltip.bind(null, null)}>{translate('HPS')}: {formats.round1(m.getHps())} { m.getClip() ? <span>({formats.round1((m.getClip() * m.getHps() / m.getRoF()) / ((m.getClip() / m.getRoF()) + m.getReload())) })</span> : null }</div> : null }
{ m.getDps() && m.getEps() ? <div className={'l'} onMouseOver={termtip.bind(null, 'dpe')} onMouseOut={tooltip.bind(null, null)}>{translate('DPE')}: {formats.f1(m.getDps() / m.getEps())}</div> : null }
{ m.getRoF() ? <div className={'l'} onMouseOver={termtip.bind(null, 'rof')} onMouseOut={tooltip.bind(null, null)}>{translate('ROF')}: {formats.f1(m.getRoF())}{u.ps}</div> : null }
{ m.getRange() && !m.getDps() ? <div className={'l'}>{translate('Range')} : {formats.round(m.getRange() / 1000)}{u.km}</div> : null }
{ m.getRange() ? <div className={'l'}>{translate('range')} {formats.f1(m.getRange() / 1000)}{u.km}</div> : null }
{ m.getShieldBoost() ? <div className={'l'}>+{formats.pct1(m.getShieldBoost())}</div> : null }
{ m.getAmmo() ? <div className={'l'}>{translate('ammunition')}: {formats.int(m.getClip())}/{formats.int(m.getAmmo())}</div> : null }
{ showModuleResistances && m.getExplosiveResistance() ? <div className='l'>{translate('explres')}: {formats.pct(m.getExplosiveResistance())}</div> : null }

View File

@@ -40,7 +40,7 @@ export default class InternalSlot extends Slot {
{ m.rate ? <div className={'l'}>{translate('rate')}: {m.rate}{u.kgs}&nbsp;&nbsp;&nbsp;{translate('refuel time')}: {formats.time(this.props.fuel * 1000 / m.rate)}</div> : null }
{ m.getAmmo() ? <div className={'l'}>{translate('ammunition')}: {formats.gen(m.getAmmo())}</div> : null }
{ m.cells ? <div className={'l'}>{translate('cells')}: {m.cells}</div> : null }
{ m.recharge ? <div className={'l'}>{translate('recharge')}: {m.recharge} <u>MJ</u>&nbsp;&nbsp;&nbsp;{translate('total')}: {m.cells * m.recharge}{u.MJ}</div> : null }
{ m.shieldreinforcement ? <div className={'l'}>{translate('shieldreinforcement')}: {formats.int(m.getShieldReinforcement())} <u>MJ</u>&nbsp;&nbsp;&nbsp;{translate('total')}: {formats.int(m.cells * m.getShieldReinforcement())}{u.MJ}</div> : null }
{ m.repair ? <div className={'l'}>{translate('repair')}: {m.repair}</div> : null }
{ m.getFacingLimit() ? <div className={'l'}>{translate('facinglimit')} {formats.f1(m.getFacingLimit())}°</div> : null }
{ m.getRange() ? <div className={'l'}>{translate('range')} {formats.f2(m.getRange())}{u.km}</div> : null }

View File

@@ -2,6 +2,7 @@ import { ModuleGroupToName, MountMap, BulkheadNames } from './Constants';
import { Ships } from 'coriolis-data/dist';
import Ship from './Ship';
import * as ModuleUtils from './ModuleUtils';
import * as Utils from '../utils/UtilityFunctions';
import LZString from 'lz-string';
const STANDARD = ['powerPlant', 'thrusters', 'frameShiftDrive', 'lifeSupport', 'powerDistributor', 'sensors', 'fuelTank'];
@@ -209,13 +210,13 @@ export function toDetailedExport(builds) {
* @return {string} Zipped Base 64 encoded JSON
*/
export function fromComparison(name, builds, facets, predicate, desc) {
return LZString.compressToBase64(JSON.stringify({
return Utils.toUrlSafe(LZString.compressToBase64(JSON.stringify({
n: name,
b: builds.map((b) => { return { s: b.id, n: b.buildName, c: b.toString() }; }),
f: facets,
p: predicate,
d: desc ? 1 : 0
})).replace(/\//g, '-');
})));
};
/**
@@ -224,5 +225,5 @@ export function fromComparison(name, builds, facets, predicate, desc) {
* @return {Object} Comparison data object
*/
export function toComparison(code) {
return JSON.parse(LZString.decompressFromBase64(code.replace(/-/g, '/')));
return JSON.parse(LZString.decompressFromBase64(Utils.fromUrlSafe(code)));
};

View File

@@ -1,5 +1,6 @@
import * as Calc from './Calculations';
import * as ModuleUtils from './ModuleUtils';
import * as Utils from '../utils/UtilityFunctions';
import Module from './Module';
import LZString from 'lz-string';
import isEqual from 'lodash/lang';
@@ -601,15 +602,15 @@ export default class Ship {
code = parts[0];
if (parts[1]) {
enabled = LZString.decompressFromBase64(parts[1].replace(/-/g, '/')).split('');
enabled = Utils.fromUrlSafe(LZString.decompressFromBase64(parts[1])).split('');
}
if (parts[2]) {
priorities = LZString.decompressFromBase64(parts[2].replace(/-/g, '/')).split('');
priorities = Utils.fromUrlSafe(LZString.decompressFromBase64(parts[2])).split('');
}
if (parts[3]) {
const modstr = parts[3].replace(/-/g, '/');
const modstr = Utils.fromUrlSafe(parts[3]);
if (modstr.match(':')) {
this.decodeModificationsString(modstr, modifications);
} else {
@@ -1198,7 +1199,7 @@ export default class Ship {
priorities.push(slot.priority);
}
this.serialized.priorities = LZString.compressToBase64(priorities.join('')).replace(/\//g, '-');
this.serialized.priorities = Utils.toUrlSafe(LZString.compressToBase64(priorities.join('')));
return this;
}
@@ -1219,7 +1220,7 @@ export default class Ship {
enabled.push(slot.enabled ? 1 : 0);
}
this.serialized.enabled = LZString.compressToBase64(enabled.join('')).replace(/\//g, '-');
this.serialized.enabled = Utils.toUrlSafe(LZString.compressToBase64(enabled.join('')));
return this;
}
@@ -1265,7 +1266,7 @@ export default class Ship {
}
allMods.push(slotMods.join(';'));
}
this.serialized.modifications = LZString.compressToBase64(allMods.join(',').replace(/,+$/, '')).replace(/\//g, '-');
this.serialized.modifications = Utils.toUrlSafe(LZString.compressToBase64(allMods.join(',').replace(/,+$/, '')));
return this;
}
@@ -1386,7 +1387,7 @@ export default class Ship {
buffer.writeInt8(-1, curpos++);
}
this.serialized.modifications = zlib.gzipSync(buffer).toString('base64').replace(/\//g, '-');
this.serialized.modifications = Utils.toUrlSafe(zlib.gzipSync(buffer).toString('base64'));
} else {
this.serialized.modifications = null;
}

View File

@@ -151,6 +151,7 @@ export function shipFromJson(json) {
throw 'Unknown bulkheads "' + armourJson.name + '"';
}
ship.bulkheads.enabled = true;
if (armourJson.modifiers) _addModifications(ship.bulkheads.m, armourJson.modifiers);
// Add the standard modules
// Power plant
@@ -159,7 +160,7 @@ export function shipFromJson(json) {
if (powerplantJson.modifiers) _addModifications(powerplant, powerplantJson.modifiers);
ship.use(ship.standard[0], powerplant, true);
ship.standard[0].enabled = powerplantJson.on === true;
ship.standard[0].priority = powerplantJson.priority + 1;
ship.standard[0].priority = powerplantJson.priority;
// Thrusters
const thrustersJson = json.modules.MainEngines.module;
@@ -167,7 +168,7 @@ export function shipFromJson(json) {
if (thrustersJson.modifiers) _addModifications(thrusters, thrustersJson.modifiers);
ship.use(ship.standard[1], thrusters, true);
ship.standard[1].enabled = thrustersJson.on === true;
ship.standard[1].priority = thrustersJson.priority + 1;
ship.standard[1].priority = thrustersJson.priority;
// FSD
const frameshiftdriveJson = json.modules.FrameShiftDrive.module;
@@ -175,7 +176,7 @@ export function shipFromJson(json) {
if (frameshiftdriveJson.modifiers) _addModifications(frameshiftdrive, frameshiftdriveJson.modifiers);
ship.use(ship.standard[2], frameshiftdrive, true);
ship.standard[2].enabled = frameshiftdriveJson.on === true;
ship.standard[2].priority = frameshiftdriveJson.priority + 1;
ship.standard[2].priority = frameshiftdriveJson.priority;
// Life support
const lifesupportJson = json.modules.LifeSupport.module;
@@ -183,7 +184,7 @@ export function shipFromJson(json) {
if (lifesupportJson.modifiers)_addModifications(lifesupport, lifesupportJson.modifiers);
ship.use(ship.standard[3], lifesupport, true);
ship.standard[3].enabled = lifesupportJson.on === true;
ship.standard[3].priority = lifesupportJson.priority + 1;
ship.standard[3].priority = lifesupportJson.priority;
// Power distributor
const powerdistributorJson = json.modules.PowerDistributor.module;
@@ -191,7 +192,7 @@ export function shipFromJson(json) {
if (powerdistributorJson.modifiers) _addModifications(powerdistributor, powerdistributorJson.modifiers);
ship.use(ship.standard[4], powerdistributor, true);
ship.standard[4].enabled = powerdistributorJson.on === true;
ship.standard[4].priority = powerdistributorJson.priority + 1;
ship.standard[4].priority = powerdistributorJson.priority;
// Sensors
const sensorsJson = json.modules.Radar.module;
@@ -199,14 +200,14 @@ export function shipFromJson(json) {
if (sensorsJson.modifiers) _addModifications(sensors, sensorsJson.modifiers);
ship.use(ship.standard[5], sensors, true);
ship.standard[5].enabled = sensorsJson.on === true;
ship.standard[5].priority = sensorsJson.priority + 1;
ship.standard[5].priority = sensorsJson.priority;
// Fuel tank
const fueltankJson = json.modules.FuelTank.module;
const fueltank = _moduleFromEdId(fueltankJson.id);
ship.use(ship.standard[6], fueltank, true);
ship.standard[6].enabled = true;
ship.standard[6].priority = 1;
ship.standard[6].priority = 0;
// Add hardpoints
let hardpointClassNum = -1;
@@ -285,11 +286,11 @@ function _addModifications(module, modifiers) {
// Carry out the required changes
for (const action in modifierActions) {
const actionValue = modifierActions[action] * value;
let mod = module.getModValue(action);
let mod = module.getModValue(action) / 10000;
if (!mod) {
mod = 0;
}
module.setModValue(action, ((1 + mod / 10000) * (1 + actionValue) - 1) * 10000);
module.setModValue(action, ((1 + mod) * (1 + actionValue) - 1) * 10000);
}
}
@@ -299,20 +300,20 @@ function _addModifications(module, modifiers) {
// being a 4% boost they are a 104% multiplier. Unfortunately this means that our % modification
// is incorrect so we fix it
if (module.grp === 'sb' && module.getModValue('shieldboost')) {
const alteredBoost = (1 + module.shieldboost) * (module.getModValue('shieldboost'));
module.setModValue('shieldboost', alteredBoost / module.shieldboost);
const alteredBoost = (1 + module.shieldboost) * (module.getModValue('shieldboost') / 10000);
module.setModValue('shieldboost', alteredBoost * 10000 / module.shieldboost);
}
// Shield booster resistance is actually a damage modifier, so needs to be inverted.
if (module.grp === 'sb') {
if (module.getModValue('explres')) {
module.setModValue('explres', module.getModValue('explres') * -1);
module.setModValue('explres', ((module.getModValue('explres') / 10000) * -1) * 10000);
}
if (module.getModValue('kinres')) {
module.setModValue('kinres', module.getModValue('kinres') * -1);
module.setModValue('kinres', ((module.getModValue('kinres') / 10000) * -1) * 10000);
}
if (module.getModValue('thermres')) {
module.setModValue('thermres', module.getModValue('thermres') * -1);
module.setModValue('thermres', ((module.getModValue('thermres') / 10000) * -1) * 10000);
}
}
@@ -320,17 +321,43 @@ function _addModifications(module, modifiers) {
// In addition, the modification is based off the inherent resistance of the module
if (module.isShieldGenerator()) {
if (module.getModValue('explres')) {
module.setModValue('explres', (1 - (1 - module.explres) * (1 + module.getModValue('explres'))) - module.explres);
module.setModValue('explres', ((1 - (1 - module.explres) * (1 + module.getModValue('explres') / 10000)) - module.explres) * 10000);
}
if (module.getModValue('kinres')) {
module.setModValue('kinres', (1 - (1 - module.kinres) * (1 + module.getModValue('kinres')))- module.kinres);
module.setModValue('kinres', ((1 - (1 - module.kinres) * (1 + module.getModValue('kinres') / 10000)) - module.kinres) * 10000);
}
if (module.getModValue('thermres')) {
module.setModValue('thermres', (1 - (1 - module.thermres) * (1 + module.getModValue('thermres'))) - module.thermres);
module.setModValue('thermres', ((1 - (1 - module.thermres) * (1 + module.getModValue('thermres') / 10000)) - module.thermres) * 10000);
}
}
// Hull reinforcement package resistance is actually a damage modifier, so needs to be inverted.
if (module.grp === 'hr') {
if (module.getModValue('explres')) {
module.setModValue('explres', ((module.getModValue('explres') / 10000) * -1) * 10000);
}
if (module.getModValue('kinres')) {
module.setModValue('kinres', ((module.getModValue('kinres') / 10000) * -1) * 10000);
}
if (module.getModValue('thermres')) {
module.setModValue('thermres', ((module.getModValue('thermres') / 10000) * -1) * 10000);
}
}
// Bulkhead resistance is actually a damage modifier, so needs to be inverted.
// In addition, the modification is based off the inherent resistance of the module
if (module.grp == 'bh') {
if (module.getModValue('explres')) {
module.setModValue('explres', ((1 - (1 - module.explres) * (1 + module.getModValue('explres') / 10000)) - module.explres) * 10000);
}
if (module.getModValue('kinres')) {
module.setModValue('kinres', ((1 - (1 - module.kinres) * (1 + module.getModValue('kinres') / 10000)) - module.kinres) * 10000);
}
if (module.getModValue('thermres')) {
module.setModValue('thermres', ((1 - (1 - module.thermres) * (1 + module.getModValue('thermres') / 10000)) - module.thermres) * 10000);
}
}
//TODO do this for armour resistances as well ?
// Jitter is in degrees not % so need to divide it by 100 to obtain the correct number
if (module.getModValue('jitter')) {
@@ -339,7 +366,6 @@ function _addModifications(module, modifiers) {
// FD uses interval between bursts internally, so we need to translate this to a real rate of fire
if (module.getModValue('rof')) {
module.setModValue('rof', (1 / (1 + module.getModValue('jitter'))) - 1);
module.setModValue('rof', ((1 / (1 + module.getModValue('rof') / 10000)) - 1) * 10000);
}
}

View File

@@ -58,3 +58,21 @@ export function shallowEqual(objA, objB) {
return true;
}
/**
* Turn a base-64 encoded string in to a URL-safe version
* @param {string} data the string
* @return {string} the converted string
*/
export function toUrlSafe(data) {
return data.replace(/\\/g, '-').replace(/\+/g, '_');
}
/**
* Turn a URL-safe base-64 encoded string in to a normal version
* @param {string} data the string
* @return {string} the converted string
*/
export function fromUrlSafe(data) {
return data.replace(/-/g, '/').replace(/_/g, '+');
}