Merge branch 'release/2.5.2'

This commit is contained in:
willyb321
2018-04-13 07:56:38 +10:00
17 changed files with 579 additions and 20 deletions

21
.editorconfig Normal file
View File

@@ -0,0 +1,21 @@
root = true
[*]
# change these settings to your own preference
indent_style = space
indent_size = 4
# we recommend you to keep these unchanged
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
[{package,bower}.json]
indent_style = space
indent_size = 2

1
devServer.js Normal file → Executable file
View File

@@ -5,6 +5,7 @@ var config = require('./webpack.config.dev');
new WebpackDevServer(webpack(config), {
publicPath: config.output.publicPath,
hot: true,
disableHostCheck: true,
headers: { "Access-Control-Allow-Origin": "*" },
historyApiFallback: {
rewrites: [

13
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{
"name": "coriolis_shipyard",
"version": "2.5.0",
"version": "2.5.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -11961,6 +11961,17 @@
}
}
},
"webpack-notifier": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/webpack-notifier/-/webpack-notifier-1.6.0.tgz",
"integrity": "sha1-/6yOVf+MRpdSuMG7sBGhbxCYbgI=",
"dev": true,
"requires": {
"node-notifier": "5.1.2",
"object-assign": "4.1.1",
"strip-ansi": "3.0.1"
}
},
"webpack-sources": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-0.1.5.tgz",

View File

@@ -1,6 +1,6 @@
{
"name": "coriolis_shipyard",
"version": "2.5.1",
"version": "2.5.2",
"repository": {
"type": "git",
"url": "https://github.com/EDCD/coriolis"
@@ -87,10 +87,11 @@
"rollup": "0.41",
"rollup-plugin-node-resolve": "3",
"style-loader": "^0.16.1",
"uglify-js": "^2.4.11",
"url-loader": "^0.5.8",
"webpack": "^2.4.1",
"webpack-dev-server": "^2.4.4",
"uglify-js": "^2.4.11"
"webpack-notifier": "^1.6.0"
},
"dependencies": {
"babel-polyfill": "*",

View File

@@ -12,6 +12,7 @@ import ModalHelp from './components/ModalHelp';
import ModalImport from './components/ModalImport';
import ModalPermalink from './components/ModalPermalink';
import * as CompanionApiUtils from './utils/CompanionApiUtils';
import * as JournalUtils from './utils/JournalUtils';
import AboutPage from './pages/AboutPage';
import NotFoundPage from './pages/NotFoundPage';
@@ -92,7 +93,14 @@ export default class Coriolis extends React.Component {
// Need to decode and gunzip the data, then build the ship
const data = zlib.inflate(new Buffer(r.params.data, 'base64'), { to: 'string' });
const json = JSON.parse(data);
const ship = CompanionApiUtils.shipFromJson(json);
console.log('Ship import data: ');
console.log(json);
let ship;
if (json && json.modules) {
ship = CompanionApiUtils.shipFromJson(json);
} else if (json && json.Modules) {
ship = JournalUtils.shipFromLoadoutJSON(json);
}
r.params.ship = ship.id;
r.params.code = ship.toString();
this._setPage(OutfittingPage, r);

View File

@@ -96,7 +96,7 @@ export default class StandardSlot extends TranslatedComponent {
return (
<div className={cn('slot', { selected: this.props.selected })} onClick={this.props.onOpen} onContextMenu={stopCtxPropagation}>
<div className={cn('details-container', { warning: warning && warning(slot.m), disabled: m.grp !== 'bh' && !slot.enabled })}>
<div className={'sz'}>{slot.maxClass}</div>
<div className={'sz'}>{m.grp == 'bh' ? m.name.charAt(0) : slot.maxClass}</div>
<div>
<div className={'l'}>{classRating} {translate(m.name || m.grp)}{m.mods && Object.keys(m.mods).length > 0 ? <span className='r' onMouseOver={termtip.bind(null, modTT)} onMouseOut={tooltip.bind(null, null)}><Modified /></span> : null }</div>
<div className={'r'}>{formats.round(mass)}{units.T}</div>

View File

@@ -6,6 +6,7 @@ import * as FR from './fr';
import * as IT from './it';
import * as RU from './ru';
import * as PL from './pl';
import * as PT from './pt';
import * as d3 from 'd3';
let fallbackTerms = EN.terms;
@@ -25,6 +26,7 @@ export function getLanguage(langCode) {
case 'it': lang = IT; break;
case 'ru': lang = RU; break;
case 'pl': lang = PL; break;
case 'pt': lang = PT; break;
default:
lang = EN;
}
@@ -88,5 +90,6 @@ export const Languages = {
es: 'Español',
fr: 'Français',
ru: 'ру́сский',
pl: 'polski'
pl: 'polski',
pt: 'português'
};

16
src/app/i18n/pt.js Normal file
View File

@@ -0,0 +1,16 @@
export const formats = {
decimal: ',',
thousands: '.',
grouping: [3],
currency: ['', ' €'],
dateTime: '%A, %e de %B de %Y, %X',
date: '%d/%m/%Y',
time: '%H:%M:%S',
periods: ['AM', 'PM'],
days: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes', 'sábado'],
shortDays: ['dom', 'lun', 'mar', 'mié', 'jue', 'vie', 'sáb'],
months: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio', 'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'],
shortMonths: ['ene', 'feb', 'mar', 'abr', 'may', 'jun', 'jul', 'ago', 'sep', 'oct', 'nov', 'dic']
};
export { default as terms } from './pt.json';

278
src/app/i18n/pt.json Normal file

File diff suppressed because one or more lines are too long

View File

@@ -73,13 +73,10 @@ export default class OutfittingPage extends Page {
let buildName = params.bn;
let data = Ships[shipId]; // Retrieve the basic ship properties, slots and defaults
let savedCode = Persist.getBuild(shipId, buildName);
if (!data) {
return { error: { message: 'Ship not found: ' + shipId } };
}
let ship = new Ship(shipId, data.properties, data.slots); // Create a new Ship instance
if (code) {
ship.buildFrom(code); // Populate modules from serialized 'code' URL param
} else {

View File

@@ -194,6 +194,7 @@ export default class ShipyardPage extends Page {
<td className='cn'>{s.standard[3]}</td>
<td className='cn'>{s.standard[4]}</td>
<td className='cn'>{s.standard[5]}</td>
<td className='cn'>{s.standard[6]}</td>
<td className={cn({ disabled: !s.hp[1] })}>{s.hp[1]}</td>
<td className={cn({ disabled: !s.hp[2] })}>{s.hp[2]}</td>
<td className={cn({ disabled: !s.hp[3] })}>{s.hp[3]}</td>
@@ -329,7 +330,7 @@ export default class ShipyardPage extends Page {
<th>&nbsp;</th>
<th colSpan={4}>{translate('base')}</th>
<th colSpan={5}>{translate('max')}</th>
<th className='lft' colSpan={6}></th>
<th className='lft' colSpan={7}></th>
<th className='lft' colSpan={5}></th>
<th className='lft' colSpan={8}></th>
</tr>
@@ -347,7 +348,7 @@ export default class ShipyardPage extends Page {
<th className='sortable' onClick={sortShips('maxCargo')}>{translate('cargo')}</th>
<th className='sortable' onClick={sortShips('maxPassengers')}>{translate('passengers')}</th>
<th className='lft' colSpan={6}>{translate('core module classes')}</th>
<th className='lft' colSpan={7}>{translate('core module classes')}</th>
<th colSpan={5} className='sortable lft' onClick={sortShips('hpCount')}>{translate('hardpoints')}</th>
<th colSpan={8} className='sortable lft' onClick={sortShips('intCount')}>{translate('internal compartments')}</th>
</tr>
@@ -369,7 +370,7 @@ export default class ShipyardPage extends Page {
<th className='sortable' onMouseEnter={termtip.bind(null, 'life support')} onMouseLeave={hide} onClick={sortShips('standard', 3)}>{'ls'}</th>
<th className='sortable' onMouseEnter={termtip.bind(null, 'power distriubtor')} onMouseLeave={hide} onClick={sortShips('standard', 4)}>{'pd'}</th>
<th className='sortable' onMouseEnter={termtip.bind(null, 'sensors')} onMouseLeave={hide} onClick={sortShips('standard', 5)}>{'s'}</th>
<th className='sortable' onMouseEnter={termtip.bind(null, 'fuel tank')} onMouseLeave={hide} onClick={sortShips('standard', 6)}>{'ft'}</th>
<th className='sortable lft' onClick={sortShips('hp',1)}>{translate('S')}</th>
<th className='sortable' onClick={sortShips('hp', 2)}>{translate('M')}</th>
<th className='sortable' onClick={sortShips('hp', 3)}>{translate('L')}</th>
@@ -395,4 +396,4 @@ export default class ShipyardPage extends Page {
</div>
);
}
}
}

View File

@@ -63,7 +63,6 @@ export function standard(type, id) {
if (!isNaN(type)) {
type = StandardArray[type];
}
let s = Modules.standard[type].find(e => e.id == id || (e.class == id.charAt(0) && e.rating == id.charAt(1)));
if (s) {
s = new Module({ template: s });

View File

@@ -616,7 +616,7 @@ export default class Ship {
standard[i].cat = 0;
standard[i].priority = priorities && priorities[i + 1] ? priorities[i + 1] * 1 : 0;
standard[i].type = 'SYS';
standard[i].m = null; // Resetting 'old' modul if there was one
standard[i].m = null; // Resetting 'old' module if there was one
standard[i].discountedCost = 0;
if (comps) {
let module = ModuleUtils.standard(i, comps.standard[i]);

View File

@@ -36,13 +36,14 @@ const SHIP_FD_NAME_TO_CORIOLIS_NAME = {
'Type7': 'type_7_transport',
'Type9': 'type_9_heavy',
'Type9_Military': 'type_10_defender',
'TypeX': 'alliance_chieftain',
'Viper': 'viper',
'Viper_MkIV': 'viper_mk_iv',
'Vulture': 'vulture'
};
// Mapping from hardpoint class to name in companion API
const HARDPOINT_NUM_TO_CLASS = {
export const HARDPOINT_NUM_TO_CLASS = {
0: 'Tiny',
1: 'Small',
2: 'Medium',
@@ -114,7 +115,7 @@ function _shipModelFromEDName(edName) {
* @return {string} the Coriolis model of the ship
*/
export function shipModelFromJson(json) {
return _shipModelFromEDName(json.name);
return _shipModelFromEDName(json.name || json.Ship);
}
/**
@@ -144,7 +145,7 @@ export function shipFromJson(json) {
}
let rootModule;
// Add the bulkheads
const armourJson = json.modules.Armour.module;
if (armourJson.name.endsWith('_Armour_Grade1')) {
@@ -315,8 +316,6 @@ export function shipFromJson(json) {
*/
function _addModifications(module, modifiers, blueprint, grade, specialModifications) {
if (!modifiers) return;
console.log(module);
console.log(modifiers);
let special;
if (specialModifications) {
special = Modifications.specials[Object.keys(specialModifications)[0]]

View File

@@ -0,0 +1,221 @@
import Ship from '../shipyard/Ship'
import { HARDPOINT_NUM_TO_CLASS, shipModelFromJson } from './CompanionApiUtils'
import { Ships } from 'coriolis-data/dist'
import Module from '../shipyard/Module'
import { Modules } from '../../../../coriolis-data/dist'
/**
* Obtain a module given its FD Name
* @param {string} fdname the FD Name of the module
* @return {Module} the module
*/
function _moduleFromFdName(fdname) {
if (!fdname) return null;
fdname = fdname.toLowerCase();
// Check standard modules
for (const grp in Modules.standard) {
if (Modules.standard.hasOwnProperty(grp)) {
for (const i in Modules.standard[grp]) {
if (Modules.standard[grp][i].symbol && Modules.standard[grp][i].symbol.toLowerCase() === fdname) {
// Found it
return new Module({ template: Modules.standard[grp][i] });
}
}
}
}
// Check hardpoint modules
for (const grp in Modules.hardpoints) {
if (Modules.hardpoints.hasOwnProperty(grp)) {
for (const i in Modules.hardpoints[grp]) {
if (Modules.hardpoints[grp][i].symbol && Modules.hardpoints[grp][i].symbol.toLowerCase() === fdname) {
// Found it
return new Module({ template: Modules.hardpoints[grp][i] });
}
}
}
}
// Check internal modules
for (const grp in Modules.internal) {
if (Modules.internal.hasOwnProperty(grp)) {
for (const i in Modules.internal[grp]) {
if (Modules.internal[grp][i].symbol && Modules.internal[grp][i].symbol.toLowerCase() === fdname) {
// Found it
return new Module({ template: Modules.internal[grp][i] });
}
}
}
}
console.log(fdname)
// Not found
return null;
}
/**
* Build a ship from the journal Loadout event JSON
* @param {object} json the Loadout event JSON
* @return {Ship} the built ship
*/
export function shipFromLoadoutJSON(json) {
// Start off building a basic ship
const shipModel = shipModelFromJson(json);
if (!shipModel) {
throw 'No such ship found: "' + json.Ship + '"';
}
const shipTemplate = Ships[shipModel];
let ship = new Ship(shipModel, shipTemplate.properties, shipTemplate.slots);
ship.buildWith(null);
// Initial Ship building, don't do engineering yet.
for (const module of json.Modules) {
switch (module.Slot) {
// Cargo Hatch.
case 'CargoHatch':
ship.cargoHatch.enabled = module.On;
ship.cargoHatch.priority = module.Priority;
break;
// Add the bulkheads
case 'Armour':
if (module.Item.endsWith('_Armour_Grade1')) {
ship.useBulkhead(0, true);
} else if (module.Item.endsWith('_Armour_Grade2')) {
ship.useBulkhead(1, true);
} else if (module.Item.endsWith('_Armour_Grade3')) {
ship.useBulkhead(2, true);
} else if (module.Item.endsWith('_Armour_Mirrored')) {
ship.useBulkhead(3, true);
} else if (module.Item.endsWith('_Armour_Reactive')) {
ship.useBulkhead(4, true);
} else {
throw 'Unknown bulkheads "' + module.Item + '"';
}
ship.bulkheads.enabled = true;
break;
case 'PowerPlant':
const powerplant = _moduleFromFdName(module.Item);
ship.use(ship.standard[0], powerplant, true);
ship.standard[0].enabled = module.On;
ship.standard[0].priority = module.Priority;
break;
case 'MainEngines':
const thrusters = _moduleFromFdName(module.Item);
ship.use(ship.standard[1], thrusters, true);
ship.standard[1].enabled = module.On;
ship.standard[1].priority = module.Priority;
break;
case 'FrameShiftDrive':
const frameshiftdrive = _moduleFromFdName(module.Item);
ship.use(ship.standard[2], frameshiftdrive, true);
ship.standard[2].enabled = module.On;
ship.standard[2].priority = module.Priority;
break;
case 'LifeSupport':
const lifesupport = _moduleFromFdName(module.Item);
ship.use(ship.standard[3], lifesupport, true);
ship.standard[3].enabled = module.On === true;
ship.standard[3].priority = module.Priority;
break;
case 'PowerDistributor':
const powerdistributor = _moduleFromFdName(module.Item);
ship.use(ship.standard[4], powerdistributor, true);
ship.standard[4].enabled = module.On;
ship.standard[4].priority = module.Priority;
break;
case 'Radar':
const sensors = _moduleFromFdName(module.Item);
ship.use(ship.standard[5], sensors, true);
ship.standard[5].enabled = module.On;
ship.standard[5].priority = module.Priority;
break;
case 'FuelTank':
const fueltank = _moduleFromFdName(module.Item);
ship.use(ship.standard[6], fueltank, true);
ship.standard[6].enabled = true;
ship.standard[6].priority = 0;
break;
default:
}
if (module.Slot.search(/Hardpoint/) !== -1) {
// Add hardpoints
let hardpointClassNum = -1;
let hardpointSlotNum = -1;
let hardpointArrayNum = 0;
for (let i in shipTemplate.slots.hardpoints) {
if (shipTemplate.slots.hardpoints[i] === hardpointClassNum) {
// Another slot of the same class
hardpointSlotNum++;
} else {
// The first slot of a new class
hardpointClassNum = shipTemplate.slots.hardpoints[i];
hardpointSlotNum = 1;
}
// Now that we know what we're looking for, find it
const hardpointName = HARDPOINT_NUM_TO_CLASS[hardpointClassNum] + 'Hardpoint' + hardpointSlotNum;
const hardpointSlot = json.Modules.find(elem => elem.Slot === hardpointName);
if (!hardpointSlot) {
// This can happen with old imports that don't contain new hardpoints
} else if (!hardpointSlot) {
// No module
} else {
const hardpoint = _moduleFromFdName(hardpointSlot.Item);
ship.use(ship.hardpoints[hardpointArrayNum], hardpoint, true);
ship.hardpoints[hardpointArrayNum].enabled = hardpointSlot.On;
ship.hardpoints[hardpointArrayNum].priority = hardpointSlot.Priority;
}
hardpointArrayNum++;
}
}
if (module.Slot.search(/Slot\d/) !== -1) {
let internalSlotNum = 1;
let militarySlotNum = 1;
for (let i in shipTemplate.slots.internal) {
const isMilitary = isNaN(shipTemplate.slots.internal[i]) ? shipTemplate.slots.internal[i].name = 'Military' : false;
// The internal slot might be a standard or a military slot. Military slots have a different naming system
let internalSlot = null;
if (isMilitary) {
const internalName = 'Military0' + militarySlotNum;
internalSlot = json.Modules.find(elem => elem.Slot === internalName);
militarySlotNum++;
} else {
// Slot numbers are not contiguous so handle skips.
while (internalSlot === null && internalSlotNum < 99) {
// Slot sizes have no relationship to the actual size, either, so check all possibilities
for (let slotsize = 0; slotsize < 9; slotsize++) {
const internalName = 'Slot' + (internalSlotNum <= 9 ? '0' : '') + internalSlotNum + '_Size' + slotsize;
if (json.Modules.find(elem => elem.Slot === internalName)) {
internalSlot = json.Modules.find(elem => elem.Slot === internalName);
break;
}
}
internalSlotNum++;
}
}
if (!internalSlot) {
// This can happen with old imports that don't contain new slots
} else if (!internalSlot) {
// No module
} else {
const internalJson = internalSlot;
const internal = _moduleFromFdName(internalJson.Item);
ship.use(ship.internal[i], internal, true);
ship.internal[i].enabled = internalJson.On === true;
ship.internal[i].priority = internalJson.Priority;
}
}
}
}
// We don't have any information on it so guess it's priority 5 and disabled
if (!ship.cargoHatch) {
ship.cargoHatch.enabled = false;
ship.cargoHatch.priority = 4;
}
console.log(ship);
// Now update the ship's codes before returning it
return ship.updatePowerPrioritesString().updatePowerEnabledString().updateModificationsString();
}

View File

@@ -54,6 +54,7 @@ textarea {
width:100%;
min-height: 10em;
resize: vertical;
user-select: auto;
margin:2em 0;
}
}

View File

@@ -4,6 +4,7 @@ var webpack = require('webpack');
var pkgJson = require('./package');
var HtmlWebpackPlugin = require("html-webpack-plugin");
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var WebpackNotifierPlugin = require('webpack-notifier');
function CopyDirPlugin(source, destination) {
this.source = source;
@@ -51,6 +52,7 @@ module.exports = {
disable: false,
allChunks: true
}),
new WebpackNotifierPlugin({alwaysNotify: true}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin()
],