diff --git a/.gitignore b/.gitignore
index d958da9..bd40008 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,3 +20,13 @@ node_modules
*.ipr
*.iws
.idea/
+
+
+### Typescript/Babel
+packages/*/lib/
+.grunt
+.baseDir.ts
+.tscache
+tmp/*
+packages/*/typings/*
+!packages/*/typings/custom
diff --git a/package.json b/package.json
index ae0955a..37f5941 100644
--- a/package.json
+++ b/package.json
@@ -5,7 +5,7 @@
"update-all": "node ./scripts/npm-update-all.js"
},
"dependencies": {
- "async": "^2.0.0-rc.2",
+ "async": "^2.0.1",
"colors": "^1.1.2"
}
}
diff --git a/packages/maniajs-admin/src/game.js b/packages/maniajs-admin/src/game.js
new file mode 100644
index 0000000..845956d
--- /dev/null
+++ b/packages/maniajs-admin/src/game.js
@@ -0,0 +1,65 @@
+/**
+ * ADMIN COMMANDS - GAME ITSELF
+ */
+'use strict';
+
+
+/**
+ * Game Commands.
+ *
+ * @class
+ */
+module.exports.default = class {
+ constructor (plugin) {
+ this.plugin = plugin;
+ }
+
+ /**
+ * Register all the player commands.
+ *
+ * @param {object} manager
+ * @param {function} manager.on
+ */
+ register (manager) {
+
+ /**
+ * /admin players
+ * Full player list, of the well known players (from database).
+ */
+ manager.on('setmode', {
+ admin: true,
+ level: 3,
+ text: 'Set GameMode, rounds/ta/team/laps/cup/stunts'
+ }, (player, params) => this._setMode(player, params));
+ }
+
+
+ /**
+ * /admin setmode
+ *
+ * @param player
+ * @param params
+ * @private
+ */
+ _setMode (player, params) {
+ let mapping = {
+ rounds: 1,
+ ta: 2,
+ team: 3,
+ laps: 4,
+ cup: 5,
+ stunts: 6
+ };
+
+ if (params.length === 0 || ! mapping.hasOwnProperty(params[0])) {
+ return this.plugin.server.send().chat('$F66Syntax Error:$z $fff$n/admin setmode [rounds/ta/team/laps/cup/stunts]$z', {destination: player.login}).exec();
+ }
+
+ return Promise.all([
+ this.plugin.server.send()
+ .custom('SetGameMode', [mapping[params[0]]]).exec(),
+ this.plugin.server.send()
+ .chat(`$5A0Next game mode will be ${params[0]} and will be active from next map!`).exec()
+ ]);
+ }
+};
diff --git a/packages/maniajs-admin/src/map.js b/packages/maniajs-admin/src/map.js
index d23dcf7..f98865e 100644
--- a/packages/maniajs-admin/src/map.js
+++ b/packages/maniajs-admin/src/map.js
@@ -53,6 +53,16 @@ module.exports.default = class {
text: 'Replay current map, add to the jukebox.'
}, (player, params) => this._replay(player, params));
+ /**
+ * /admin endround
+ * End Round.
+ */
+ manager.on('endround', {
+ admin: true,
+ level: 2,
+ text: 'End current round.'
+ }, (player, params) => this._endround(player, params));
+
/**
* /admin savemaps
* Save matchsettings list to disk!
@@ -74,6 +84,11 @@ module.exports.default = class {
this.server.send().custom('RestartMap').exec();
}
+ _endround (player, params) {
+ this.server.send().chat('$fffEnd round...').exec();
+ this.server.send().custom('ForceEndRound').exec();
+ }
+
_replay (player, params) {
// TODO: Add support for maniajs-jukebox
if (this.plugin.maps.current.uid) {
diff --git a/packages/maniajs-admin/src/plugin.js b/packages/maniajs-admin/src/plugin.js
index 9bbb682..6af2c19 100644
--- a/packages/maniajs-admin/src/plugin.js
+++ b/packages/maniajs-admin/src/plugin.js
@@ -6,6 +6,7 @@ var Plugin = require('@maniajs/plugin').default;
var PlayerCommands = require('./player').default;
var MapCommands = require('./map').default;
+var GameCommands = require('./game').default;
/**
* ManiaJS Admin Plugin.
@@ -33,7 +34,8 @@ module.exports.default = class extends Plugin {
// Plugin Specific Variables
this.components = [
new PlayerCommands(this),
- new MapCommands(this)
+ new MapCommands(this),
+ new GameCommands(this)
];
}
diff --git a/packages/maniajs-cpdifference/.gitignore b/packages/maniajs-cpdifference/.gitignore
new file mode 100644
index 0000000..0de5731
--- /dev/null
+++ b/packages/maniajs-cpdifference/.gitignore
@@ -0,0 +1,34 @@
+### OS
+.DS_Store
+Thumbs.db
+
+### JetBrains template
+*.iml
+*.ipr
+*.iws
+.idea/
+.idea/mongoSettings.xml
+
+### Node template
+# Logs
+logs
+*.log
+npm-debug.log*
+
+# Runtime data
+pids
+*.pid
+*.seed
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+lib-cov
+
+# Coverage directory used by tools like istanbul
+coverage
+
+# Dependency directory
+node_modules
+
+### App Specific
+config.yaml
+database.sqlite
diff --git a/packages/maniajs-cpdifference/LICENSE b/packages/maniajs-cpdifference/LICENSE
new file mode 100644
index 0000000..e5fb4ee
--- /dev/null
+++ b/packages/maniajs-cpdifference/LICENSE
@@ -0,0 +1,13 @@
+Copyright (c) 2016, ManiaJS
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/packages/maniajs-cpdifference/README.md b/packages/maniajs-cpdifference/README.md
new file mode 100644
index 0000000..d1d7529
--- /dev/null
+++ b/packages/maniajs-cpdifference/README.md
@@ -0,0 +1,2 @@
+# maniajs-cpdifference
+ManiaJS Plugin - Displays difference between current CP time and CP time of local/dedimania record.
diff --git a/packages/maniajs-cpdifference/package.json b/packages/maniajs-cpdifference/package.json
new file mode 100644
index 0000000..33b8e7a
--- /dev/null
+++ b/packages/maniajs-cpdifference/package.json
@@ -0,0 +1,25 @@
+{
+ "name": "@maniajs/plugin-cpdifference",
+ "version": "0.0.0",
+ "main": "src/plugin.js",
+ "description": "ManiaJS Plugin - CP Difference Plugin, displays difference between current CP time and local/dedimania CP time.",
+ "keywords": [
+ "maniajs",
+ "maniaplanet",
+ "trackmania",
+ "plugin",
+ "cpdifference"
+ ],
+ "bugs": {
+ "url": "https://github.com/ManiaJS/plugins/issues"
+ },
+ "license": "ISC",
+ "repository": "https://github.com/ManiaJS/plugins/tree/master/packages/maniajs-cpdifference",
+ "engines": {
+ "node": ">=4.0.0"
+ },
+ "dependencies": {
+ "@maniajs/plugin": "0.*",
+ "async": "^2.0.1"
+ }
+}
diff --git a/packages/maniajs-cpdifference/src/models/.gitkeep b/packages/maniajs-cpdifference/src/models/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/packages/maniajs-cpdifference/src/plugin.js b/packages/maniajs-cpdifference/src/plugin.js
new file mode 100644
index 0000000..3a61e6d
--- /dev/null
+++ b/packages/maniajs-cpdifference/src/plugin.js
@@ -0,0 +1,214 @@
+'use strict';
+
+var Package = require('./../package.json');
+var path = require('path');
+
+var async = require('async');
+
+var Plugin = require('@maniajs/plugin').default;
+
+/**
+ * LocalRecords Plugin.
+ */
+module.exports.default = class extends Plugin {
+
+ constructor() {
+ super();
+
+ // Set the package stuff into the plugin context.
+ this.name = Package.name;
+ this.version = Package.version;
+ this.directory = __dirname;
+ this.records = null;
+
+ // Add dependencies, enter module full id's (mostly npm package names) here.
+ this.dependencies = ['@maniajs/plugin-localrecords'];
+ this.players = [];
+ }
+
+ /**
+ * Init will be run once the plugin can register everything at the core.
+ * From this point the {this.app} and all other injected variables are available.
+ *
+ * @return {Promise} The init should ALWAYS return a promise, the core will wait until the promise has been resolved!
+ */
+ init() {
+ this.cpWidget = this.app.ui.build(this, 'cpwidget', 1);
+ this.cpWidget.global({
+ manialinkid: 'CPDifference',
+ widget_x: -3.65,
+ widget_y: 21
+ });
+
+ this.server.on('trackmania.player.checkpoint',
+ (params) => this.playerCheckpoint(params));
+
+ this.server.on('player.connect', (params) => {
+ let player = this.players.list[params.login];
+ this.loadPlayerSetting(player);
+ });
+
+ this.server.on('player.disconnect', (params) => {
+ delete this.players[params.login];
+ });
+
+ Object.keys(this.players.list).forEach((login) => {
+ let player = this.players.list[login];
+ this.loadPlayerSetting(player);
+ });
+
+ this.server.command.on('cpdifference', 'Change your CP Difference setting', (player, params) => this.setPlayerSettingCommand(player, params));
+ this.server.command.on('cps', 'Change your CP Difference setting', (player, params) => this.setPlayerSettingCommand(player, params));
+
+ return Promise.resolve();
+ }
+
+ /**
+ * Loads CP Difference setting for player into the local playerlist.
+ *
+ * @param player
+ */
+ loadPlayerSetting(player) {
+ this.settings.get('cpDifference', player.id).then((setting) => {
+ if(! setting) {
+ this.setPlayerSetting(player, 'own');
+ } else {
+ this.players[player.login] = setting.value;
+ }
+ });
+ }
+
+ /**
+ * Saves CP Difference setting for player.
+ *
+ * @param player
+ * @param setting
+ */
+ setPlayerSetting(player, setting) {
+ this.players[player.login] = setting;
+ this.settings.set('cpDifference', player.id, setting);
+ }
+
+ /**
+ * Allows player to update their CP Difference setting.
+ *
+ * @param player
+ * @param params
+ */
+ setPlayerSettingCommand(player, params) {
+ switch(params[0]) {
+ case 'own':
+ this.setPlayerSetting(player, 'own');
+ this.server.send().chat('$fffSet CP Difference to use own record (or last local in case of no record).', {destination: player.login}).exec();
+ break;
+ case 'local':
+ this.setPlayerSetting(player, 'local');
+ this.server.send().chat('$fffSet CP Difference to use first local record.', {destination: player.login}).exec();
+ break;
+ case 'dedi':
+ this.setPlayerSetting(player, 'dedi');
+ this.server.send().chat('$fffSet CP Difference to use first dedimania record.', {destination: player.login}).exec();
+ break;
+ case 'help':
+ default:
+ let ownBold = '';
+ let localBold = '';
+ let dediBold = '';
+
+ switch(this.players[player.login]) {
+ case 'own':
+ ownBold = '$o';
+ break;
+ case 'local':
+ localBold = '$o';
+ break;
+ case 'dedi':
+ dediBold = '$o';
+ break;
+ }
+ this.server.send().chat('$fffUsage: /cpdifference (or /cps) [$eee' + ownBold + 'own (or last)' + ownBold + ', ' + localBold + 'local' + localBold + ', ' + dediBold + 'dedi' + dediBold + '$fff]', {destination: player.login}).exec();
+ break;
+ }
+ }
+
+ /**
+ * Function registers when a player passes a checkpoint and saves this in the current runs.
+ * playerId: 0,
+ * login: 1,
+ * timeOrScore: 2,
+ * curLap: 3,
+ * checkpoint: 4
+ *
+ * @param checkpoint
+ */
+ playerCheckpoint(checkpoint) {
+ let player = this.players.list[checkpoint.login];
+ if(this.players[player.login] == 'own') {
+ this.app.plugins['@maniajs/plugin-localrecords'].getPersonalMapRecord(this.maps.list[this.maps.current.uid], player).then((personalRecord) => {
+ if(personalRecord.rank != null) {
+ let checkpoints = personalRecord.checkpoints.split(',');
+ let currentCheckpoint = checkpoint.timeOrScore;
+ let recordCheckpoint = checkpoints[checkpoint.checkpoint];
+
+ this.displayUI(player, 'personal', currentCheckpoint, recordCheckpoint);
+ } else {
+ this.playerCheckpointLastRecord(player, checkpoint);
+ }
+ }).catch(() => {
+ this.playerCheckpointLastRecord(player, checkpoint);
+ });
+ } else if(this.players[player.login] == 'local') {
+ this.app.plugins['@maniajs/plugin-localrecords'].getMapRecord(this.maps.list[this.maps.current.uid]).then((localRecord) => {
+ let checkpoints = localRecord.checkpoints.split(',');
+ let currentCheckpoint = checkpoint.timeOrScore;
+ let recordCheckpoint = checkpoints[checkpoint.checkpoint];
+
+ this.displayUI(player, 'local', currentCheckpoint, recordCheckpoint);
+ });
+ }
+ }
+
+ /**
+ * Function requests last record to be displayed.
+ *
+ * @param player
+ * @param checkpoint
+ */
+ playerCheckpointLastRecord(player, checkpoint) {
+ this.app.plugins['@maniajs/plugin-localrecords'].getLastMapRecord(this.maps.list[this.maps.current.uid]).then((lastRecord) => {
+ let checkpoints = lastRecord.checkpoints.split(',');
+ let currentCheckpoint = checkpoint.timeOrScore;
+ let recordCheckpoint = checkpoints[checkpoint.checkpoint];
+
+ this.displayUI(player, 'last', currentCheckpoint, recordCheckpoint);
+ });
+ }
+
+ /**
+ * Display UI to the player.
+ *
+ * @param player
+ * @param recordType
+ * @param current
+ * @param comparison
+ */
+ displayUI(player, recordType, current, comparison) {
+ let difference = (current - comparison);
+ let improve = false;
+
+ let text = '';
+ if(difference < 0) {
+ improve = true;
+ difference *= -1;
+
+ text += '$00C-';
+ } else {
+ text += '$C00+';
+ }
+
+ text += this.app.util.times.stringTime(difference);
+
+ this.cpWidget.timeout = 2000;
+ this.cpWidget.player(player.login, {difference: text, recordType: recordType}).update();
+ }
+};
diff --git a/packages/maniajs-cpdifference/src/view/cpwidget.hbs b/packages/maniajs-cpdifference/src/view/cpwidget.hbs
new file mode 100644
index 0000000..a0bf813
--- /dev/null
+++ b/packages/maniajs-cpdifference/src/view/cpwidget.hbs
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/packages/maniajs-dedimania/.npmignore b/packages/maniajs-dedimania/.npmignore
new file mode 100644
index 0000000..b1c1070
--- /dev/null
+++ b/packages/maniajs-dedimania/.npmignore
@@ -0,0 +1,2 @@
+### Sources (non-es6)
+src/
diff --git a/packages/maniajs-dedimania/Gruntfile.js b/packages/maniajs-dedimania/Gruntfile.js
new file mode 100644
index 0000000..d0c8d55
--- /dev/null
+++ b/packages/maniajs-dedimania/Gruntfile.js
@@ -0,0 +1,38 @@
+'use strict';
+
+module.exports = function (grunt) {
+ require('load-grunt-config')(grunt, {
+ jitGrunt: {}
+ });
+ require('time-grunt')(grunt);
+
+ grunt.loadNpmTasks('grunt-contrib-clean');
+ grunt.loadNpmTasks('grunt-contrib-watch');
+ grunt.loadNpmTasks('grunt-contrib-copy');
+ grunt.loadNpmTasks('grunt-tslint');
+ grunt.loadNpmTasks('grunt-ts');
+ grunt.loadNpmTasks('grunt-nsp');
+
+ grunt.registerTask('build', [
+ 'clean:default',
+ 'tslint:default',
+ 'ts:default',
+ 'copy:default'
+ ]);
+
+ grunt.registerTask('dev', [
+ 'clean:default',
+ 'tslint:default',
+ 'ts:default',
+ 'copy:default',
+ 'watch'
+ ]);
+
+ grunt.registerTask('default', [
+ 'clean:default',
+ 'tslint:default',
+ 'ts:default',
+ 'copy:default',
+ 'watch'
+ ]);
+};
diff --git a/packages/maniajs-dedimania/grunt/clean.js b/packages/maniajs-dedimania/grunt/clean.js
new file mode 100644
index 0000000..2f6f3e1
--- /dev/null
+++ b/packages/maniajs-dedimania/grunt/clean.js
@@ -0,0 +1,7 @@
+'use strict';
+
+module.exports = {
+ default: [
+ 'lib/*'
+ ]
+};
diff --git a/packages/maniajs-dedimania/grunt/copy.js b/packages/maniajs-dedimania/grunt/copy.js
new file mode 100644
index 0000000..1816ce7
--- /dev/null
+++ b/packages/maniajs-dedimania/grunt/copy.js
@@ -0,0 +1,11 @@
+'use strict';
+
+module.exports = {
+ default: {
+ files: [
+ {
+ expand: true, cwd: 'src', src: ['**/*', '!**/*.ts'], dest: 'lib/', filter: 'isFile'
+ }
+ ]
+ }
+};
diff --git a/packages/maniajs-dedimania/grunt/nsp.js b/packages/maniajs-dedimania/grunt/nsp.js
new file mode 100644
index 0000000..5624792
--- /dev/null
+++ b/packages/maniajs-dedimania/grunt/nsp.js
@@ -0,0 +1,7 @@
+'use strict';
+
+module.exports = function (grunt, options) {
+ return {
+ package: grunt.file.readJSON('package.json')
+ };
+};
diff --git a/packages/maniajs-dedimania/grunt/ts.js b/packages/maniajs-dedimania/grunt/ts.js
new file mode 100644
index 0000000..6875599
--- /dev/null
+++ b/packages/maniajs-dedimania/grunt/ts.js
@@ -0,0 +1,25 @@
+'use strict';
+
+module.exports = {
+ default: {
+ tsconfig: true
+
+ }
+};
+
+let t = {
+ files: [
+ {
+ src: ['src/*/**.ts', 'src/*.ts'],
+ dest: 'lib'
+ },
+ // { src: 'test/**.ts' , dest: 'lib/test' }
+ ],
+
+ options: {
+ // tsconfig: __dirname + '/../../tsconfig.json',
+ // fast: 'never',
+ // module: 'es6',
+ // target: 'es6'
+ }
+};
diff --git a/packages/maniajs-dedimania/grunt/tslint.js b/packages/maniajs-dedimania/grunt/tslint.js
new file mode 100644
index 0000000..61c100a
--- /dev/null
+++ b/packages/maniajs-dedimania/grunt/tslint.js
@@ -0,0 +1,14 @@
+'use strict';
+
+module.exports = {
+ default: {
+ files: {
+ src: [
+ 'src/**.ts'
+ ]
+ }
+ },
+ options: {
+ configuration: 'tslint.json'
+ }
+};
diff --git a/packages/maniajs-dedimania/grunt/watch.js b/packages/maniajs-dedimania/grunt/watch.js
new file mode 100644
index 0000000..d69981f
--- /dev/null
+++ b/packages/maniajs-dedimania/grunt/watch.js
@@ -0,0 +1,18 @@
+'use strict';
+
+module.exports = {
+ ts: {
+ files: [
+ 'src/**/*.ts',
+ 'src/**/*',
+ 'test/**/*.ts'
+ ],
+ tasks: ['clean:default', 'tslint', 'ts:default', 'copy:default']
+ },
+ test: {
+ files: [
+ 'out/**/*.js'
+ ],
+ tasks: []
+ }
+};
diff --git a/packages/maniajs-dedimania/package.json b/packages/maniajs-dedimania/package.json
index 415622a..a029e8e 100644
--- a/packages/maniajs-dedimania/package.json
+++ b/packages/maniajs-dedimania/package.json
@@ -24,10 +24,39 @@
"engines": {
"node": ">=4.0.0"
},
- "main": "src/plugin.js",
+ "scripts": {
+ "devtools": "npm i -g typescript typings grunt-cli typedoc && typings install",
+ "ts": "grunt ts",
+ "watch": "grunt watch",
+ "start": "node ./maniajs.js",
+ "dev": "npm run build && node ./maniajs.js",
+ "build": "grunt build",
+ "prepublish": "npm run build"
+ },
+ "main": "lib/plugin.js",
"dependencies": {
- "async": "^1.5.2",
"@maniajs/plugin": "0.*",
- "@maniajs/xmlrpc": "^2.0.0-beta.4"
+ "@maniajs/xmlrpc": "^2.0.0-beta.4",
+ "async": "^2.0.1",
+ "pjson": "^1.0.7"
+ },
+ "devDependencies": {
+ "chai": "^3.5.0",
+ "dts-generator": "^1.7.0",
+ "eslint": "^3.3.1",
+ "grunt": "^1.0.1",
+ "grunt-contrib-clean": "^1.0.0",
+ "grunt-contrib-copy": "^1.0.0",
+ "grunt-contrib-watch": "^1.0.0",
+ "grunt-nsp": "^2.3.1",
+ "grunt-ts": "^5.5.1",
+ "grunt-tslint": "^3.2.0",
+ "load-grunt-config": "^0.19.2",
+ "source-map-support": "^0.4.2",
+ "time-grunt": "^1.4.0",
+ "tslint": "^3.14.0",
+ "typedoc": "^0.4.5",
+ "typescript": "^1.8.10",
+ "typings": "^1.3.2"
}
}
diff --git a/packages/maniajs-dedimania/src/logic/DedimaniaClient.ts b/packages/maniajs-dedimania/src/logic/DedimaniaClient.ts
new file mode 100644
index 0000000..71d5caa
--- /dev/null
+++ b/packages/maniajs-dedimania/src/logic/DedimaniaClient.ts
@@ -0,0 +1,39 @@
+/**
+ * Holds Connection and does stuff with the Dedimania API.
+ *
+ * @author Tom Valk
+ * @date 06-03-16
+ */
+
+import * as xmlrpc from '@maniajs/xmlrpc';
+import {EventEmitter} from 'events';
+
+import * as util from 'util';
+import * as os from 'os';
+import * as Package from 'pjson';
+
+import Plugin from '../plugin';
+
+/**
+ * Dedimania Logic.
+ *
+ */
+export class DedimaniaClient extends EventEmitter {
+
+ private plugin: Plugin;
+
+ constructor (options) {
+ super();
+
+ this.plugin = options.plugin;
+ }
+
+
+ public async init() {
+ console.log('INIT DEDICLIENT');
+ console.log('INIT DEDICLIENT');
+ console.log('INIT DEDICLIENT');
+ return;
+ }
+}
+
diff --git a/packages/maniajs-dedimania/src/logic/Widget.ts b/packages/maniajs-dedimania/src/logic/Widget.ts
new file mode 100644
index 0000000..9fa0ffe
--- /dev/null
+++ b/packages/maniajs-dedimania/src/logic/Widget.ts
@@ -0,0 +1,30 @@
+/**
+ * Dedimania Widget
+ * @author Tom Valk
+ * @date 06-03-16
+ */
+
+import Plugin from '../plugin';
+
+/**
+ * Widget Logic.
+ *
+ * @class Widget
+ * @type {Widget}
+ *
+ * @property {App} app
+ * @property {Plugin} plugin
+ * @property {Flow} flow
+ */
+export class Widget {
+
+ private plugin: Plugin;
+
+ constructor (plugin) {
+ this.plugin = plugin;
+ }
+
+ public async init() {
+
+ }
+}
diff --git a/packages/maniajs-dedimania/src/plugin.js b/packages/maniajs-dedimania/src/plugin.js
deleted file mode 100644
index 0dc9331..0000000
--- a/packages/maniajs-dedimania/src/plugin.js
+++ /dev/null
@@ -1,351 +0,0 @@
-'use strict';
-
-var Package = require('./../package.json');
-var path = require('path');
-
-var Plugin = require('@maniajs/plugin').default;
-
-var Dedimania = require('./logic/dedimania').default;
-var Widget = require('./logic/widget').default;
-var Flow = require('./logic/flow').default;
-
-/**
- * DediMania Plugin.
- *
- * @property {Dedimania} dedimania
- * @property {object} serverInfo
- * @property {number} serverInfo.ServerMaxRank
- *
- * @property {Widget} widget
- */
-module.exports.default = class extends Plugin {
-
- constructor() {
- super();
-
- // Set the package stuff into the plugin context.
- this.name = Package.name;
- this.version = Package.version;
- this.directory = __dirname;
-
- // Add dependencies, enter module full id's (mostly npm package names) here.
- this.dependencies = [];
-
- // Game Requirements
- this.game.games = ['trackmania']; // Only for trackmania
- this.game.modes = [1, 2, 3, 4, 5]; // rounds,timeattack,team,laps,cup
-
- // Plugin properties
- this.client = null;
- this.session = null;
-
- this.newRecords = []; // Holds newly driven records. (queue to send to the dedimania server).
- this.playerInfo = []; // Holds info like max record limit and if banned, etc.
-
- // Server Record Limit
- this.serverInfo = {};
- this.displaylimit = 50;
-
- this.chatdisplay = true;
- this.chatannounce = true;
-
- // Dedimania Logic
- this.dedimania = new Dedimania({
- host: 'dedimania.net',
- port: 8081,
- path: '/Dedimania',
- debug: true
- });
-
- // Widget Logic
- this.widget = new Widget(this);
-
- // Game Flow Logic
- this.flow = new Flow(this);
-
-
- this.timerUpdate = null;
- }
-
- /**
- * Init will be run once the plugin can register everything at the core.
- * From this point the {this.app} and all other injected variables are available.
- *
- * @return {Promise} The init should ALWAYS return a promise, the core will wait until the promise has been resolved!
- */
- init() {
- return new Promise((resolve, reject) => {
- // Verify config
- if ( ! this.config || ! this.config.hasOwnProperty('login') || this.config.login === ''
- || ! this.config.hasOwnProperty('dedimaniacode') || this.config.dedimaniacode === '') {
- return reject(new Error('Dedimania plugin needs a server login and dedimania code!'));
- }
-
- // Set the dedimania stuff.
- this.dedimania.config = this.config;
- this.dedimania.app = this.app;
- this.dedimania.plugin = this;
- // UI
- this.widget.init(this.app.ui.build(this, 'recordswidget', 1));
- // Flow
- this.flow.init();
-
-
-
- // Events
- this.server.on('map.begin',
- (params) => { this.beginMap(params) });
- this.server.on('map.end',
- (params) => { this.endMap(params) });
-
- this.server.on('player.connect',
- (params) => { this.playerConnect(params) });
- this.server.on('player.disconnect',
- (params) => { this.playerDisconnect(params) });
-
- this.server.on('trackmania.player.finish',
- (params) => { this.playerFinish(params) });
-
- this.server.on('trackmania.player.checkpoint',
- (params) => { this.playerCheckpoint(params) });
-
-
- // Open session.
- this.dedimania.open().then(()=>{
- return this.dedimania.start();
- }).then(()=> {
- this.dedimania.getRecords();
-
- // Start timer.
- this.timerUpdate = setInterval(() => {
- this.dedimania.updatePlayers();
- }, 240000); // 4 minutes.
- });
-
-
-
- // Fetch records event.
- this.dedimania.on('fetched', (records) => {
- this.flow.setRecords(records);
-
- // Start flow (and check if map is allowed)
- this.flow.mapCheck().then((allowed) => {
- if (allowed) {
- // Dispaly Records
- this.displayRecords();
- this.displayPersonalRecords();
- } else {
- // Remove widget
- this.widget.hideAll();
- }
- });
- });
-
- return resolve();
- });
- }
-
-
- /**
- * Begin Map callback.
- * @param map
- */
- beginMap(map) {
- this.runs = [];
-
- // Dedimania Logic. Update Map.
- this.dedimania.game.map = map;
- // Load records. This will fire the done event.
- this.dedimania.getRecords();// will trigger ui after fetched
-
- // Reset, new map loaded!
- this.flow.reset();
- this.flow.start();
-
- // Set timer.
- this.timerUpdate = setInterval(() => {
- this.dedimania.updatePlayers();
- }, 240000); // 4 minutes.
- }
-
- /**
- * End Map callback.
- * @param map
- */
- endMap(map) {
- // Clear Interval
- if (this.timerUpdate) {
- clearInterval(this.timerUpdate);
- }
-
- // Send records to dedimania
- this.flow.end();
- }
-
- playerConnect(params) {
- let player = this.players.list[params.login];
-
- // Send to dedimania
- this.dedimania.sendConnect(player);
-
- // Load records pane and text
- this.displayTextualRecord(player);
- this.widget.displayRecordsWidget(player);
- }
-
- playerDisconnect(params) {
- let player = this.players.list[params.login];
-
- // Send disconnect
- this.dedimania.sendDisconnect(player);
-
- // Cleanup
- // TODO;
- }
-
- /**
- * Function registers when a player finished and updates/inserts a local record if it's his/her best new time.
- *
- * @param {{login: string, timeOrScore: number}} finish
- */
- playerFinish(finish) {
- let login = finish.login;
- let player = this.players.list[login];
- let time = finish.timeOrScore;
-
- if (time > 0 && player && this.dedimania.playerData.hasOwnProperty(login)) {
- this.flow.finish(player, time);
- }
-
- return;
-
- if(time > 0) {
- let player = this.players.list[login];
- var record = this.flow.records.filter(function (rec) { return rec.PlayerId == player.id; });
-
- if (record.length == 1) {
- // Already has a local record
- if(time < record[0].score) {
- var previousTime = record[0].score;
- var previousIndex = this.flow.records.indexOf(record[0]);
-
- record[0].score = time;
- if(this.runs[login]) {
- record[0].checkpoints = this.runs[login];
- } else {
- record[0].checkpoints = '';
- }
- record[0].save();
-
- this.flow.records = this.flow.records.sort((a, b) => a.score - b.score);
- var newIndex = this.flow.records.indexOf(record[0]);
-
- var improvedRecordText = '';
- if(newIndex < previousIndex) {
- improvedRecordText = '$090$<$fff' + player.nickname + '$>$090 gained the $fff' + (newIndex + 1) + '$090. Local Record, with a time of $fff' + this.app.util.times.stringTime(record[0].score) + '$090 ($fff' + (previousIndex + 1) + '$090. $fff' + this.app.util.times.stringTime(previousTime) + '$090)!';
- } else {
- improvedRecordText = '$090$<$fff' + player.nickname + '$>$090 improved his/her $fff' + (newIndex + 1) + '$090., with a time of $fff' + this.app.util.times.stringTime(record[0].score) + '$090 ($fff' + this.app.util.times.stringTime(previousTime) + '$090).';
- }
- this.server.send().chat(improvedRecordText).exec();
- } else if(time == record[0].score) {
- var equalledRecordText = '$090$<$fff' + player.nickname + '$>$090 equalled his/her $fff' + (this.flow.records.indexOf(record[0]) + 1) + '$090. Local Record, with a time of $fff' + this.app.util.times.stringTime(record[0].score) + '$090...';
- this.server.send().chat(equalledRecordText).exec();
- }
- } else {
- // Does not have a local record yet
- var newRecord = this.models.LocalRecord.build({
- score: time,
- Map: this.maps.current,
- Player: player,
- MapId: this.maps.current.id,
- PlayerId: player.id
- });
-
- newRecord.checkpoints = this.runs[login]? this.runs[login] : '';
-
- this.flow.records.push(newRecord);
- this.flow.records = this.flow.records.sort((a, b) => a.score - b.score);
- var newRecordText = '$090$<$fff' + player.nickname + '$>$090 drove the $fff' + (this.flow.records.indexOf(newRecord) + 1) + '$090. Local Record, with a time of $fff' + this.app.util.times.stringTime(newRecord.score) + '$090!';
- this.server.send().chat(newRecordText).exec();
-
- newRecord.save();
- }
- }
- }
-
- /**
- * Function registers when a player passes a checkpoint and saves this in the current runs.
- * playerId
- * login
- * timeOrScore
- * curLap
- * checkpoint
- *
- * @param {{login: string, timeOrScore: number}} params
- */
- playerCheckpoint(params) {
- let login = params.login;
- let player = this.players.list[login];
- let time = params.timeOrScore;
-
- if (player) {
- this.flow.checkpoint (player, time);
- }
- }
-
-
-
-
-
-
-
-
-
-
- displayRecords() {
- if (this.flow.records) {
- var text = '$39fDedimania Records on $<$fff' + this.maps.current.name + '$>$39f (' + (this.flow.records.length - 1) + '): ';
-
- for(var recordPos = 0; (recordPos < 5 && recordPos < this.flow.records.length); recordPos++) {
- text += '$fff' + (recordPos + 1) + '$39f. $<$fff' + this.flow.records[recordPos].NickName + '$>$39f [$fff' + this.app.util.times.stringTime(this.flow.records[recordPos].Best) + '$39f] ';
- }
-
- this.server.send().chat(text).exec();
- }
- }
-
-
-
-
- displayPersonalRecords () {
- Object.keys(this.players.list).forEach((login) => {
- let player = this.players.list[login];
- this.displayTextualRecord(player);
- this.widget.displayRecordsWidget(player);
- });
- }
-
- /**
- * Displays the dedimania record for the player.
- *
- * @param player
- */
- displayTextualRecord (player) {
- var text = '$0f3You do not have a Dedimania Record on this map.';
-
- var record = [];
- if (this.flow.records.length > 0) {
- record = this.flow.records.filter(function (rec) {
- return rec.Login == player.login;
- });
- }
-
- if (record.length == 1) {
- record = record[0];
- var recordIndex = (this.flow.records.indexOf(record) + 1);
- text = '$0f3Your current Dedimania Record is: $fff' + recordIndex + '$0f3. with a time of $fff' + this.app.util.times.stringTime(record.Best) + '$0f3.';
- }
-
- this.server.send().chat(text, {destination: player.login}).exec();
- }
-};
diff --git a/packages/maniajs-dedimania/src/plugin.ts b/packages/maniajs-dedimania/src/plugin.ts
new file mode 100644
index 0000000..ea094d8
--- /dev/null
+++ b/packages/maniajs-dedimania/src/plugin.ts
@@ -0,0 +1,62 @@
+///
+import * as Package from 'pjson';
+import * as path from 'path';
+
+import {BasePlugin} from '@maniajs/plugin';
+import {DedimaniaClient} from './logic/DedimaniaClient';
+
+/*var Dedimania = require('./logic/dedimania').default;
+var Widget = require('./logic/widget').default;
+var Flow = require('./logic/flow').default;
+*/
+
+export default class Plugin extends BasePlugin {
+
+ public dedimania: DedimaniaClient;
+ public widget;
+ public flow;
+
+ constructor () {
+ super();
+
+ // Package info and directory.
+ this.name = Package.name;
+ this.version = Package.version;
+ this.directory = __dirname;
+
+ // Set the package stuff into the plugin context.
+ this.name = Package.name;
+ this.version = Package.version;
+ this.directory = __dirname;
+
+ // Add dependencies, enter module full id's (mostly npm package names) here.
+ this.dependencies = [];
+
+ // Game Requirements
+ this.game.games = ['trackmania']; // Only for trackmania
+ this.game.modes = [1, 2, 3, 4, 5]; // rounds,timeattack,team,laps,cup
+
+ // Init logic components
+ this.dedimania = new DedimaniaClient({
+ host: 'dedimania.net',
+ port: 8081,
+ path: '/Dedimania',
+ debug: true,
+ plugin: this
+ });
+ }
+
+ public async init() {
+ // Verify configuration.
+ if (! this.config || ! this.config.hasOwnProperty('login') || ! this.config.hasOwnProperty('dedimaniacode')
+ || ! this.config.login || ! this.config.dedimaniacode) {
+ throw new Error('Dedimania Plugin needs server login and dedimaniacode in the config file!');
+ }
+
+ await this.dedimania.init();
+
+ console.log('JAJAJJAJAJ');
+ console.log('JAJAJJAJAJ');
+ console.log('JAJAJJAJAJ');
+ }
+}
diff --git a/packages/maniajs-dedimania/tsconfig.json b/packages/maniajs-dedimania/tsconfig.json
new file mode 100644
index 0000000..a6d41ad
--- /dev/null
+++ b/packages/maniajs-dedimania/tsconfig.json
@@ -0,0 +1,37 @@
+{
+ "compilerOptions": {
+ "target": "ES6",
+ "module": "commonjs",
+ "moduleResolution": "classic",
+ "emitDecoratorMetadata": true,
+ "experimentalDecorators": true,
+ "sourceMap": true,
+ "removeComments": false,
+ "noImplicitAny": false,
+ "outDir": "./lib"
+ },
+ "exclude": [
+ "node_modules",
+ "./typings/*/**.d.ts"
+ ],
+ "filesGlob": [
+ "./src/**/*.ts",
+ "./src/*.ts",
+ "./test/**/*.ts",
+ "!./node_modules/**/*.ts"
+ ],
+ "awesomeTypescriptLoaderOptions": {
+ "resolveGlobs": true,
+ "forkChecker": true
+ },
+ "compileOnSave": false,
+ "buildOnSave": false,
+ "atom": {
+ "rewriteTsconfig": false
+ },
+ "files": [
+ "src/logic/DedimaniaClient.ts",
+ "src/logic/Widget.ts",
+ "src/plugin.ts"
+ ]
+}
\ No newline at end of file
diff --git a/packages/maniajs-dedimania/tslint.json b/packages/maniajs-dedimania/tslint.json
new file mode 100644
index 0000000..a907161
--- /dev/null
+++ b/packages/maniajs-dedimania/tslint.json
@@ -0,0 +1,134 @@
+{
+ "rules": {
+ "member-access": false,
+ "member-ordering": [
+ true,
+ "public-before-private",
+ "static-before-instance",
+ "variables-before-functions"
+ ],
+ "no-any": false,
+ "no-inferrable-types": false,
+ "no-internal-module": true,
+ "no-var-requires": false,
+ "typedef": false,
+ "typedef-whitespace": [
+ true,
+ {
+ "call-signature": "nospace",
+ "index-signature": "nospace",
+ "parameter": "nospace",
+ "property-declaration": "nospace",
+ "variable-declaration": "nospace"
+ },
+ {
+ "call-signature": "space",
+ "index-signature": "space",
+ "parameter": "space",
+ "property-declaration": "space",
+ "variable-declaration": "space"
+ }
+ ],
+ "ban": false,
+ "curly": false,
+ "forin": true,
+ "label-position": true,
+ "label-undefined": true,
+ "no-arg": true,
+ "no-bitwise": true,
+ "no-conditional-assignment": true,
+ "no-console": [
+ true,
+ "debug",
+ "info",
+ "time",
+ "timeEnd",
+ "trace"
+ ],
+ "no-construct": true,
+ "no-debugger": true,
+ "no-duplicate-key": true,
+ "no-duplicate-variable": true,
+ "no-empty": false,
+ "no-eval": true,
+ "no-null-keyword": false,
+ "no-shadowed-variable": true,
+ "no-string-literal": false,
+ "no-switch-case-fall-through": true,
+ "no-unreachable": true,
+ "no-unused-expression": true,
+ "no-unused-variable": false,
+ "no-use-before-declare": true,
+ "no-var-keyword": false,
+ "radix": true,
+ "switch-default": true,
+ "triple-equals": [
+ true,
+ "allow-null-check"
+ ],
+ "use-strict": [
+ true,
+ "check-module"
+ ],
+ "eofline": true,
+ "indent": [
+ true,
+ "spaces"
+ ],
+ "max-line-length": [
+ true,
+ 120
+ ],
+ "no-require-imports": false,
+ "no-trailing-whitespace": true,
+ "object-literal-sort-keys": false,
+ "trailing-comma": [
+ true,
+ {
+ "multiline": "never",
+ "singleline": "never"
+ }
+ ],
+ "align": false,
+ "class-name": true,
+ "comment-format": [
+ true,
+ "check-space"
+ ],
+ "interface-name": false,
+ "jsdoc-format": true,
+ "no-consecutive-blank-lines": false,
+ "no-constructor-vars": false,
+ "one-line": [
+ true,
+ "check-open-brace",
+ "check-catch",
+ "check-else",
+ "check-finally",
+ "check-whitespace"
+ ],
+ "quotemark": [
+ true,
+ "single",
+ "avoid-escape"
+ ],
+ "semicolon": [
+ true,
+ "always"
+ ],
+ "variable-name": [
+ true,
+ "check-format",
+ "allow-leading-underscore",
+ "ban-keywords"
+ ],
+ "whitespace": [
+ true,
+ "check-branch",
+ "check-decl",
+ "check-operator",
+ "check-separator",
+ "check-type"
+ ]
+ }
+}
diff --git a/packages/maniajs-dedimania/typedoc.json b/packages/maniajs-dedimania/typedoc.json
new file mode 100644
index 0000000..186b50c
--- /dev/null
+++ b/packages/maniajs-dedimania/typedoc.json
@@ -0,0 +1,15 @@
+{
+ "mode": "modules",
+ "out": "doc",
+ "theme": "default",
+ "ignoreCompilerErrors": "true",
+ "experimentalDecorators": "true",
+ "emitDecoratorMetadata": "true",
+ "target": "ES6",
+ "moduleResolution": "node",
+ "preserveConstEnums": "true",
+ "stripInternal": "true",
+ "suppressExcessPropertyErrors": "true",
+ "suppressImplicitAnyIndexErrors": "true",
+ "module": "commonjs"
+}
diff --git a/packages/maniajs-dedimania/typings.json b/packages/maniajs-dedimania/typings.json
new file mode 100644
index 0000000..d94c656
--- /dev/null
+++ b/packages/maniajs-dedimania/typings.json
@@ -0,0 +1,14 @@
+{
+ "name": "@maniajs/dedimania",
+ "globalDependencies": {
+ "@maniajs/xmlrpc": "file:typings/custom/@maniajs/xmlrpc/typings.json",
+ "lodash": "registry:dt/lodash#3.10.0+20160330154726",
+ "maniajs": "https://raw.githubusercontent.com/ManiaJS/ManiaJS/master/type/maniajs.d.ts",
+ "node": "registry:dt/node#6.0.0+20160608110640",
+ "pjson": "file:./typings/custom/pjson/typings.json",
+ "sequelize": "registry:dt/sequelize#3.4.1+20160423143634",
+ "validator": "registry:dt/validator#4.5.1+20160316155526"
+ },
+ "devDependencies": {},
+ "dependencies": {}
+}
diff --git a/packages/maniajs-dedimania/typings/custom/.gitkeep b/packages/maniajs-dedimania/typings/custom/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/packages/maniajs-dedimania/typings/custom/@maniajs/xmlrpc/index.d.ts b/packages/maniajs-dedimania/typings/custom/@maniajs/xmlrpc/index.d.ts
new file mode 100644
index 0000000..3eb3ee5
--- /dev/null
+++ b/packages/maniajs-dedimania/typings/custom/@maniajs/xmlrpc/index.d.ts
@@ -0,0 +1,5 @@
+
+declare module '@maniajs/xmlrpc' {
+ var xmlrpc: any;
+ export = xmlrpc;
+}
diff --git a/packages/maniajs-dedimania/typings/custom/@maniajs/xmlrpc/typings.json b/packages/maniajs-dedimania/typings/custom/@maniajs/xmlrpc/typings.json
new file mode 100644
index 0000000..f684b3a
--- /dev/null
+++ b/packages/maniajs-dedimania/typings/custom/@maniajs/xmlrpc/typings.json
@@ -0,0 +1,4 @@
+{
+ "name": "@maniajs/xmlrpc",
+ "main": "index.d.ts"
+}
diff --git a/packages/maniajs-dedimania/typings/custom/pjson/index.d.ts b/packages/maniajs-dedimania/typings/custom/pjson/index.d.ts
new file mode 100644
index 0000000..15b4148
--- /dev/null
+++ b/packages/maniajs-dedimania/typings/custom/pjson/index.d.ts
@@ -0,0 +1,195 @@
+interface pjsonPerson {
+ name : string;
+ url : string;
+ email : string;
+}
+
+declare module "pjson" {
+ /**
+ * The name of the package.
+ */
+ export var name : string;
+
+ /**
+ * Version must be parseable by node-semver, which is
+ * bundled with npm as a dependency.
+ */
+ export var version : string;
+
+ /**
+ * This helps people discover your package, as it's
+ * listed in 'npm search'.
+ */
+ export var description : string;
+
+ /**
+ * This helps people discover your package as it's
+ * listed in 'npm search'.
+ */
+ export var keywords : string[];
+
+ /**
+ * The url to the project homepage.
+ */
+ export var homepage : string;
+
+ /**
+ * The url to your project's issue tracker and / or the email
+ * address to which issues should be reported. These are
+ * helpful for people who encounter issues with your package.
+ */
+ export var bugs : {
+
+ /**
+ * The url to your project's issue tracker.
+ */
+ url : string;
+
+ /**
+ * The email address to which issues should be reported.
+ */
+ email: string;
+ };
+
+ /**
+ * You should specify a license for your package so that
+ * people know how they are permitted to use it, and any
+ * restrictions you're placing on it.
+ */
+ export var license : string;
+
+ /**
+ * A person who has been involved in creating or maintaining this package
+ */
+ export var author : pjsonPerson;
+
+ /**
+ * A list of people who contributed to this package.
+ */
+ export var contributors : pjsonPerson[];
+
+ /**
+ * A list of people who maintains this package.
+ */
+ export var maintainers : pjsonPerson[];
+
+ /**
+ * The 'files' field is an array of files to include in your project.
+ * If you name a folder in the array, then it will also include
+ * the files inside that folder.
+ */
+ export var files : string[];
+
+ /**
+ * The main field is a module ID that is the primary entry point to your program.
+ */
+ export var main : string;
+
+ /**
+ * Names of binaries for this package
+ */
+ export var bin : {};
+
+ /**
+ * Specify either a single file or an array of filenames to put in place for the man program to find.
+ */
+ export var man : string[];
+
+ /**
+ * Recognized directories for the package
+ */
+ export var directories : {
+ /**
+ * If you specify a 'bin' directory, then all the files in that folder will be used as the 'bin' hash.
+ */
+ bin: string;
+
+ /**
+ * Put markdown files in here. Eventually, these will be displayed nicely, maybe, someday.
+ */
+ doc: string;
+
+ /**
+ * Put example scripts in here. Someday, it might be exposed in some clever way.
+ */
+ example: string;
+
+ /**
+ * Tell people where the bulk of your library is. Nothing special
+ * is done with the lib folder in any way, but it's useful meta info.
+ */
+ lib : string;
+
+ /**
+ * A folder that is full of man pages. Sugar to generate a 'man' array by walking the folder.
+ */
+ man : string;
+
+ /**
+ * Test folder
+ */
+ test : string
+ };
+
+ /**
+ * Specify the place where your code lives. This is helpful for people who want to contribute.
+ */
+ export var repository : {
+ type : string;
+ url : string;
+ };
+
+ /**
+ * The 'scripts' member is an object hash of script commands that are run at various times in
+ * the lifecycle of your package. The key is the lifecycle event, and the value is
+ * the command to run at that point.
+ */
+ export var scripts : {}
+
+ /**
+ * A 'config' hash can be used to set configuration parameters used in
+ * package scripts that persist across upgrades.
+ */
+ export var config : {};
+
+ /**
+ * Dependencies are specified with a simple hash of package name to version range.
+ * The version range is a string which has one or more space-separated descriptors.
+ * Dependencies can also be identified with a tarball or git URL.
+ */
+ export var dependencies : {};
+ export var devDependencies : {};
+ export var optionalDependencies : {};
+ export var peerDependencies : {};
+
+ /**
+ * Array of package names that will be bundled when publishing the package.
+ */
+ export var bundleDependencies : string[];
+
+ export var engines : {};
+ export var engineStrict : boolean;
+ export var os : string[];
+ export var cpu : string[];
+
+ /**
+ * If your package is primarily a command-line application
+ * that should be installed globally, then set this value to
+ * true to provide a warning if it is installed locally.
+ */
+ export var preferGlobal : boolean;
+
+ /**
+ * If set to true, then npm will refuse to publish it.
+ */
+ export var private : boolean;
+
+ export var publishConfig : {};
+
+ export var dist : {
+ shasum : string;
+ tarball : string;
+ };
+
+ export var readme : string;
+}
diff --git a/packages/maniajs-dedimania/typings/custom/pjson/typings.json b/packages/maniajs-dedimania/typings/custom/pjson/typings.json
new file mode 100644
index 0000000..c8a5d59
--- /dev/null
+++ b/packages/maniajs-dedimania/typings/custom/pjson/typings.json
@@ -0,0 +1,4 @@
+{
+ "name": "pjson",
+ "main": "index.d.ts"
+}
diff --git a/packages/maniajs-jukebox/package.json b/packages/maniajs-jukebox/package.json
index bf3d09e..cb25a34 100644
--- a/packages/maniajs-jukebox/package.json
+++ b/packages/maniajs-jukebox/package.json
@@ -20,7 +20,7 @@
"node": ">=4.0.0"
},
"dependencies": {
- "async": "^1.5.2",
- "@maniajs/plugin": "0.*"
+ "@maniajs/plugin": "0.*",
+ "async": "^2.0.1"
}
}
diff --git a/packages/maniajs-jukebox/src/maplist.js b/packages/maniajs-jukebox/src/maplist.js
index 8f7d0ca..db645eb 100644
--- a/packages/maniajs-jukebox/src/maplist.js
+++ b/packages/maniajs-jukebox/src/maplist.js
@@ -16,7 +16,7 @@ module.exports.default = class Maplist {
{
name: 'Name',
field: 'name',
- width: 120,
+ width: 100,
level: 0,
sort: true,
event: 'jukebox'
@@ -24,12 +24,191 @@ module.exports.default = class Maplist {
{
name: 'Author',
field: 'author',
- width: 40,
+ width: 30,
level: 0,
sort: true,
event: 'searchAuthor'
}
];
+
+ if(!params.length) {
+ this.displayGeneral(player, cols);
+ } else {
+ let command = params.shift();
+ switch(command) {
+ case 'help':
+ return this.plugin.server.send().chat('$fffUsage: /list [$eee, karma <+, -, #>, records, personal, nofinish, best, worst$fff]', {destination: player.login}).exec();
+ break;
+ case 'karma':
+ let karma = params.shift();
+ this.displayByKarma(player, cols, karma);
+ break;
+ case 'personal':
+ this.displayWithPersonalRecord(player, cols, 'personal');
+ break;
+ case 'nofinish':
+ this.displayWithPersonalRecord(player, cols, 'nofinish');
+ break;
+ case 'best':
+ this.displayWithPersonalRecord(player, cols, 'best');
+ break;
+ case 'worst':
+ this.displayWithPersonalRecord(player, cols, 'worst');
+ break;
+ case 'records':
+ this.displayWithRecord(player, cols);
+ break;
+ default:
+ this.displayByAuthor(player, cols, command);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Display general list (name, author, karma).
+ * @param {Player} player
+ * @param cols
+ */
+ displayGeneral(player, cols) {
+ var data = [];
+ Object.keys(this.plugin.maps.list).forEach((uid) => {
+ let map = this.plugin.maps.list[uid];
+ data.push({
+ uid: map.uid,
+ name: map.name,
+ author: map.author
+ });
+ });
+
+ this.displayIncludeKarma(data).then((result) => {
+ cols.push({
+ name: 'Karma',
+ field: 'karma',
+ width: 20,
+ level: 0,
+ sort: true
+ });
+
+ this.displayList('Maps on the server', player, cols, result);
+ });
+ }
+
+ /**
+ * Display general list (name, author, karma) for maps by author.
+ * @param {Player} player
+ * @param cols
+ * @param author
+ */
+ displayByAuthor(player, cols, author) {
+ var data = [];
+ Object.keys(this.plugin.maps.list).forEach((uid) => {
+ let map = this.plugin.maps.list[uid];
+ if(map.author.indexOf(author) > -1) {
+ data.push({
+ uid: map.uid,
+ name: map.name,
+ author: map.author
+ });
+ }
+ });
+
+ this.displayIncludeKarma(data).then((result) => {
+ cols.push({
+ name: 'Karma',
+ field: 'karma',
+ width: 20,
+ level: 0,
+ sort: true
+ });
+
+ this.displayList('Maps on the server by ' + author, player, cols, result);
+ });
+ }
+
+ /**
+ * Display general list (name, author, karma) by karma.
+ * @param {Player} player
+ * @param cols
+ * @param karma
+ */
+ displayByKarma(player, cols, karma) {
+ var data = [];
+ Object.keys(this.plugin.maps.list).forEach((uid) => {
+ let map = this.plugin.maps.list[uid];
+ data.push({
+ uid: map.uid,
+ name: map.name,
+ author: map.author
+ });
+ });
+
+ this.displayIncludeKarma(data).then((result) => {
+ cols.push({
+ name: 'Karma',
+ field: 'karma',
+ width: 20,
+ level: 0,
+ sort: true
+ });
+
+ let titleAddition;
+
+ if(karma == undefined || karma == '+' || karma == '++') {
+ data = result.sort((a, b) => b.karma - a.karma);
+ titleAddition = 'ordered by karma (DESC)';
+ } else if(karma == '-' || karma == '--') {
+ data = result.sort((a, b) => a.karma - b.karma);
+ titleAddition = 'ordered by karma (ASC)';
+ } else if(karma < 0) {
+ data = result.filter((a) => a.karma <= karma);
+ data = data.sort((a, b) => a.karma - b.karma);
+ titleAddition = 'with karma <= ' + karma;
+ } else if(karma >= 0) {
+ data = result.filter((a) => a.karma >= karma);
+ data = data.sort((a, b) => b.karma - a.karma);
+ titleAddition = 'with karma >= ' + karma;
+ }
+
+ this.displayList('Maps on the server ' + titleAddition, player, cols, data);
+ });
+ }
+
+ /**
+ * Display list with local record (name, author, record) for all maps.
+ * @param {Player} player
+ * @param cols
+ */
+ displayWithRecord(player, cols) {
+ var data = [];
+ Object.keys(this.plugin.maps.list).forEach((uid) => {
+ let map = this.plugin.maps.list[uid];
+ data.push({
+ uid: map.uid,
+ name: map.name,
+ author: map.author
+ });
+ });
+
+ this.displayIncludeRecord(data).then((result) => {
+ cols.push({
+ name: 'Record',
+ field: 'record',
+ width: 50,
+ level: 0,
+ sort: true
+ });
+
+ this.displayList('Maps on the server with local record', player, cols, result);
+ });
+ }
+
+ /**
+ * Display list with personal record (name, author, record) for all maps.
+ * @param {Player} player
+ * @param cols
+ */
+ displayWithPersonalRecord(player, cols, command) {
var data = [];
Object.keys(this.plugin.maps.list).forEach((uid) => {
let map = this.plugin.maps.list[uid];
@@ -40,7 +219,131 @@ module.exports.default = class Maplist {
});
});
- let list = this.app.ui.list('Maps on the server', player.login, cols, data);
+ this.displayIncludePersonalRecord(data, player).then((result) => {
+ let title;
+ if(command == 'nofinish') {
+ data = result.filter((a) => a.personalrecord == 'none');
+ title = 'Maps on the server with no personal time';
+ } else {
+ cols.push({
+ name: 'Personal Record',
+ field: 'personalrecord',
+ width: 50,
+ level: 0,
+ sort: true
+ });
+
+ data = result.filter((a) => a.personalrecord != 'none');
+
+ if(command == 'personal') {
+ title = 'Maps on the server with personal record';
+ } else if(command == 'best') {
+ data = data.sort((a, b) => {
+ if(a.personalrank != null && b.personalrank != null)
+ return a.personalrank - b.personalrank;
+ if(a.personalrank == null)
+ return 1;
+ if(b.personalrank == null)
+ return -1;
+ });
+ title = 'Maps on the server with personal record (best)';
+ } else if(command == 'worst') {
+ data = data.sort((a, b) => {
+ if(a.personalrank != null && b.personalrank != null)
+ return b.personalrank - a.personalrank;
+ if(b.personalrank == null)
+ return 1;
+ if(a.personalrank == null)
+ return -1;
+ });
+ title = 'Maps on the server with personal record (worst)';
+ }
+ }
+
+ this.displayList(title, player, cols, data);
+ });
+ }
+
+ /**
+ * Add karma to the list.
+ * @param data
+ *
+ * returns {Promise}
+ */
+ displayIncludeKarma(data) {
+ if(this.app.plugins.hasOwnProperty('@maniajs/plugin-karma')) {
+ let mapper = (map) => {
+ return this.app.plugins['@maniajs/plugin-karma'].getMapKarma(this.plugin.maps.list[map.uid]).then((karma) => {
+ map.karma = karma;
+ return map;
+ });
+ };
+
+ return Promise.all(data.map(mapper));
+ } else {
+ return Promise.resolve(data);
+ }
+ }
+
+ /**
+ * Add local record to the list.
+ * @param data
+ *
+ * returns {Promise}
+ */
+ displayIncludeRecord(data) {
+ if(this.app.plugins.hasOwnProperty('@maniajs/plugin-localrecords')) {
+ let mapper = (map) => {
+ return this.app.plugins['@maniajs/plugin-localrecords'].getMapRecord(this.plugin.maps.list[map.uid]).then((record) => {
+ map.record = (this.app.util.times.stringTime(record.score) + ' ($<' + record.Player.nickname + '$>)');
+ return map;
+ });
+ }
+
+ return Promise.all(data.map(mapper));
+ } else {
+ return Promise.resolve(data);
+ }
+ }
+
+ /**
+ * Add local record to the list.
+ * @param data
+ *
+ * returns {Promise}
+ */
+ displayIncludePersonalRecord(data, player) {
+ if(this.app.plugins.hasOwnProperty('@maniajs/plugin-localrecords')) {
+ let mapper = (map) => {
+ return this.app.plugins['@maniajs/plugin-localrecords'].getPersonalMapRecord(this.plugin.maps.list[map.uid], player).then((record) => {
+ map.personalrecord = this.app.util.times.stringTime(record.score);
+ map.personalrank = record.rank;
+
+ if(record.rank != null) {
+ map.personalrecord += ' (' + record.rank + ')';
+ }
+ return map;
+ }).catch(() => {
+ map.personalrecord = 'none';
+ return map;
+ });
+ }
+
+ return Promise.all(data.map(mapper));
+ } else {
+ return Promise.resolve(data);
+ }
+ }
+
+ /**
+ * Set ManiaLink and display on screen.
+ * @param title
+ * @param {Player} player
+ * @param cols
+ * @param data
+ */
+ displayList(title, player, cols, data) {
+ let list = this.app.ui.list(title, player.login, cols, data);
list.display();
list.on('jukebox', (map) => {
// Add to jukebox.
@@ -50,5 +353,10 @@ module.exports.default = class Maplist {
this.plugin.server.send().chat(`Error: ${err.message}`, {destination: player.login}).exec();
});
});
+
+ list.on('searchAuthor', (map) => {
+ // Display list for author.
+ this.display(player, [map.entry.author]);
+ });
}
};
diff --git a/packages/maniajs-jukebox/src/plugin.js b/packages/maniajs-jukebox/src/plugin.js
index f03f225..a696900 100644
--- a/packages/maniajs-jukebox/src/plugin.js
+++ b/packages/maniajs-jukebox/src/plugin.js
@@ -24,7 +24,7 @@ module.exports.default = class extends Plugin {
this.dependencies = [];
// Game Requirements
- this.game.games = ['trackmania']; // Only for trackmania
+ this.game.games = ['trackmania', 'shootmania'];
this.game.modes = [1, 2, 3, 4, 5]; // rounds,timeattack,team,laps,cup
}
@@ -48,17 +48,17 @@ module.exports.default = class extends Plugin {
// List command.
this.server.command.on('jukebox', 0, (playerObject, params) => {
- if (! params.length) {
+ if(!params.length) {
return this.server.send().chat('$fffUsage: /jukebox [$eeelist, clear$fff]', {destination: playerObject.login}).exec();
}
let player = this.players.list[playerObject.login];
- switch (params.shift()) {
+ switch(params.shift()) {
case 'list':
this.jukebox.list(player, params);
break;
case 'clear':
- if (playerObject.level > 2) {
+ if(playerObject.level > 2) {
this.jukebox.clear();
this.server.send().chat(`$c70$<$fff${playerObject.nickname}$>$c70 cleared the jukebox!`).exec();
} else {
diff --git a/packages/maniajs-karma/src/plugin.js b/packages/maniajs-karma/src/plugin.js
index 07eadc3..8fcc2f2 100644
--- a/packages/maniajs-karma/src/plugin.js
+++ b/packages/maniajs-karma/src/plugin.js
@@ -117,8 +117,13 @@ module.exports.default = class extends Plugin {
init() {
return new Promise((resolve, reject) => {
// Event
- this.server.on('map.begin',
- (params) => this.loadVotes(params));
+ this.server.on('map.begin', (params) => this.loadVotes(this.maps.current).then(() => {
+ Object.keys(this.players.list).forEach((login) => {
+ let player = this.players.list[login];
+ this.displayVotes(player);
+ this.displayKarmaWidget(player);
+ });
+ }));
this.server.on('player.connect', (params) => {
let player = this.players.list[params.login];
@@ -136,6 +141,7 @@ module.exports.default = class extends Plugin {
this.displayList(player);
});
+ this.server.command.on('karma', 0, (player, params) => this.displayVotes(player));
this.server.command.on('++', 0, (player, params) => this.votePositive(player, false));
this.server.command.on('--', 0, (player, params) => this.voteNegative(player, false));
this.server.on('player.chat', (params) => {
@@ -158,6 +164,12 @@ module.exports.default = class extends Plugin {
});
this.loadVotes(this.maps.current).then(() => {
+ Object.keys(this.players.list).forEach((login) => {
+ let player = this.players.list[login];
+ this.displayVotes(player);
+ this.displayKarmaWidget(player);
+ });
+
resolve();
}).catch((err) => {
reject(err);
@@ -166,7 +178,7 @@ module.exports.default = class extends Plugin {
}
/**
- * Function will display the map karma based on the current map (does not use map input).
+ * Load the karma votes for the map into the plugin.
*
* @param map
*
@@ -177,7 +189,7 @@ module.exports.default = class extends Plugin {
return this.models.Karma.findAll({
where: {
- MapId: this.maps.current.id
+ MapId: map.id
},
include: [Player]
}).then((votes) => {
@@ -192,12 +204,21 @@ module.exports.default = class extends Plugin {
this.minVotes++;
}
});
+ });
+ }
- Object.keys(this.players.list).forEach((login) => {
- let player = this.players.list[login];
- this.displayVotes(player);
- this.displayKarmaWidget(player);
- });
+ /**
+ * Returns the map karma for the requested map.
+ *
+ * @param map
+ *
+ * @returns {Promise}
+ */
+ getMapKarma(map) {
+ return this.models.Karma.sum('score', {
+ where: {
+ MapId: map.id
+ }
});
}
diff --git a/packages/maniajs-localrecords/package.json b/packages/maniajs-localrecords/package.json
index 458e220..e70b4cd 100644
--- a/packages/maniajs-localrecords/package.json
+++ b/packages/maniajs-localrecords/package.json
@@ -19,7 +19,7 @@
"node": ">=4.0.0"
},
"dependencies": {
- "async": "^1.5.2",
- "@maniajs/plugin": "0.*"
+ "@maniajs/plugin": "0.*",
+ "async": "^2.0.1"
}
}
diff --git a/packages/maniajs-localrecords/src/plugin.js b/packages/maniajs-localrecords/src/plugin.js
index 236ae4e..9eb05a9 100644
--- a/packages/maniajs-localrecords/src/plugin.js
+++ b/packages/maniajs-localrecords/src/plugin.js
@@ -25,7 +25,7 @@ module.exports.default = class extends Plugin {
// Game Requirements
this.game.games = ['trackmania']; // Only for trackmania
- this.game.modes = [1, 2, 3, 4, 5]; // rounds,timeattack,team,laps,cup
+ this.game.modes = [1, 2, 3, 5]; // rounds,timeattack,team,laps,cup
// Plugin properties
this.records = null;
@@ -77,6 +77,13 @@ module.exports.default = class extends Plugin {
}
};
+ this.setWidgetSettings();
+ }
+
+ /**
+ * Sets the widget settings property.
+ */
+ setWidgetSettings() {
this.widgetSettings = {
manialinkid: 'LocalRecords',
actionid: 'OpenLocalRecords',
@@ -219,6 +226,8 @@ module.exports.default = class extends Plugin {
if(this.config.hasOwnProperty('widgety') && this.config.widgety != '') {
this.widgetY = this.config.widgety;
}
+
+ this.setWidgetSettings();
}
/**
@@ -248,9 +257,13 @@ module.exports.default = class extends Plugin {
where: {
MapId: this.maps.current.id
},
+ order: [
+ ['score', 'ASC']
+ ],
+ limit: this.recordlimit,
include: [Player]
}).then((records) => {
- this.records = records.sort((a, b) => a.score - b.score);
+ this.records = records;
if(this.chatdisplay) {
var localRecords = '$39fLocal Records on $<$fff' + this.maps.current.name + '$>$39f';
@@ -285,6 +298,106 @@ module.exports.default = class extends Plugin {
});
}
+ /**
+ * Function will return the local record for map.
+ *
+ * @param map
+ *
+ * @returns {Promise}
+ */
+ getMapRecord(map) {
+ let Player = this.app.models.Player;
+
+ return this.models.LocalRecord.findOne({
+ where: {
+ MapId: map.id
+ },
+ order: [
+ ['score', 'ASC']
+ ],
+ include: [Player]
+ });
+ }
+
+ /**
+ * Function will return the personal record for map.
+ *
+ * @param map
+ * @param player
+ *
+ * @returns {Promise}
+ */
+ getPersonalMapRecord(map, player) {
+ let Player = this.app.models.Player;
+
+ return new Promise((resolve, reject) => {
+ this.models.LocalRecord.findOne({
+ where: {
+ MapId: map.id,
+ PlayerId: player.id
+ },
+ include: [Player]
+ }).then((data) => {
+ if(!data) return reject('No record');
+
+ this.models.LocalRecord.count({
+ where: {
+ MapId: data.MapId,
+ score: {
+ $lt: data.score
+ }
+ }
+ }).then((count) => {
+ if((count + 1) <= this.recordlimit) {
+ data.rank = (count + 1);
+ } else {
+ data.rank = null;
+ }
+
+ return resolve(data);
+ });
+ }).catch((error) => {
+ return reject(error);
+ });
+ });
+ }
+
+ /**
+ * Get last (so recordlimit, or higher if less records) local record for map.
+ *
+ * @param map
+ */
+ getLastMapRecord(map) {
+ let Player = this.app.models.Player;
+
+ return new Promise((resolve, reject) => {
+ this.models.LocalRecord.count({
+ where: {
+ MapId: map.id
+ }
+ }).then((count) => {
+ var limit = this.recordlimit;
+ if(count < this.recordlimit) {
+ limit = count;
+ }
+
+ this.models.LocalRecord.findOne({
+ where: {
+ MapId: map.id,
+ },
+ order: [
+ ['score', 'ASC']
+ ],
+ offset: (limit - 1),
+ include: [Player]
+ }).then((data) => {
+ data.rank = limit;
+ return resolve(data);
+ });
+ });
+ });
+ }
+
/**
* Displays the local record for the player.
*
diff --git a/packages/maniajs-mapwidget/src/plugin.js b/packages/maniajs-mapwidget/src/plugin.js
index 93f77f4..e8c1a26 100644
--- a/packages/maniajs-mapwidget/src/plugin.js
+++ b/packages/maniajs-mapwidget/src/plugin.js
@@ -165,7 +165,13 @@ module.exports.default = class extends Plugin {
mapPromise.then((map) => {
this.widgetSettings.mapname = map.Name;
this.widgetSettings.author = map.Author;
- this.widgetSettings.author_time = this.app.util.times.stringTime(map.AuthorTime);
+
+ if (this.app.config.config.server.game === 'shootmania') {
+ this.widgetSettings.author_time = '';
+ } else {
+ this.widgetSettings.author_time = this.app.util.times.stringTime(map.AuthorTime);
+ }
+
this.mapWidget.global(this.widgetSettings).update();
});
}
diff --git a/packages/maniajs-mapwidget/src/view/mapwidget.hbs b/packages/maniajs-mapwidget/src/view/mapwidget.hbs
index 7737b17..7ed6455 100644
--- a/packages/maniajs-mapwidget/src/view/mapwidget.hbs
+++ b/packages/maniajs-mapwidget/src/view/mapwidget.hbs
@@ -10,6 +10,9 @@
-
-
-
\ No newline at end of file
+
+ {{#if author_time}}
+
+
+ {{/if}}
+
diff --git a/packages/maniajs-plugin/package.json b/packages/maniajs-plugin/package.json
index bb63178..a454b75 100644
--- a/packages/maniajs-plugin/package.json
+++ b/packages/maniajs-plugin/package.json
@@ -1,6 +1,6 @@
{
"name": "@maniajs/plugin",
- "version": "0.1.0",
+ "version": "0.3.0",
"private": false,
"main": "src/plugin.js",
"description": "Plugin Interface for ManiaJS Plugin Structure",
diff --git a/packages/maniajs-plugin/src/plugin.js b/packages/maniajs-plugin/src/plugin.js
index 1848907..9be7b74 100644
--- a/packages/maniajs-plugin/src/plugin.js
+++ b/packages/maniajs-plugin/src/plugin.js
@@ -17,6 +17,7 @@ var EventEmitter = require('events').EventEmitter;
* @property {Maps} maps
* @property {{}} models
* @property {{}} config
+ * @property {{}} settings
* @property {UIFacade} ui
*
* @property {{modes: number[], game: string[]}} game
@@ -59,22 +60,23 @@ module.exports.default = class extends EventEmitter {
/**
* Inject Core App interface into the plugin.
*
- * @param {App} app App context.
- * @param {object} config Plugin config.
- * @param {Logger|{}} log Child Logger.
+ * @param {{}} props Injectable properties.
*/
- inject(app, config, log) {
- this.app = app;
- this.config = config;
- this.log = log;
+ inject(props) {
+ this.app = props.app;
+ this.config = props.config;
+ this.log = props.log;
- this.server = app.server;
+ this.server = props.app.server;
// Expand app into separate parts.
- this.players = app.players;
- this.maps = app.maps;
- this.plugins = app.plugins;
- this.ui = app.ui;
+ this.players = props.app.players;
+ this.maps = props.app.maps;
+ this.plugins = props.app.plugins;
+ this.ui = props.app.ui;
+ this.models = props.app.models[this.name] || {};
+
+ this.settings = props.settingStore || null;
}
};