diff --git a/.gitignore b/.gitignore
index ec670c9..453bac9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,18 +1,15 @@
-### Maven
-
-/target
-
-### IntelliJ
-
+### Intellij ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
## Directory-based project format
-.idea/
+.idea
+
+# CMake
+cmake-build-debug/
## File-based project format
*.iws
-*.iml
## Plugin-specific files:
@@ -25,6 +22,12 @@
# JIRA plugin
atlassian-ide-plugin.xml
+# Cursive Clojure plugin
+.idea/replstate.xml
+
+# Ruby plugin and RubyMine
+/.rakeTasks
+
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
@@ -32,102 +35,55 @@ crashlytics-build.properties
fabric.properties
-### Python ###
-# Byte-compiled / optimized / DLL files
-__pycache__/
-*.py[cod]
-*$py.class
-
-# C extensions
-*.so
-
-# Distribution / packaging
-.Python
-env/
-build/
-develop-eggs/
-dist/
-downloads/
-eggs/
-.eggs/
-lib/
-lib64/
-parts/
-sdist/
-var/
-wheels/
-*.egg-info/
-.installed.cfg
-*.egg
-
-# PyInstaller
-# Usually these files are written by a python script from a template
-# before PyInstaller builds the exe, so as to inject date/other infos into it.
-*.manifest
-*.spec
-
-# Installer logs
-pip-log.txt
-pip-delete-this-directory.txt
-
-# Unit test / coverage reports
-htmlcov/
-.tox/
-.coverage
-.coverage.*
-.cache
-nosetests.xml
-coverage.xml
-*,cover
-.hypothesis/
-
-# Translations
-*.mo
-*.pot
-
-# Django stuff:
-*.log
-local_settings.py
-
-# Flask stuff:
-instance/
-.webassets-cache
-
-# Scrapy stuff:
-.scrapy
-
-# Sphinx documentation
-docs/_build/
-
-# PyBuilder
-target/
-
-# Jupyter Notebook
-.ipynb_checkpoints
-
-# pyenv
-.python-version
-
-# celery beat schedule file
-celerybeat-schedule
-
-# SageMath parsed files
-*.sage.py
-
-# dotenv
-.env
-
-# virtualenv
-.venv
-venv/
-ENV/
-
-# Spyder project settings
-.spyderproject
-.spyproject
-
-# Rope project settings
-.ropeproject
-
-# mkdocs documentation
-/site
+### Intellij Patch ###
+# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
+
+# *.iml
+# modules.xml
+# .idea/misc.xml
+# *.ipr
+
+
+### Rust ###
+# Generated by Cargo
+# will have compiled files and executables
+/target/
+
+# These are backup files generated by rustfmt
+**/*.rs.bk
+
+
+### SublimeText ###
+# cache files for sublime text
+*.tmlanguage.cache
+*.tmPreferences.cache
+*.stTheme.cache
+
+# workspace files are user-specific
+*.sublime-workspace
+
+# project files should be checked into the repository, unless a significant
+# proportion of contributors will probably not be using SublimeText
+# *.sublime-project
+
+# sftp configuration file
+sftp-config.json
+
+# Package control specific files
+Package Control.last-run
+Package Control.ca-list
+Package Control.ca-bundle
+Package Control.system-ca-bundle
+Package Control.cache/
+Package Control.ca-certs/
+Package Control.merged-ca-bundle
+Package Control.user-ca-bundle
+oscrypto-ca-bundle.crt
+bh_unicode_properties.cache
+
+# Sublime-github package stores a github token in this file
+# https://packagecontrol.io/packages/sublime-github
+GitHub.sublime-settings
+
+
+# End of https://www.gitignore.io/api/rust,intellij,sublimetext
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644
index 0000000..a842230
--- /dev/null
+++ b/Cargo.lock
@@ -0,0 +1,201 @@
+[[package]]
+name = "backtrace"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "backtrace-sys"
+version = "0.1.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "cc"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "cfg-if"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "dtoa"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "failure"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "failure_derive"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "itoa"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "libc"
+version = "0.2.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "num-traits"
+version = "0.1.41"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "quote"
+version = "0.3.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "rustc-demangle"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "serde"
+version = "1.0.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "serde_derive"
+version = "1.0.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive_internals 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "serde_derive_internals"
+version = "0.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "syn"
+version = "0.11.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "synom"
+version = "0.11.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "synstructure"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "unicode-xid"
+version = "0.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "winapi"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi-i686-pc-windows-gnu 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-x86_64-pc-windows-gnu 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "zeps-core"
+version = "0.1.0"
+dependencies = [
+ "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[metadata]
+"checksum backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbbf59b1c43eefa8c3ede390fcc36820b4999f7914104015be25025e0d62af2"
+"checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661"
+"checksum cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a9b13a57efd6b30ecd6598ebdb302cca617930b5470647570468a65d12ef9719"
+"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
+"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
+"checksum failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "934799b6c1de475a012a02dab0ace1ace43789ee4b99bcfbf1a2e3e8ced5de82"
+"checksum failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c7cdda555bb90c9bb67a3b670a0f42de8e73f5981524123ad8578aafec8ddb8b"
+"checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c"
+"checksum libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)" = "96264e9b293e95d25bfcbbf8a88ffd1aedc85b754eba8b7d78012f638ba220eb"
+"checksum num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cacfcab5eb48250ee7d0c7896b51a2c5eec99c1feea5f32025635f5ae4b00070"
+"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
+"checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e"
+"checksum serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "db99f3919e20faa51bb2996057f5031d8685019b5a06139b1ce761da671b8526"
+"checksum serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "f4ba7591cfe93755e89eeecdbcc668885624829b020050e6aec99c2a03bd3fd0"
+"checksum serde_derive_internals 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6e03f1c9530c3fb0a0a5c9b826bdd9246a5921ae995d75f512ac917fc4dd55b5"
+"checksum serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c9db7266c7d63a4c4b7fe8719656ccdd51acf1bed6124b174f933b009fb10bcb"
+"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
+"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
+"checksum synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a761d12e6d8dcb4dcf952a7a89b475e3a9d69e4a69307e01a470977642914bd"
+"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
+"checksum winapi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b09fb3b6f248ea4cd42c9a65113a847d612e17505d6ebd1f7357ad68a8bf8693"
+"checksum winapi-i686-pc-windows-gnu 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ec6667f60c23eca65c561e63a13d81b44234c2e38a6b6c959025ee907ec614cc"
+"checksum winapi-x86_64-pc-windows-gnu 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "98f12c52b2630cd05d2c3ffd8e008f7f48252c042b4871c72aed9dc733b96668"
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..ff7ed66
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,19 @@
+[package]
+name = "zeps-core"
+version = "0.1.0"
+authors = ["The zDevelopers"]
+
+[dependencies]
+serde = "1.0.8"
+serde_json = "1.0.2"
+serde_derive = "1.0.8"
+failure = "0.1.1"
+failure_derive = "0.1.1"
+
+[lib]
+name = "zeps"
+path = "src/lib.rs"
+
+[[bin]]
+name = "zeps-core"
+path = "src/main.rs"
diff --git a/Jenkinsfile b/Jenkinsfile
index 1c4b033..a369834 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -1,13 +1,30 @@
pipeline {
- agent any
- stages {
- stage('Build') {
- agent any
- steps {
- checkout scm
- sh 'mvn clean install'
- archiveArtifacts(artifacts: '**/target/*.jar', fingerprint: true)
- }
+ agent {
+ docker 'rust:latest'
+ }
+ stages {
+ stage('Prepare') {
+ steps {
+ checkout scm;
+ }
+ }
+
+ stage('Clean') {
+ steps {
+ sh 'cargo clean'
+ }
+ }
+
+ stage('Build') {
+ steps {
+ sh 'cargo build'
+ }
+ }
+
+ stage('Test') {
+ steps {
+ sh 'cargo test'
+ }
+ }
}
- }
}
diff --git a/pom.xml b/pom.xml
deleted file mode 100644
index 8e4da39..0000000
--- a/pom.xml
+++ /dev/null
@@ -1,54 +0,0 @@
-
-
- 4.0.0
-
- me.cassayre.florian
- NetherRail
- 1.1-SNAPSHOT
-
-
-
- com.google.code.gson
- gson
- 2.3.1
-
-
-
-
-
-
- maven-assembly-plugin
-
-
-
- me.cassayre.florian.netherrail.Main
-
-
-
- jar-with-dependencies
-
-
-
-
- make-assembly
- package
-
- single
-
-
-
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
- 3.5.1
-
-
- 1.7
-
-
-
-
-
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
deleted file mode 100644
index 79fa3ea..0000000
--- a/requirements.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-appdirs==1.4.3
-click==6.7
-Flask==0.12.2
-itsdangerous==0.24
-Jinja2==2.9.6
-MarkupSafe==1.0
-packaging==16.8
-path.py==10.3.1
-pyparsing==2.2.0
-six==1.10.0
-Werkzeug==0.12.2
diff --git a/serve_api.py b/serve_api.py
deleted file mode 100644
index 3cf3a0d..0000000
--- a/serve_api.py
+++ /dev/null
@@ -1,54 +0,0 @@
-# Python 3.5+ required
-
-import json
-import os
-import sys
-import subprocess
-
-from flask import Flask, request, make_response, jsonify
-from path import Path
-
-app = Flask(__name__)
-
-if not 'ZEPS_CORE_JAR' in os.environ:
- print('Please specify ZePS-Core JAR with the ZEPS_CORE_JAR environment variable.', file=sys.stderr)
- sys.exit(1)
-
-zeps_core = Path(os.environ.get('ZEPS_CORE_JAR')).expand()
-
-if not zeps_core.exists():
- print('ZePS Core JAR not found. Check the ZEPS_CORE_JAR environment variable.', file=sys.stderr)
- sys.exit(1)
-
-def call_core(command, *args):
- process = subprocess.run(['java', '-jar', zeps_core, command, *[str(arg) for arg in args]], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- try:
- process.check_returncode()
- return make_response(process.stdout, 200, {'Content-Type': 'application/json'})
- except:
- return jsonify(error=str(process.stderr), exit_code=process.returncode)
-
-@app.route('/list')
-def list():
- return call_core('list')
-
-@app.route('/list/network')
-def list_with_network():
- return call_core('list', 'true')
-
-@app.route('/path//')
-def path(from_id, to_id):
- official = 'official' in request.args
- accessible = 'accessible' in request.args
- return call_core('pathfinder', from_id, to_id, official, accessible)
-
-@app.route('/colors')
-def colors():
- return call_core('colors')
-
-@app.route('/version')
-def version():
- return jsonify(
- version=zeps_core.namebase.replace('-jar-with-dependencies', ''),
- sha256=str(zeps_core.read_hexhash('sha256'))
- )
diff --git a/src/config.rs b/src/config.rs
new file mode 100644
index 0000000..3df06d0
--- /dev/null
+++ b/src/config.rs
@@ -0,0 +1,76 @@
+use std::collections::HashMap;
+use std::io::Read;
+
+use failure::Error;
+use failure::ResultExt;
+
+use serde_json;
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
+#[serde(untagged)]
+pub enum Coordinates {
+ Simple(i64,i64),
+ Complete(i64,i64,i64),
+}
+
+#[derive(Serialize, Deserialize, Debug)]
+#[serde(untagged)]
+pub enum LinePoint {
+ Simple(String),
+ WithMetadata {
+ station: String,
+ path_type: Option,
+ path_secure: Option,
+ path_to_next: Option>,
+ }
+}
+
+#[derive(Serialize, Deserialize, Debug)]
+pub struct Line {
+ pub name: String,
+ pub color: String,
+ pub path: Vec,
+}
+
+#[derive(Serialize, Deserialize, Debug)]
+pub struct Station {
+ pub name: String,
+ pub sub_name: String,
+ pub description: String,
+ pub coordinates: Coordinates,
+ pub real_coordinates: Option,
+
+ pub is_main: bool,
+ pub has_fast_access: bool,
+ pub fast_access_time: f64,
+ pub is_hidden: Option,
+}
+
+#[derive(Serialize, Deserialize, Debug)]
+pub struct Network {
+ pub name: String,
+ pub world: String,
+ pub is_nether: Option,
+ pub coordinates_factor: Option,
+ pub stations: HashMap,
+ pub lines: Vec,
+}
+
+#[derive(Serialize, Deserialize, Debug)]
+pub struct NetworkConnection {
+ pub networks: (String, String),
+ pub autoconnect_by_name: Option,
+ pub autoconnect_by_proximity: Option,
+ pub connections: Option>,
+}
+
+#[derive(Serialize, Deserialize, Debug)]
+pub struct Universe {
+ pub name: String,
+ pub networks: HashMap,
+ pub networks_connections: Vec,
+}
+
+pub fn read_universe(reader: R) -> Result {
+ Ok(serde_json::from_reader(reader).context("Unable to parse universe data")?)
+}
diff --git a/src/data/coordinates.rs b/src/data/coordinates.rs
new file mode 100644
index 0000000..2dc6151
--- /dev/null
+++ b/src/data/coordinates.rs
@@ -0,0 +1,66 @@
+
+#[derive(Copy, Clone, Default, Debug)]
+pub struct Coordinates {
+ x: i64,
+ y: i64,
+ z: i64
+}
+
+impl Coordinates {
+ pub fn new(x: i64, y: i64, z: i64) -> Coordinates {
+ Coordinates {
+ x,
+ y,
+ z,
+ }
+ }
+
+ pub fn new_2d(x: i64, z: i64) -> Coordinates {
+ Coordinates {
+ x,
+ y: 0,
+ z,
+ }
+ }
+
+ pub fn x(&self) -> i64 {
+ self.x
+ }
+
+ pub fn y(&self) -> i64 {
+ self.y
+ }
+
+ pub fn z(&self) -> i64 {
+ self.z
+ }
+
+ /// Calculates the distance between this point and another.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// # use zeps::data::Coordinates;
+ /// let c1 = Coordinates::new(0, 0, 0);
+ /// let c2 = Coordinates::new(3, 4, 0);
+ ///
+ /// assert_eq!(c1.distance(&c2), 5.0);
+ /// ```
+ pub fn distance(&self, other: &Coordinates) -> f64 {
+ let x = self.x - other.x;
+ let y = self.y - other.y;
+ let z = self.z - other.z;
+
+ ((x * x + y * y + z * z) as f64).sqrt()
+ }
+}
+
+
+impl From<::config::Coordinates> for Coordinates {
+ fn from(coord: ::config::Coordinates) -> Self {
+ match coord {
+ ::config::Coordinates::Simple(x, z) => Coordinates::new_2d(x, z),
+ ::config::Coordinates::Complete(x, y, z) => Coordinates::new(x, y, z),
+ }
+ }
+}
diff --git a/src/data/error.rs b/src/data/error.rs
new file mode 100644
index 0000000..570f2b2
--- /dev/null
+++ b/src/data/error.rs
@@ -0,0 +1,12 @@
+
+#[derive(Debug, Fail)]
+pub enum InvalidConfigurationError {
+ #[fail(display = "Network '{}' does not exist", name)]
+ NetworkNotFound { name: String },
+
+ #[fail(display= "Station '{}' does not exist", name)]
+ StationNotFound { name: String },
+
+ #[fail(display= "Path type '{}' is not recognized", name)]
+ InvalidPathType { name: String }
+}
diff --git a/src/data/line.rs b/src/data/line.rs
new file mode 100644
index 0000000..8a6c1e7
--- /dev/null
+++ b/src/data/line.rs
@@ -0,0 +1,100 @@
+use data::coordinates::Coordinates;
+use data::error::InvalidConfigurationError;
+use data::station::Station;
+
+use std::rc::Rc;
+use std::collections::HashMap;
+
+#[derive(Debug, Copy, Clone)]
+pub enum PathType {
+ Rail,
+ Walk
+}
+
+impl PathType {
+ fn from_config(path_type: Option) -> Result {
+ Ok(match path_type.as_ref().map(|s| &s[..]) {
+ Some("rail") => PathType::Rail,
+ Some("walk") => PathType::Walk,
+ Some(other) => Err(InvalidConfigurationError::InvalidPathType { name: other.to_string() })?,
+ None => PathType::Rail
+ })
+ }
+}
+
+#[derive(Debug, Clone)]
+pub struct LinePoint {
+ station: Rc,
+ path_type: PathType,
+ path_secure: bool,
+ path_to_next: Vec,
+}
+
+impl LinePoint {
+ pub fn station(&self) -> &Station {
+ &self.station
+ }
+
+ pub fn path_type(&self) -> PathType {
+ self.path_type
+ }
+
+ pub fn path_secure(&self) -> bool {
+ self.path_secure
+ }
+
+ pub fn path_to_next(&self) -> &[Coordinates] {
+ &self.path_to_next
+ }
+
+ pub fn from_config(line_point: ::config::LinePoint, stations: &HashMap>) -> Result {
+ Ok(match line_point {
+ ::config::LinePoint::Simple(station) => LinePoint {
+ station: stations.get(&station).cloned().ok_or(InvalidConfigurationError::StationNotFound { name: station })?,
+ path_type: PathType::Rail,
+ path_secure: true,
+ path_to_next: Vec::new(),
+ },
+ ::config::LinePoint::WithMetadata { station, path_type, path_secure, path_to_next } => LinePoint {
+ station: stations.get(&station).cloned().ok_or(InvalidConfigurationError::StationNotFound { name: station })?,
+ path_type: PathType::from_config(path_type)?,
+ path_secure: path_secure.unwrap_or(true),
+ path_to_next: match path_to_next {
+ Some(vec_coordinates) => vec_coordinates.into_iter().map(|c| c.into()).collect(),
+ None => Vec::new()
+ }
+ }
+ })
+ }
+}
+
+#[derive(Debug, Clone)]
+pub struct Line {
+ name: String,
+ color: String,
+ path: Vec,
+}
+
+impl Line {
+ pub fn name(&self) -> &str {
+ &self.name
+ }
+
+ pub fn color(&self) -> &str {
+ &self.color
+ }
+
+ pub fn path(&self) -> &[LinePoint] {
+ &self.path
+ }
+
+ pub fn from_config(line: ::config::Line, stations: &HashMap>) -> Result {
+ let path = line.path.into_iter().map(|p| LinePoint::from_config(p, stations)).collect::>()?;
+
+ Ok(Line {
+ name: line.name,
+ color: line.color,
+ path
+ })
+ }
+}
diff --git a/src/data/mod.rs b/src/data/mod.rs
new file mode 100644
index 0000000..128059a
--- /dev/null
+++ b/src/data/mod.rs
@@ -0,0 +1,13 @@
+
+pub mod coordinates;
+pub mod line;
+pub mod network;
+pub mod network_connection;
+pub mod station;
+pub mod universe;
+pub mod error;
+
+pub use self::coordinates::Coordinates;
+pub use self::network::Network;
+pub use self::universe::Universe;
+pub use self::station::Station;
diff --git a/src/data/network.rs b/src/data/network.rs
new file mode 100644
index 0000000..830bd8a
--- /dev/null
+++ b/src/data/network.rs
@@ -0,0 +1,69 @@
+use data::station::Station;
+use data::line::Line;
+use data::error::InvalidConfigurationError;
+
+use std::collections::HashMap;
+use std::collections::hash_map::Values;
+use std::rc::Rc;
+
+#[derive(Debug)]
+pub struct Network {
+ minecraft_world_name: String,
+ display_name: String,
+ coordinates_factor: f64,
+
+ stations: HashMap>,
+
+ lines: Vec
+}
+
+impl Network {
+ pub fn stations(&self) -> Stations {
+ Stations { iter: self.stations.values() }
+ }
+
+ pub fn station(&self, station_code: &String) -> Option> {
+ self.stations.get(station_code).cloned()
+ }
+
+ pub fn display_name(&self) -> &str {
+ &self.display_name
+ }
+
+ pub fn world_name(&self) -> &str {
+ &self.minecraft_world_name
+ }
+
+ pub fn coordinates_factor(&self) -> f64 {
+ self.coordinates_factor
+ }
+
+ pub fn from_config(network: ::config::Network) -> Result {
+ let stations = network.stations.into_iter().map(|(k, v)| (k, Rc::new(v.into()))).collect();
+ let lines = network.lines.into_iter().map(|l| Line::from_config(l, &stations)).collect::>()?;
+
+ Ok(Network {
+ minecraft_world_name: network.world,
+ display_name: network.name,
+
+ stations,
+ lines,
+
+ coordinates_factor: network.coordinates_factor
+ .or(network.is_nether.map(|is_nether| if is_nether { 0.125 } else { 1.0 }))
+ .unwrap_or(1.0)
+ })
+ }
+}
+
+pub struct Stations<'a> {
+ iter: Values<'a, String, Rc>
+}
+
+impl<'a> Iterator for Stations<'a> {
+ type Item = &'a Rc;
+
+ fn next(&mut self) -> Option {
+ self.iter.next()
+ }
+}
diff --git a/src/data/network_connection.rs b/src/data/network_connection.rs
new file mode 100644
index 0000000..84253f3
--- /dev/null
+++ b/src/data/network_connection.rs
@@ -0,0 +1,47 @@
+use std::collections::HashMap;
+use std::rc::Rc;
+
+use data::network::Network;
+use data::error::InvalidConfigurationError;
+
+#[derive(Debug)]
+pub struct NetworkConnection {
+ network_1: Rc,
+ network_2: Rc,
+ autoconnect_by_name: bool,
+ autoconnect_by_proximity: u64,
+ connections: Vec<(String,String)>,
+}
+
+impl NetworkConnection {
+ pub fn from_config(connection: ::config::NetworkConnection, networks_map: &HashMap>) -> Result {
+ let network_1 = networks_map.get(&connection.networks.0).cloned()
+ .ok_or(InvalidConfigurationError::NetworkNotFound {name: connection.networks.0})?;
+ let network_2 = networks_map.get(&connection.networks.1).cloned()
+ .ok_or(InvalidConfigurationError::NetworkNotFound {name: connection.networks.1})?;
+
+ let mut connections: Vec<(String,String)> = Vec::new();
+
+ if let Some(config_connections) = connection.connections {
+ for conn in config_connections {
+ // Checks if the references are valid
+ network_1.station(&conn.0).ok_or(InvalidConfigurationError::StationNotFound { name: conn.0.clone() })?;
+ network_2.station(&conn.1).ok_or(InvalidConfigurationError::StationNotFound { name: conn.1.clone() })?;
+
+ connections.push((conn.0.clone(), conn.1.clone()));
+ }
+ }
+
+ let connections = connections;
+
+ Ok(NetworkConnection {
+ network_1,
+ network_2,
+
+ autoconnect_by_name: connection.autoconnect_by_name.unwrap_or(false),
+ autoconnect_by_proximity: connection.autoconnect_by_proximity.unwrap_or(0),
+
+ connections
+ })
+ }
+}
diff --git a/src/data/station.rs b/src/data/station.rs
new file mode 100644
index 0000000..1298254
--- /dev/null
+++ b/src/data/station.rs
@@ -0,0 +1,30 @@
+use data::coordinates::Coordinates;
+
+#[derive(Debug)]
+pub struct Station {
+ name: String,
+ sub_name: String,
+ description: String,
+ coordinates: Coordinates,
+ real_coordinates: Coordinates,
+ is_main: bool,
+ has_fast_access: bool,
+ fast_access_time: f64,
+ is_hidden: bool,
+}
+
+impl From<::config::Station> for Station {
+ fn from(station: ::config::Station) -> Station {
+ Station {
+ name: station.name,
+ sub_name: station.sub_name,
+ description: station.description,
+ coordinates: station.coordinates.clone().into(),
+ real_coordinates: station.real_coordinates.unwrap_or(station.coordinates).into(),
+ is_main: station.is_main,
+ has_fast_access: station.has_fast_access,
+ fast_access_time: station.fast_access_time,
+ is_hidden: station.is_hidden.unwrap_or(false)
+ }
+ }
+}
diff --git a/src/data/universe.rs b/src/data/universe.rs
new file mode 100644
index 0000000..b57ca94
--- /dev/null
+++ b/src/data/universe.rs
@@ -0,0 +1,85 @@
+use std::collections::HashMap;
+use std::collections::hash_map::Values;
+use std::rc::Rc;
+
+use data::station::Station;
+use data::network::Network;
+use data::network_connection::NetworkConnection;
+use data::error::InvalidConfigurationError;
+
+pub struct Universe {
+ display_name: String,
+ networks: HashMap>,
+ network_connections: Vec,
+}
+
+impl Universe {
+ pub fn stations(&self) -> Stations {
+ Stations {
+ iter: self.networks.values(),
+ inner_iter: None,
+ }
+ }
+
+ pub fn display_name(&self) -> &str {
+ &self.display_name
+ }
+
+ pub fn get_network(&self, connection_name: &str) -> Option<&Network> {
+ self.networks.get(connection_name).map(|x| x.as_ref())
+ }
+
+ pub fn get_network_handle(&self, connection_name: &str) -> Option> {
+ self.networks.get(connection_name).cloned()
+ }
+
+ pub fn get_connections(&self) -> &[NetworkConnection] {
+ &self.network_connections
+ }
+
+ pub fn from_config(universe: ::config::Universe) -> Result {
+ let mut networks: HashMap> = HashMap::new();
+
+ for network in universe.networks.into_iter().map(|(k, v)| (k, Network::from_config(v))) {
+ match network.1 {
+ Ok(n) => networks.insert(network.0, Rc::new(n)),
+ Err(e) => return Err(e)
+ };
+ }
+
+ let networks = networks;
+
+ let network_connections = universe.networks_connections.into_iter()
+ .map(|c| NetworkConnection::from_config(c, &networks)).collect::>()?;
+
+ Ok(Universe {
+ display_name: universe.name,
+ networks,
+ network_connections,
+ })
+
+ }
+}
+
+pub struct Stations<'a> {
+ iter: Values<'a, String, Rc>,
+ inner_iter: Option<::data::network::Stations<'a>>,
+}
+
+impl<'a> Iterator for Stations<'a> {
+ type Item = &'a Rc;
+
+ fn next(&mut self) -> Option {
+ loop {
+ if let Some(ref mut inner) = self.inner_iter {
+ if let Some(x) = inner.by_ref().next() {
+ return Some(x)
+ }
+ }
+ match self.iter.next().map(|x| x.as_ref()).map(Network::stations) {
+ None => return None,
+ next => self.inner_iter = next,
+ }
+ }
+ }
+}
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..ea274f2
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,27 @@
+extern crate serde;
+extern crate serde_json;
+extern crate failure;
+
+#[macro_use] extern crate serde_derive;
+#[macro_use] extern crate failure_derive;
+
+pub mod config;
+pub mod data;
+
+pub use data::Universe;
+
+use std::fs::File;
+use std::io::Read;
+use std::path::Path;
+
+use failure::Error;
+use failure::ResultExt;
+
+pub fn read_universe(reader: R) -> Result {
+ Ok(Universe::from_config(config::read_universe(reader)?)?)
+}
+
+pub fn read_universe_from_file>(path: P) -> Result {
+ let file = File::open(&path).with_context(|_| format!("Unable to open universe data file '{}'", path.as_ref().to_string_lossy()))?;
+ Ok(read_universe(file).with_context(|_| format!("Unable to load universe data file '{}'", path.as_ref().to_string_lossy()))?)
+}
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..7488140
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,37 @@
+extern crate zeps;
+extern crate failure;
+
+use std::io::Write;
+use failure::Error;
+use zeps::data::universe::Universe;
+
+fn print_error(e: &Error) {
+ let seriously_dude = "Unable to write to standard error output (stderr)!";
+ let stderr = &mut ::std::io::stderr();
+ let mut stderr = stderr.lock();
+
+ writeln!(stderr, " [!] Error: {}", e).expect(seriously_dude);
+
+ for cause in e.causes().skip(1) {
+ writeln!(stderr, " | Cause: \t{}", cause).expect(seriously_dude);
+ }
+
+ if cfg!(debug_assertions) {
+ writeln!(stderr, "\n\n [?] Backtrace: {:#?}", e.backtrace()).expect(seriously_dude);
+ }
+}
+
+
+fn main() {
+ if let Err(ref e) = run() {
+ print_error(e);
+ ::std::process::exit(1);
+ }
+}
+
+fn run() -> Result<(), Error> {
+ let u: Universe = zeps::read_universe_from_file("./tests/fixtures/with_data.json")?;
+ let s: Vec<_> = u.stations().collect();
+ println!("Stations: {:#?}", s);
+ Ok(())
+}
diff --git a/src/main/java/me/cassayre/florian/netherrail/Direction.java b/src/main/java/me/cassayre/florian/netherrail/Direction.java
deleted file mode 100644
index e24ba88..0000000
--- a/src/main/java/me/cassayre/florian/netherrail/Direction.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package me.cassayre.florian.netherrail;
-
-/**
- * Represents a cardinal direction.
- */
-public enum Direction
-{
- NORTH(0, "Nord"),
- EAST(1, "Est"),
- SOUTH(2, "Sud"),
- WEST(3, "Ouest");
-
- private final int INDEX;
- private final String NAME;
-
- private Direction(final int index, final String name)
- {
- INDEX = index;
- NAME = name;
- }
-
- /**
- * Get the opposite side of this direction.
- * @return the opposite direction
- */
- public Direction opposite()
- {
- if(this == NORTH)
- return SOUTH;
- if(this == EAST)
- return WEST;
- if(this == SOUTH)
- return NORTH;
- if(this == WEST)
- return EAST;
-
- throw new IllegalStateException("No opposite found!");
- }
-
- /**
- * Get the index of this direction.
- * @return the index
- */
- public int getIndex()
- {
- return INDEX;
- }
-
- /**
- * Get the french name for this direction, begining with a capital.
- * @return the name of the direction
- */
- @Override
- public String toString()
- {
- return NAME;
- }
-}
diff --git a/src/main/java/me/cassayre/florian/netherrail/Main.java b/src/main/java/me/cassayre/florian/netherrail/Main.java
deleted file mode 100644
index 4a32631..0000000
--- a/src/main/java/me/cassayre/florian/netherrail/Main.java
+++ /dev/null
@@ -1,104 +0,0 @@
-package me.cassayre.florian.netherrail;
-
-import com.google.gson.JsonArray;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonPrimitive;
-
-public class Main
-{
-
- public static void main(String[] args)
- {
- final JsonObject error = new JsonObject();
-
- error.addProperty("time", 0);
- error.addProperty("result", "failed");
-
- // TODO Something cleaner here.
-
- try
- {
- switch (args[0].toLowerCase())
- {
- case "pathfinder":
- System.out.println(new PathFinder(Station.values()[Integer.parseInt(args[1])], Station.values()[Integer.parseInt(args[2])], args.length >= 4 ? Boolean.valueOf(args[3]) : true, args.length >= 5 ? Boolean.valueOf(args[4]) : true).find());
- return;
-
- case "list":
- boolean withNetwork = false;
-
- if (args.length >= 2)
- {
- withNetwork = Boolean.parseBoolean(args[1]);
- }
-
- final JsonObject listRoot = new JsonObject();
-
- listRoot.addProperty("result", "success");
- listRoot.addProperty("time", 0);
-
- listRoot.addProperty("withNetwork", withNetwork);
-
- final JsonArray stations = new JsonArray();
-
- for (Station station : Station.getStationsAlphabetically())
- {
- stations.add(station.toJson(withNetwork));
- }
-
- listRoot.add("stations", stations);
-
- System.out.print(listRoot);
- return;
-
- case "colors":
- System.out.println(NetworkAreas.toJson());
- return;
-
- case "map":
- MapCreator.saveMap(args.length > 2 ? args[2] : "netherrail_map.png", args.length > 1 ? Integer.parseInt(args[1]) : 2);
- return;
-
- default:
- throw new IllegalArgumentException(args[0]);
- }
- }
-
- // TODO Create a REAL error catcher.
-
- catch(ArrayIndexOutOfBoundsException ex)
- {
- error.add("cause", new JsonPrimitive("Not enough arguments."));
- }
- catch(NumberFormatException ex)
- {
- error.add("cause", new JsonPrimitive("Invalid station id."));
- }
- catch(PathImpossibleException ex)
- {
- error.add("cause", new JsonPrimitive("Path not found."));
- }
- catch(IllegalArgumentException ex)
- {
- error.add("cause", new JsonPrimitive("Invalid argument."));
- }
- catch(Exception ex)
- {
- error.add("cause", new JsonPrimitive("Unknown internal error."));
- }
-
- System.out.print(error);
- }
-
- /*
- (Ancien)
-
- Paramètres :
-
- - Chemin officiel OU non officiel
- - Chemins accessibles OU en travaux
- - Distance la plus courte OU trajet le plus rapide
- - Descente en cours de route OU descente à un arrêt officiel
-
- */
-}
diff --git a/src/main/java/me/cassayre/florian/netherrail/MapCreator.java b/src/main/java/me/cassayre/florian/netherrail/MapCreator.java
deleted file mode 100644
index 6a93641..0000000
--- a/src/main/java/me/cassayre/florian/netherrail/MapCreator.java
+++ /dev/null
@@ -1,107 +0,0 @@
-package me.cassayre.florian.netherrail;
-
-import javax.imageio.ImageIO;
-import java.awt.*;
-import java.awt.geom.AffineTransform;
-import java.awt.image.BufferedImage;
-import java.io.File;
-import java.io.IOException;
-
-public final class MapCreator
-{
- private MapCreator() {}
-
- private static int zoomLevel = 2;
-
- private static int toImageX(int mapX)
- {
- return (mapX + 837) / 2 * zoomLevel;
- }
-
- private static int toImageY(int mapY)
- {
- return (mapY + 1763) / 2 * zoomLevel;
- }
-
- /**
- * Creates a basic map rendering to help correcting indexation issues.
- * @param location the path to save the image
- * @throws IOException
- */
- public static void saveMap(String location, int zoomLevel) throws IOException
- {
- MapCreator.zoomLevel = zoomLevel;
-
- BufferedImage img = new BufferedImage(798 * zoomLevel, 1194 * zoomLevel, BufferedImage.TYPE_INT_ARGB);
-
- Graphics2D g = img.createGraphics();
-
- for(Station station : Station.values())
- {
- for(Direction direction : Direction.values())
- {
- Station connection = station.getSubStation(direction);
-
- if(connection == null)
- continue;
-
- PathType pathType = station.getPathType(direction);
-
- if(pathType == PathType.OFFICIAL_RAIL)
- g.setColor(new Color(157, 221, 255));
- else if(pathType == PathType.OFFICIAL_WALKING)
- g.setColor(new Color(57, 151, 147));
- else if(pathType == PathType.UNOFFICIAL_RAIL)
- g.setColor(new Color(82, 123, 248));
- else if(pathType == PathType.UNOFFICIAL_WALKING)
- g.setColor(new Color(136, 87, 255));
-
- g.setStroke(new BasicStroke(8, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
-
- g.drawLine(toImageX(station.getX()), toImageY(station.getY()), toImageX(connection.getX()), toImageY(connection.getY()));
- }
- }
-
-
- for(Station station : Station.values())
- {
- if (station.isIntersection())
- {
- g.setColor(Color.GREEN);
- if(station.isDangerous())
- g.setColor(new Color(41, 156, 27));
-
- if(!station.isVisible())
- g.setColor(new Color(206, 227, 194));
-
- g.fillOval(toImageX(station.getX()) - 10, toImageY(station.getY()) - 10, 20, 20);
- }
-
- if (station.isPortal()) g.setColor(new Color(159, 87, 209));
- if (station.isDangerous()) g.setColor(new Color(156, 69, 108));
-
- if (!station.isVisible()) g.setColor(new Color(227, 194, 226));
-
- g.fillOval(toImageX(station.getX()) - 8, toImageY(station.getY()) - 8, 16, 16);
-
- if (station.isVisible())
- {
- g.setColor(Color.DARK_GRAY);
-
- AffineTransform fontAT = new AffineTransform();
- fontAT.setToScale(2, 2);
- Font theFont = g.getFont();
- fontAT.rotate(-Math.PI / 4.0);
- Font theDerivedFont = theFont.deriveFont(fontAT);
- g.setFont(theDerivedFont);
-
- g.drawString(station.toString(), toImageX(station.getX() + 20), toImageY(station.getY()) - 20);
-
- g.setFont(theFont);
- }
-
- }
-
- ImageIO.write(img, "png", new File(location));
- }
-}
diff --git a/src/main/java/me/cassayre/florian/netherrail/NetworkAreas.java b/src/main/java/me/cassayre/florian/netherrail/NetworkAreas.java
deleted file mode 100644
index a862e8b..0000000
--- a/src/main/java/me/cassayre/florian/netherrail/NetworkAreas.java
+++ /dev/null
@@ -1,141 +0,0 @@
-package me.cassayre.florian.netherrail;
-
-import com.google.gson.JsonArray;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonPrimitive;
-
-import java.awt.Color;
-import java.util.*;
-
-public class NetworkAreas
-{
- private final static List areas = new ArrayList<>();
-
- static
- {
- registerX(new Color(255, 236, 39), -714);
- registerX(new Color(119, 98, 40), -570);
- registerX(new Color(255, 189, 206), -529);
- registerX(new Color(255, 122, 238), -485, 688);
- registerX(new Color(221, 72, 70), -378, -286, 425);
- registerX(new Color(94, 116, 255), -341);
- registerX(new Color(110, 244, 5), -414, -234);
- registerX(new Color(255, 116, 8), -251, -184);
- registerX(new Color(165, 178, 255), 30, 142, 148, 259);
- registerX(new Color(255, 170, 20), 294);
- registerX(new Color(64, 168, 186), 540);
-
- registerY(new Color(110, 176, 86), 539);
- registerY(new Color(255, 116, 8), 254);
- registerY(new Color(221, 72, 70), 47, 251);
- registerY(new Color(165, 178, 255), -84, -94, -120, -408);
- registerY(new Color(0, 0, 0), -260, -301, -342);
- registerY(new Color(255, 170, 20), -702);
- registerY(new Color(64, 168, 186), -780, -1160);
- registerY(new Color(255, 236, 39), -823);
- registerY(new Color(255, 189, 206), -853);
- registerY(new Color(165, 178, 255), -863);
- registerY(new Color(119, 98, 40), -1069);
- registerY(new Color(94, 116, 255), -1208);
- registerY(new Color(255, 122, 238), -1436);
- registerY(new Color(110, 244, 5), -1740);
- }
-
- public static void registerX(Color color, int... coordinates)
- {
- register(Area.Orientation.VERTICAL, color, coordinates);
- }
-
- public static void registerY(Color color, int... coordinates)
- {
- register(Area.Orientation.HORIZONTAL, color, coordinates);
- }
-
- private static void register(Area.Orientation orientation, Color color, int... coordinates)
- {
- if(orientation == null)
- throw new IllegalArgumentException("Orientation cannot be null.");
-
- if(color == null)
- throw new IllegalArgumentException("Color cannot be null.");
-
- areas.add(new Area(orientation, color, coordinates));
- }
-
- public static List getAreas(Area.Orientation orientation)
- {
- List list = new ArrayList<>();
-
- for(Area area : areas)
- {
- if(area.ORIENTATION == orientation)
- list.add(area);
- }
-
- return list;
- }
-
- public static JsonObject toJson()
- {
- JsonObject object = new JsonObject();
-
- JsonArray arrayX = new JsonArray();
- JsonArray arrayY = new JsonArray();
-
- for(Area area : areas)
- {
- JsonObject areaObject = new JsonObject();
-
- JsonArray array = new JsonArray();
-
- for(Integer value : area.COORDINATES)
- array.add(new JsonPrimitive(value));
-
- areaObject.add("coordinates", array);
-
- areaObject.add("color", colorToJson(area.COLOR));
-
- if(area.ORIENTATION == Area.Orientation.VERTICAL)
- arrayX.add(areaObject);
- else if(area.ORIENTATION == Area.Orientation.HORIZONTAL)
- arrayY.add(areaObject);
- }
-
- object.add("northsouth", arrayX);
-
- object.add("eastwest", arrayY);
-
- return object;
- }
-
- public static JsonObject colorToJson(Color color)
- {
- JsonObject object = new JsonObject();
-
- object.add("red", new JsonPrimitive(color.getRed()));
- object.add("green", new JsonPrimitive(color.getGreen()));
- object.add("blue", new JsonPrimitive(color.getBlue()));
-
- return object;
- }
-}
-
-class Area
-{
- public final Orientation ORIENTATION;
- public final int[] COORDINATES;
- public final Color COLOR;
-
- public Area(Orientation orientation, Color color, int... coordinates)
- {
- ORIENTATION = orientation;
- COORDINATES = coordinates;
- COLOR = color;
- }
-
- enum Orientation
- {
- VERTICAL,
- HORIZONTAL
- }
-}
diff --git a/src/main/java/me/cassayre/florian/netherrail/PathFinder.java b/src/main/java/me/cassayre/florian/netherrail/PathFinder.java
deleted file mode 100644
index 19f1fab..0000000
--- a/src/main/java/me/cassayre/florian/netherrail/PathFinder.java
+++ /dev/null
@@ -1,178 +0,0 @@
-package me.cassayre.florian.netherrail;
-
-import com.google.gson.JsonArray;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonPrimitive;
-
-import java.util.*;
-
-public class PathFinder
-{
- private final Station BEGIN, END;
- private final boolean LEGAL, ACCESSIBLE;
-
- private final Map weights = new HashMap();
- private final Map before = new HashMap();
- private final Set went = new HashSet();
-
- private final static double WALKING_SPEED = 1.35;
- private final static int DIRECTION_CHANGE_TIME = 15;
- private final static int INTERSECTION_TIME = 30;
-
- /**
- * Creates a new pathfinder object.
- * @param begin the station to begin at
- * @param end the station to go to
- * @param legal if official stations only should be used
- * @param accessible if safe stations only should be used
- */
- public PathFinder(Station begin, Station end, final boolean legal, final boolean accessible)
- {
- BEGIN = begin;
- END = end;
-
- LEGAL = legal;
- ACCESSIBLE = accessible;
- }
-
- /**
- * Finds the shorter path with the given parameters.
- * @return the path to follow
- * @throws PathImpossibleException if no path has been found
- */
- public JsonObject find() throws PathImpossibleException
- {
- long t1 = System.currentTimeMillis();
-
- weights.put(BEGIN, 0);
-
- for(Station minWeight = getMinWeight(); minWeight != END; minWeight = getMinWeight())
- {
- for(Direction direction : Direction.values())
- {
- if(minWeight == null)
- throw new PathImpossibleException("Cannot find a valid path for " + BEGIN + " to " + END);
-
- Station sub = minWeight.getSubStation(direction);
-
- if(sub == null)
- continue;
-
- if(went.contains(sub))
- continue;
-
-
- if((weights.get(sub) == null || weights.get(minWeight) + minWeight.getDistanceFrom(sub) < weights.get(sub)) && (!LEGAL || minWeight.getPathType(sub) == PathType.OFFICIAL_RAIL) && (!ACCESSIBLE || !sub.isDangerous()))
- {
-
- weights.put(sub, (int) (weights.get(minWeight) + minWeight.getDistanceFrom(sub)));
- before.put(sub, minWeight);
-
- if(minWeight.getPathType(sub) == PathType.UNOFFICIAL_WALKING)
- {
- weights.put(sub, (int) (weights.get(sub) * WALKING_SPEED));
- }
-
- Station ant = before.get(minWeight);
- if(ant != null)
- {
- Direction dir1 = ant.getDirection(minWeight);
- Direction dir2 = minWeight.getDirection(sub);
-
- if(dir1 != dir2)
- weights.put(sub, weights.get(sub) + DIRECTION_CHANGE_TIME);
- }
-
- if(sub.isIntersection())
- weights.put(sub, weights.get(sub) + INTERSECTION_TIME);
- }
-
- }
-
- went.add(minWeight);
- }
-
-
- final List path = createPath();
-
-
- JsonObject object = new JsonObject();
-
- long t2 = System.currentTimeMillis();
-
- object.add("result", new JsonPrimitive("success"));
-
- object.add("time", new JsonPrimitive(t2 - t1));
-
- object.add("begin", new JsonPrimitive(BEGIN.name().toLowerCase()));
-
- object.add("end", new JsonPrimitive(END.name().toLowerCase()));
-
- object.add("travel_time", new JsonPrimitive((int) Math.ceil(weights.get(END) / 7)));
-
-
- JsonArray array = new JsonArray();
-
- // Old stuff
- int distance = 0;
-
- for(int i = 0; i < path.size(); i++)
- {
- boolean hasNext = i < path.size() - 1;
-
- JsonObject objectStation = Station.buildStationPathObject(path.get(i), hasNext ? path.get(i + 1) : null);
-
- if(hasNext)
- distance += path.get(i).getDistanceFrom(path.get(i + 1));
-
- array.add(objectStation);
- }
-
- object.add("path", array);
-
- return object;
- }
-
- /**
- * Get the station with the lowest weight that has not been explored yet.
- * Can return null
if no station was found.
- * @return the station with the lowest weight
- */
- public Station getMinWeight()
- {
- Station min = null;
-
- for(Station station : weights.keySet())
- {
- if(!went.contains(station) && (min == null || weights.get(station) < weights.get(min)))
- {
- min = station;
- }
- }
-
- return min;
- }
-
- /**
- * Creates a list representing the path to follow.
- * @return a list of stations
- */
- public List createPath()
- {
- List path = new ArrayList();
-
- Station current = END;
-
- path.add(current);
-
- while(current != BEGIN)
- {
- current = before.get(current);
- path.add(current);
- }
-
- Collections.reverse(path);
-
- return path;
- }
-}
diff --git a/src/main/java/me/cassayre/florian/netherrail/PathImpossibleException.java b/src/main/java/me/cassayre/florian/netherrail/PathImpossibleException.java
deleted file mode 100644
index 9fb2196..0000000
--- a/src/main/java/me/cassayre/florian/netherrail/PathImpossibleException.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package me.cassayre.florian.netherrail;
-
-/**
- * This exception should be thrown when no valid path has been found.
- */
-public class PathImpossibleException extends Exception
-{
- public PathImpossibleException()
- {
- super();
- }
-
- public PathImpossibleException(String ex)
- {
- super(ex);
- }
-
- public PathImpossibleException(String ex, Throwable throwable)
- {
- super(ex, throwable);
- }
-}
diff --git a/src/main/java/me/cassayre/florian/netherrail/PathType.java b/src/main/java/me/cassayre/florian/netherrail/PathType.java
deleted file mode 100644
index 7b2f7b4..0000000
--- a/src/main/java/me/cassayre/florian/netherrail/PathType.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package me.cassayre.florian.netherrail;
-
-/**
- * Represents a path type between two stations.
- */
-public enum PathType
-{
- OFFICIAL_RAIL,
- OFFICIAL_WALKING,
- UNOFFICIAL_RAIL,
- UNOFFICIAL_WALKING;
-
- public boolean isRail()
- {
- return this == OFFICIAL_RAIL || this == UNOFFICIAL_RAIL;
- }
-
- public boolean isOfficial()
- {
- return this == OFFICIAL_RAIL || this == OFFICIAL_WALKING;
- }
-}
\ No newline at end of file
diff --git a/src/main/java/me/cassayre/florian/netherrail/Station.java b/src/main/java/me/cassayre/florian/netherrail/Station.java
deleted file mode 100644
index 6af58a7..0000000
--- a/src/main/java/me/cassayre/florian/netherrail/Station.java
+++ /dev/null
@@ -1,821 +0,0 @@
-package me.cassayre.florian.netherrail;
-
-import com.google.gson.JsonArray;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonPrimitive;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-
-/**
- * Represents an intersection, a portal or a point of interest.
- */
-public enum Station
-{
- NOUVEA(-714, -702, "Nouvéa", StationType.INTERSECTION_AND_PORTAL),
- ZIG_ZAG(-529, -702, "Zig Zag", StationType.INTERSECTION_ONLY),
- PEPINIERE_OUEST(-714, -582, "Pépinière Ouest", StationType.INTERSECTION_AND_PORTAL),
- FJORDS(-529, -823, "Fjords", StationType.INTERSECTION_ONLY),
- FLEURS(-714, -823, "Fleurs", StationType.INTERSECTION_ONLY),
- PEPINIERE_EST(-529, -582, "Pépinière Est", StationType.INTERSECTION_AND_PORTAL),
- PERE_DODUE(-714, -865, "Chez PèreDodue"),
- PKTEDDYB(-714, -895, "Chez PkTeddyB"),
- PINPINB(-714, -943, "Chez Pinpin'b"),
- CAMOUIL(-714, -1027, "Chez Camouil"),
- VERTICALE(-714, -1069, "Verticale des fous", StationType.INTERSECTION_ONLY),
- UZINE(-756, -1069, "UZine", StationType.INTERSECTION_AND_PORTAL),
- CARBONE(-570, -1069, "Carbone", StationType.INTERSECTION_ONLY),
- SIGICOAL_TITAN(-570, -1002, "Sigicoal Titan", StationType.INTERSECTION_AND_PORTAL),
- RESERVE(-341, -702, "Réserve de chasse", StationType.INTERSECTION_AND_PORTAL),
- PUMPKIN_VINES(-714, -1306, "Pumpkin Vines"),
- KRAVEN(-714, -1222, "Kraven", StationType.INTERSECTION_AND_PORTAL),
- MIDNIGHT_CITY(-714, -1200, "Midnight City"),
- CHESNATOWN(-714, -1351, "Chesnatown", StationType.INTERSECTION_AND_PORTAL),
- SEPTENTRION_OCCIDENTAL(-714, -1436, "Bout Septentrional du monde", StationType.INTERSECTION_ONLY),
- PIC_MARECAGE(-779, -1436, "Pic du marécage", StationType.INTERSECTION_AND_PORTAL),
- TARDIS(-800, -1435, "T.A.R.D.I.S", StationType.INTERSECTION_AND_PORTAL),
- TOUR_KIFEPEUR(-714, -1507, "La Tour Kifépeur", StationType.INTERSECTION_AND_PORTAL),
- VEKTOR(-714, -1585, "Chez Vektor", StationType.INTERSECTION_AND_PORTAL),
- PIERIRO_BILLGATESARDECHE(-714, -1633, "Chez Pieriro et BillGatesardeche", StationType.INTERSECTION_AND_PORTAL),
- HURLENEIGE(-540, -1436, "Hurleneige", StationType.INTERSECTION_AND_PORTAL),
- FROSTBORN_CANYON(-485, -1436, "Frostborn Canyon", StationType.INTERSECTION_ONLY),
- VOYAGE_ECLAIR(-485, -1675, "Voyage-Éclair (Sanctuary)", StationType.INTERSECTION_AND_PORTAL),
- GARDIENS(-413, -1436, "Chute de gardiens", StationType.INTERSECTION_AND_PORTAL),
- FORET_COUVERTE(-570, -1129, "Forêt couverte et Marais montagneux"),
- BASTION_DU_CACTUS_GIVRE(-714, -451, "Bastion du cactus givré"),
- MOINTAGNE(-714, -397, "Mointagne"),
- ISLA_NUBLAR(-529, -520, "Isla Nublar"),
- COLLINE_BOULEAUX(-485, -853, "Colline des bouleaux géants"),
- AEROPORT(-436, -853, "Aéroport"),
- SOURCE(-419, -853, "Source miraculeuse", StationType.INTERSECTION_AND_PORTAL),
- ELERIA(-341, -823, "Eléria", StationType.INTERSECTION_AND_PORTAL),
- SORCIERES(-341, -871, "Usine à sorcières"),
- ATLANTIS(-341, -913, "Atlantis", StationType.INTERSECTION_AND_PORTAL),
- ENGORIA(-341, -961, "Engoria"),
- DOGGO(-341, -1015, "République Souterraine Doggo"),
- BOREE(-234, -1436, "Borée", StationType.INTERSECTION_ONLY),
- KERSUB(-414, -1700, "Kersub", StationType.INTERSECTION_AND_PORTAL),
- GHAST(-341, -1069, "Ghast taquin", StationType.INTERSECTION_ONLY),
- MOREA(-473, -1069, "Îles de la Moréa"),
- PIC_ASSAUT(-234, -1069, "Pic Assaut", StationType.INTERSECTION_ONLY),
- ILE_FLEURS(-234, -1130, "Île aux fleurs"),
- WITHER(-234, -1232, "Lande du Wither", StationType.INTERSECTION_AND_PORTAL),
- CREVASSES(-234, -1315, "Croisée des crevasses"),
- LAC_AMOUREUX(-234, -1351, "Lac des amoureux"),
- SEPTENTRION(30, -1436, "Septentrion", StationType.INTERSECTION_AND_PORTAL),
- TENTACLES(206, -1436, "Tentaclès", StationType.INTERSECTION_AND_PORTAL),
- MESAPLAYA(30, -1278, "Mesaplaya", StationType.INTERSECTION_AND_PORTAL),
- RIVE_BLANCHE(30, -1207, "Rive Blanche", StationType.INTERSECTION_AND_PORTAL),
- FALAISIE(30, -1069, "Falaisie", StationType.INTERSECTION_ONLY),
- TUX(108, -1069, "Tux concursus", StationType.INTERSECTION_AND_PORTAL),
- PIC_MORIPLAY(195, -1069, "Pic Moriplay"),
- CHESLAND(275, -1069, "Chesland", StationType.INTERSECTION_AND_PORTAL),
- SAINT_KEHAINSYS(540, -1069, "Saint-Kéhainsys", StationType.INTERSECTION_ONLY),
- CHASSEUR(540, -1160, "Chasseur", StationType.INTERSECTION_ONLY),
- PLATYPUS(570, -1160, "Platypus", StationType.INTERSECTION_AND_PORTAL),
- WITHER_DESAFFECTE(430, -1160, "Wither desaffecté", StationType.INTERSECTION_AND_PORTAL),
- REFUGE_ARCTIQUE(540, -1248, "Refuge Arctique"),
- BASE_MILITAIRE_MEUDON(540, -1275, "Base militaire et château de Meudon"),
- MONTAGNE_SOLITAIRE(540, -1302, "Montagne solitaire"),
- POUTLARD(540, -1391, "Poutlard", StationType.INTERSECTION_AND_PORTAL),
- IVUJIVIK(540, -1363, "Ivujivik", StationType.PORTAL_ONLY),
- NORDET(540, -1436, "Nordet", StationType.INTERSECTION_ONLY),
- D_MONSTRATOR(688, -1677, "D-Monstrator", StationType.INTERSECTION_AND_PORTAL),
- INTERSECT_33(688, -1436, "Intersection", StationType.INTERSECTION_ONLY, true, false),
- CAPITALE_ADMINISTRATIVE_FEDERALE(638, -1436, "Capitale Administrative Fédérale", StationType.INTERSECTION_AND_PORTAL),
- GLACIER(-529, -342, "Glacier", StationType.INTERSECTION_AND_PORTAL),
- UNKNOWN_1(-714, -342, "Inconnue", StationType.INTERSECTION_ONLY, true, false),
- NOT_FINISHED_1(-529, -301, "En travaux", StationType.INTERSECTION_ONLY, false, true),
- NOT_FINISHED_2(-714, -301, "En travaux", StationType.INTERSECTION_ONLY, false, true),
- BIRDY(-714, -241, "Palais de Birdy"),
- CHEZ_SQUALL(-714, -103, "Chez Squall"),
- GRAND_OUEST(-714, 47, "Aiguillage du Grand Ouest", StationType.INTERSECTION_ONLY),
- AMAZONIA(-804, 47, "Amazonia", StationType.INTERSECTION_AND_PORTAL),
- VILLAGE_CORROMPU(-655, 47, "Village corrompu", StationType.INTERSECTION_AND_PORTAL),
- PERE_MORIEL(-621, 47, "Père Moriel", StationType.INTERSECTION_AND_PORTAL),
- SOMONITES(-529, 47, "Désert des Somonites", StationType.INTERSECTION_ONLY),
- FALLEN_KINGDOM(-714, 267, "Fallen Kingdom", StationType.INTERSECTION_AND_PORTAL),
- OCEAN_GAUCHE(-714, 539, "Océan du côté gauche", StationType.INTERSECTION_ONLY),
- NAILA(-804, 539, "Naila"),
- DEPOT(-529, 539, "Dépôt", StationType.INTERSECTION_ONLY),
- KERLAM(-529, 421, "Kerlam", StationType.INTERSECTION_AND_PORTAL),
- ALEXANDRIE(-529, 292, "Alexandrie", StationType.INTERSECTION_AND_PORTAL),
- GUET(-529, 598, "Tour de guet"),
- ACADEMIE(-219, -702, "Académie des Mages"),
- BLAZE_ROAD(-145, -702, "Blaze Road", StationType.INTERSECTION_ONLY),
- MER_ADIEUX(30, -702, "Mer des Adieux", StationType.INTERSECTION_ONLY),
- FERME_VILLAGEOIS(30, -829, "Ferme à Villageois", StationType.INTERSECTION_AND_PORTAL),
- POINT_CENTRAL(30, -863, "Point Central", StationType.INTERSECTION_AND_PORTAL),
- MONUMENT_DE_POINT_CENTRAL(-21, -863, "Monument de Point Central", StationType.INTERSECTION_AND_PORTAL),
- ARCHIPEL_TROPE(142,-863, "Archipel Trope", StationType.INTERSECTION_AND_PORTAL),
- PINK_TOWER(142,-907, "Pink Tower", StationType.INTERSECTION_AND_PORTAL),
- JONCTION(121, -702, "Jonction des continents"),
- MARAYA(294, -702, "Maraya Toumismo", StationType.INTERSECTION_ONLY),
- SPERANZA_PRISTINE(540, -702, "Speranza Pristine", StationType.INTERSECTION_ONLY),
- COL_AIGUES(540, -780, "Col Aigues", StationType.INTERSECTION_ONLY),
- AIGUES_CHAUDES(668, -780, "Aigues chaudes", StationType.INTERSECTION_AND_PORTAL),
- PICS_PRECIPICES(-234, -1183, "Pics et précipices"),
- VYNCIS(294, -661, "Vyncis", StationType.INTERSECTION_AND_PORTAL),
- TECI_TARZAN(294, -637, "La téci d'Tarzan"),
- CARTOUME(294, -604, "Cartoume", StationType.INTERSECTION_AND_PORTAL),
- VENICE(294, -529, "Venice", StationType.INTERSECTION_AND_PORTAL),
- PROJETZ(30, -613, "ProjetZ", StationType.INTERSECTION_AND_PORTAL),
- UNKNOWN_2(30, -408, "Inconnue", StationType.INTERSECTION_ONLY, true, false),
- VILLAGE_MAYA(30, -318, "Village Maya"),
- AIGUILLAGE_BAZAR(30, -301, "Aiguillage du Bazar bizarre", StationType.INTERSECTION_ONLY),
- BAZAR(-113, -301, "Bazar bizarre", StationType.INTERSECTION_AND_PORTAL),
- WALL_STREET(-144, -301, "Wall Street"),
- CONSTRUCTEURS(212, -408, "Constructeurs de l'extrême", StationType.INTERSECTION_AND_PORTAL),
- UNKNOWN_3(259, -408, "Inconnue", StationType.INTERSECTION_ONLY, true, false),
- UNKNOWN_4(259, -301, "Inconnue", StationType.INTERSECTION_ONLY, true, false),
- UNKNOWN_5(259, -260, "Inconnue", StationType.INTERSECTION_ONLY, true, false),
- ETHERNIA(259, -271, "Ethernia", StationType.INTERSECTION_AND_PORTAL),
- CART_TOON(540, -260, "Cart Toon", StationType.INTERSECTION_ONLY),
- SPERANZA(518, -702, "Sperenza"),
- ILE_PRISTINE(540, -672, "Île Pristine"),
- ORDOGRAD(540, -558, "Ordograd", StationType.PORTAL_ONLY),
- CENTRE_SPATIAL(540, -469, "Centre Spatial", StationType.PORTAL_ONLY),
- GOULAG(582, -260, "Goulag et Usine à fer", StationType.INTERSECTION_AND_PORTAL),
- HALDA(684, -260, "Halda", StationType.INTERSECTION_AND_PORTAL),
- TASSE(714, -260, "La tasse", StationType.INTERSECTION_AND_PORTAL),
- EURAZIE(259, 47, "EuraZie", StationType.INTERSECTION_ONLY),
- SECTEUR_GHASTS(295, 47, "Secteur Ghasts", StationType.INTERSECTION_ONLY),
- CLEM(425, 47, "Secteur Clem", StationType.INTERSECTION_ONLY),
- LAPUTA(425, 200, "Laputa", StationType.INTERSECTION_AND_PORTAL),
- MELBURNE(540, 47, "Melburne", StationType.INTERSECTION_ONLY),
- MACCRAGE(30, -202, "Secteur Maccrage", StationType.INTERSECTION_AND_PORTAL),
- BALADE(30, -146, "Balade", StationType.INTERSECTION_AND_PORTAL),
- UNKNOWN_7(30, -120, "Inconnue", StationType.INTERSECTION_ONLY, true, false),
- UNKNOWN_8(148, -120, "Inconnue", StationType.INTERSECTION_ONLY, true, false),
- ARENE_BLAZIQUE(148, -32, "Arène blazique"),
- FORTERESSE_LOUL(175, -120, "Forteresse de Sire Loul"),
- UNKNOWN_9(30, -94, "Inconnue", StationType.INTERSECTION_ONLY, true, false),
- UNKNOWN_10(148, -94, "Inconnue", StationType.INTERSECTION_ONLY, true, false),
- CITE_SCIENCES(190, -94, "Cité des sciences"),
- GRAND_TEMPLE(30, -84, "Grand temple de May"),
- COIN_NATURISTES(93, -84, "Le coin des naturistes"),
- CHEZ_Z(30, -65, "Chez Z"),
- VILLAGE_ELFIQUE(30, -54, "Village elfique"),
- FORTERESSE_2(30, -41, "Forteresse 2"),
- FLANGORIA(30, -24, "Flangoria"),
- ATTRACTION(30, -3, "Attractions"),
- UZINE_COCHON(30, 23, "UZine à cochons"),
- VAALON(30, 47, "Vaalon", StationType.INTERSECTION_AND_PORTAL),
- MOBY_DICK(89, 47, "New Libery & Moby Dick"),
- AGRISUB_1(132, 47, "Agrisub I", StationType.INTERSECTION_AND_PORTAL),
- UNKNOWN_11(148, 47, "Inconnue", StationType.INTERSECTION_ONLY, true, false),
- AZIE(221, 47, "Azie", StationType.INTERSECTION_AND_PORTAL),
- SILVERISLAND(276, 47, "Silverisland"),
- COLLINE_JAMBES(-46, 47, "La colline a des jambes"),
- GRANDE_LOTTERIE(-73, 47, "La grande lotterie"),
- FORTERESSE_1(-110, 47, "Forteresse 1"),
- OCTOPUSSY(-129, 47, "Octopussy", StationType.INTERSECTION_AND_PORTAL),
- AIGUILLAGE_CHATEAUNOIR(-251, 47, "Aiguillage Château Noir", StationType.INTERSECTION_ONLY),
- CARROUSEL_HOLERIBUS(-251, 254, "Carrousel Holeribus"),
- UNKNOWN_17(-184, 254, "Inconnue", StationType.INTERSECTION_ONLY, true, false),
- CHATEAU_NOIR(-184, 293, "Château Noir", StationType.INTERSECTION_AND_PORTAL),
- CHATEAU_GLACES(-242, 47, "Château des glaces"),
- ARRAKIS(-251, 65, "Arrakis"),
- PIXEL_ART(-286, 47, "Pixel Art", StationType.INTERSECTION_ONLY),
- MUSEE_PIXEL(-286, -93, "Musée du pixel art"),
- BANANEROSE(-361, 47, "Ville de bananerose"),
- CIUDAD(-378, 47, "Ciudad Esmeralda", StationType.INTERSECTION_AND_PORTAL),
- BLAZES_POINT(-378, -152, "Blazes point"),
- UNKNOWN_12(-341, -1208, "Inconnue", StationType.INTERSECTION_ONLY, true, false),
- USINE_OR(-527, -1208, "Usine à or et à XP"),
- POSEIDOPOLIS_EST(540, 251, "Poseidopolis Est", StationType.INTERSECTION_AND_PORTAL),
- POSEIDOPOLIS(450, 251, "Poseidopolis", StationType.INTERSECTION_AND_PORTAL),
- INTERSECT_34(425, 251, "Intersection", StationType.INTERSECTION_ONLY, true, false),
- ILE_PARADISIAQUE_BOBBIX(540, 366, "Île paradisiaque (Bobbix)", StationType.PORTAL_ONLY),
- SUDET(540, 539, "Sudet", StationType.INTERSECTION_ONLY, false, false),
- CARDINALE_EST(708, 539, "Cardinale Est", StationType.INTERSECTION_AND_PORTAL),
- SURET(540, 600, "Suret", StationType.INTERSECTION_AND_PORTAL),
- USINE_GARDIENS(426, 539, "Usine à gardiens", StationType.INTERSECTION_AND_PORTAL),
- FORTERESSE_MYSTERIEUSE(-132, 539, "Mystérieuse forteresse", StationType.INTERSECTION_AND_PORTAL),
- HASHTAG(-348, 539, "HashTag", StationType.INTERSECTION_AND_PORTAL),
- ILE_ZACQUES(-480, 539, "Île de Zâcques"),
- UNKNOWN_13(-529, -853, "Inconnue", StationType.INTERSECTION_ONLY, true, false),
- UNKNOWN_14(-234, -1740, "Inconnue", StationType.INTERSECTION_ONLY, true, false),
- UNKNOWN_15(-414, -1740, "Inconnue", StationType.INTERSECTION_ONLY, true, false),
- ILE_VOLCANIQUE(-714, 384, "Île volcanique"),
- FJORD_SUD(-529, -763, "Fjord Sud"),
- FJORD_CENTRAL(-529, -786, "Fjord Central"),
- FJORD_NORD(-529, -795, "Fjord Nord"),
- LAGON_DE_FLUM(-575, -823, "Lagon de Flum"),
- FORTERESSE_DES_FLEURS(-611, -823, "Forteresse des fleurs"),
- FLEURS_CREVASSES(-636, -823, "Des fleurs et des crevasses"),
- ISLA_SOMA(-529, -680, "Isla Soma"),
- CHEZ_CARANDOOM(-529, -564, "Chez Carandoom"),
- CHEZ_CANTIN(-529, -403, "Chez Cantin"),
- ISLA_PENA(-431, -702, "Isla Pena"),
- TENTACLES_PORT(158, -1436, "Port-Tentaclès", StationType.INTERSECTION_AND_PORTAL),
- NOT_FINISHED_4(30, -1682, "Station inconnue", StationType.INTERSECTION_AND_PORTAL), // Portail ne menant nulle part
- KAAMELOTT(-234, -1454, "Kaamelott"),
- POMMACROBATICS(-234, -1604, "PommAcrobatics", StationType.INTERSECTION_AND_PORTAL),
- CHEZ_NAGAIWA(-234, -1706, "Chez Nagaiwa"),
-
- // Old foot-based network (so-called « Netherroutes »)
-
- INTERSECT_18(30, 64, "Intersection", StationType.INTERSECTION_ONLY, true, false),
- ADELLIA(30, 76, "Adellia"),
- RAZIEL(30, 92, "Raziel"),
- INTERSECT_19(30, 112, "Intersection", StationType.INTERSECTION_ONLY, true, false),
- FORTERESSE_3(30, 128, "Forteresse 3"),
- ARBRE_BIBLIOTHEQUE(30, 152, "Arbre bibliothèque"),
- SIGICOAL(30, 189, "Sigicoal III"),
-
- MORZAN(-40, 64, "Morzan"),
- SMASTEN(-40, 98, "Smasten"),
- INTERSECT_21(-98, 64, "Intersection", StationType.INTERSECTION_ONLY, true, false),
- JUNGLE_PAUMEE(-98, 117, "Jungle paumée"),
-
- TAVERNE_BUNKER(22, 112, "Taverne Bunker"),
- INTERSECT_22(22, 140, "Intersection", StationType.INTERSECTION_ONLY, true, false),
- INTERSECT_23(55, 140, "Intersection", StationType.INTERSECTION_ONLY, true, false),
- ELEVAGE_DE_MEUH(155, 140, "Élevage de Meuh"),
- AMPHIPOLIS(55, 164, "Amphipolis"),
- REZERVE(55, 184, "RéZerve"),
- INTERSECT_26(55, 206, "Intersection", StationType.INTERSECTION_ONLY, true, false), //ok
- INTERSECT_27(108, 206, "Intersection", StationType.INTERSECTION_ONLY, true, false), //ok
- FOREST_OF_MAGIC_ISLAND(108, 296, "Forest of Magic Island"),
- ILE_PARADISIAQUE(108, 345, "Île paradisiaque"),
- INTERSECT_30(108, 460, "Intersection", StationType.INTERSECTION_ONLY, true, false),
- MONTAGNES_CREUSES(108, 481, "Montagnes creuses"),
- BAIE_HA_LONG(295, 460, "Baie d'Ha-Long", StationType.INTERSECTION_AND_PORTAL),
- MASTER_PWEL(343, 460, "Master Pwel"),
- STEP_31(295, 326, "Étape", StationType.INTERSECTION_ONLY, true, true),
- STEP_32(295, 304, "Étape", StationType.INTERSECTION_ONLY, true, true),
- FORT_BOYAUX(295, 133, "Fort Boyaux"),
- SANATORIUM_VERT(295, 61, "Sanatorium Vert"),
-
- KASTOU(221, 74, "Kastou"),
- SWAG_ISLAND(221, 186, "Swag island"),
-
- TOUR_INFERNALE(259, 164, "Tour Infernale")
-
- ;
-
- static
- {
- register(NOUVEA, FLEURS, ZIG_ZAG, PEPINIERE_OUEST, null); //
- register(ZIG_ZAG, FJORD_SUD, ISLA_PENA, ISLA_SOMA, NOUVEA); //
- register(PEPINIERE_OUEST, NOUVEA, null, BASTION_DU_CACTUS_GIVRE, null); //
- register(FJORDS, UNKNOWN_13, null, FJORD_NORD, LAGON_DE_FLUM); //
- register(LAGON_DE_FLUM, null, FJORDS, null, FORTERESSE_DES_FLEURS); //
- register(FORTERESSE_DES_FLEURS, null, LAGON_DE_FLUM, null, FLEURS_CREVASSES);
- register(FLEURS, PERE_DODUE, FLEURS_CREVASSES, NOUVEA, null); //
- register(PEPINIERE_EST, ISLA_SOMA, null, CHEZ_CARANDOOM, null); //
- register(PERE_DODUE, PKTEDDYB, null, FLEURS, null); //
- register(PKTEDDYB, PINPINB, null, PERE_DODUE, null); //
- register(PINPINB, CAMOUIL, null, PKTEDDYB, null); //
- register(CAMOUIL, VERTICALE, null, PINPINB, null); //
- register(VERTICALE, MIDNIGHT_CITY, CARBONE, CAMOUIL, UZINE); //
- register(UZINE, null, VERTICALE, null, null); //
- register(CARBONE, FORET_COUVERTE, MOREA, SIGICOAL_TITAN, VERTICALE); //
- register(SIGICOAL_TITAN, CARBONE, null, null, null); //
- register(RESERVE, ELERIA, ACADEMIE, null, ISLA_PENA);
- register(MIDNIGHT_CITY, KRAVEN, null, VERTICALE, null); //
- register(KRAVEN, PUMPKIN_VINES, null, MIDNIGHT_CITY, null); //
- register(PUMPKIN_VINES, CHESNATOWN, null, KRAVEN, null); //
- register(CHESNATOWN, SEPTENTRION_OCCIDENTAL, null, PUMPKIN_VINES, null); //
- register(SEPTENTRION_OCCIDENTAL, TOUR_KIFEPEUR, HURLENEIGE, CHESNATOWN, PIC_MARECAGE); //
- register(TOUR_KIFEPEUR, VEKTOR, null, SEPTENTRION_OCCIDENTAL, null);
- register(VEKTOR, PIERIRO_BILLGATESARDECHE, null, TOUR_KIFEPEUR, null);
- register(PIERIRO_BILLGATESARDECHE, null, null, VEKTOR, null);
- register(PIC_MARECAGE, null, SEPTENTRION_OCCIDENTAL, null, TARDIS); //
- register(TARDIS, null, PIC_MARECAGE, null, null); //
- register(HURLENEIGE, null, FROSTBORN_CANYON, null, SEPTENTRION_OCCIDENTAL); //
- register(FROSTBORN_CANYON, VOYAGE_ECLAIR, GARDIENS, null, HURLENEIGE); //
- register(VOYAGE_ECLAIR, null, null, FROSTBORN_CANYON, null); //
- register(GARDIENS, null, BOREE, null, FROSTBORN_CANYON); //
- register(FORET_COUVERTE, null, null, CARBONE, null); //
- register(BASTION_DU_CACTUS_GIVRE, PEPINIERE_OUEST, null, MOINTAGNE, null); //
- register(MOINTAGNE, BASTION_DU_CACTUS_GIVRE, null, UNKNOWN_1, null); //
- register(ISLA_NUBLAR, CHEZ_CARANDOOM, null, CHEZ_CANTIN, null); //
- register(COLLINE_BOULEAUX, null, AEROPORT, null, UNKNOWN_13); //
- register(AEROPORT, null, SOURCE, null, COLLINE_BOULEAUX); //
- register(SOURCE, null, null, null, AEROPORT); //
- register(ELERIA, SORCIERES, null, RESERVE, null); //
- register(SORCIERES, ATLANTIS, null, ELERIA, null); //
- register(ATLANTIS, ENGORIA, null, SORCIERES, null); //
- register(ENGORIA, DOGGO, null, ATLANTIS, null); //
- register(DOGGO, GHAST, null, ENGORIA, null); //
- register(BOREE, KAAMELOTT, SEPTENTRION, LAC_AMOUREUX, GARDIENS); //
- register(KAAMELOTT, POMMACROBATICS, null, BOREE, null); //
- register(POMMACROBATICS, CHEZ_NAGAIWA, null, KAAMELOTT, null); //
- register(CHEZ_NAGAIWA, UNKNOWN_14, null, POMMACROBATICS, null); //
- register(KERSUB, UNKNOWN_15, null, null, null); //
- register(GHAST, UNKNOWN_12, PIC_ASSAUT, DOGGO, MOREA);
- register(MOREA, null, GHAST, null, CARBONE); //
- register(PIC_ASSAUT, ILE_FLEURS, FALAISIE, null, GHAST);
- register(ILE_FLEURS, PICS_PRECIPICES, null, PIC_ASSAUT, null); //
- register(WITHER, CREVASSES, null, PICS_PRECIPICES, null); //
- register(CREVASSES, LAC_AMOUREUX, null, WITHER, null); //
- register(LAC_AMOUREUX, BOREE, null, CREVASSES, null); //
- register(SEPTENTRION, NOT_FINISHED_4, TENTACLES_PORT, MESAPLAYA, BOREE); //
- register(TENTACLES_PORT, null, TENTACLES, null, SEPTENTRION); //
- register(TENTACLES, null, NORDET, null, TENTACLES_PORT); //
- register(MESAPLAYA, SEPTENTRION, null, RIVE_BLANCHE, null); //
- register(RIVE_BLANCHE, MESAPLAYA, null, FALAISIE, null); //
- register(FALAISIE, RIVE_BLANCHE, TUX, POINT_CENTRAL, PIC_ASSAUT);
- register(TUX, null, PIC_MORIPLAY, null, FALAISIE); //
- register(PIC_MORIPLAY, null, CHESLAND, null, TUX); //
- register(CHESLAND, null, SAINT_KEHAINSYS, null, PIC_MORIPLAY); //
- register(SAINT_KEHAINSYS, CHASSEUR, null, COL_AIGUES, CHESLAND);
- register(CHASSEUR, REFUGE_ARCTIQUE, PLATYPUS, SAINT_KEHAINSYS, WITHER_DESAFFECTE); //
- register(WITHER_DESAFFECTE, null, CHASSEUR, null, null); //
- register(PLATYPUS, null, null, null, CHASSEUR); //
- register(REFUGE_ARCTIQUE, BASE_MILITAIRE_MEUDON, null, CHASSEUR, null); //
- register(BASE_MILITAIRE_MEUDON, MONTAGNE_SOLITAIRE, null, REFUGE_ARCTIQUE, null); //
- register(MONTAGNE_SOLITAIRE, IVUJIVIK, null, BASE_MILITAIRE_MEUDON, null); //
- register(IVUJIVIK, POUTLARD, null, MONTAGNE_SOLITAIRE, null); //
- register(POUTLARD, NORDET, null, IVUJIVIK, null); //
- register(NORDET, null, CAPITALE_ADMINISTRATIVE_FEDERALE, POUTLARD, TENTACLES);
- register(CAPITALE_ADMINISTRATIVE_FEDERALE, null, INTERSECT_33, null, NORDET);
- register(INTERSECT_33, D_MONSTRATOR, null, null, CAPITALE_ADMINISTRATIVE_FEDERALE);
- register(D_MONSTRATOR, null, null, INTERSECT_33, null);;
- register(GLACIER, new Station[] {CHEZ_CANTIN, null, NOT_FINISHED_1, UNKNOWN_1}, new PathType[] {PathType.OFFICIAL_RAIL, PathType.OFFICIAL_RAIL, PathType.OFFICIAL_RAIL, PathType.UNOFFICIAL_WALKING});
- register(UNKNOWN_1, new Station[] {MOINTAGNE, GLACIER, NOT_FINISHED_2, null}, new PathType[] {PathType.OFFICIAL_RAIL, PathType.UNOFFICIAL_WALKING, PathType.OFFICIAL_RAIL, PathType.OFFICIAL_RAIL});
- register(NOT_FINISHED_1, GLACIER, WALL_STREET, SOMONITES, NOT_FINISHED_2);
- register(NOT_FINISHED_2, UNKNOWN_1, NOT_FINISHED_1, BIRDY, null);
- register(BIRDY, NOT_FINISHED_2, null, CHEZ_SQUALL, null); //
- register(CHEZ_SQUALL, BIRDY, null, GRAND_OUEST, null);
- register(GRAND_OUEST, CHEZ_SQUALL, VILLAGE_CORROMPU, FALLEN_KINGDOM, AMAZONIA);
- register(AMAZONIA, null, GRAND_OUEST, null, null); //
- register(VILLAGE_CORROMPU, null, PERE_MORIEL, null, GRAND_OUEST); //
- register(PERE_MORIEL, null, SOMONITES, null, VILLAGE_CORROMPU); //
- register(SOMONITES, NOT_FINISHED_1, CIUDAD, ALEXANDRIE, PERE_MORIEL);
- register(FALLEN_KINGDOM, GRAND_OUEST, null, ILE_VOLCANIQUE, null); //
- register(OCEAN_GAUCHE, ILE_VOLCANIQUE, DEPOT, null, NAILA); //
- register(NAILA, null, OCEAN_GAUCHE, null, null); //
- register(DEPOT, KERLAM, ILE_ZACQUES, GUET, OCEAN_GAUCHE);
- register(KERLAM, ALEXANDRIE, null, DEPOT, null); //
- register(ALEXANDRIE, SOMONITES, null, KERLAM, null);
- register(ACADEMIE, null, BLAZE_ROAD, null, RESERVE);
- register(BLAZE_ROAD, null, MER_ADIEUX, null, ACADEMIE); //
- register(MER_ADIEUX, FERME_VILLAGEOIS, JONCTION, PROJETZ, BLAZE_ROAD); //
- register(FERME_VILLAGEOIS, POINT_CENTRAL, null, MER_ADIEUX, null); //
- register(POINT_CENTRAL, FALAISIE, ARCHIPEL_TROPE, FERME_VILLAGEOIS, MONUMENT_DE_POINT_CENTRAL); //
- register(MONUMENT_DE_POINT_CENTRAL, null, POINT_CENTRAL, null, null); //
- register(ARCHIPEL_TROPE, PINK_TOWER, null, null, POINT_CENTRAL); //
- register(PINK_TOWER, null, null, ARCHIPEL_TROPE, null); //
- register(GUET, DEPOT, null, null, null); //
- register(JONCTION, null, MARAYA, null, MER_ADIEUX); // ***
- register(MARAYA, null, SPERANZA, VYNCIS, JONCTION);
- register(SPERANZA_PRISTINE, COL_AIGUES, null, ILE_PRISTINE, SPERANZA);
- register(COL_AIGUES, SAINT_KEHAINSYS, AIGUES_CHAUDES, SPERANZA_PRISTINE, null);
- register(AIGUES_CHAUDES, null, null, null, COL_AIGUES);
- register(PICS_PRECIPICES, WITHER, null, ILE_FLEURS, null);
- register(VYNCIS, MARAYA, null, TECI_TARZAN, null);
- register(TECI_TARZAN, VYNCIS, null, CARTOUME, null);
- register(CARTOUME, TECI_TARZAN, null, VENICE, null);
- register(VENICE, CARTOUME, null, null, null);
- register(PROJETZ, MER_ADIEUX, null, UNKNOWN_2, null);
- register(UNKNOWN_2, new Station[] {PROJETZ, CONSTRUCTEURS, VILLAGE_MAYA, null}, new PathType[] {PathType.OFFICIAL_RAIL, PathType.OFFICIAL_WALKING, PathType.OFFICIAL_RAIL, PathType.OFFICIAL_RAIL});
- register(VILLAGE_MAYA, UNKNOWN_2, null, AIGUILLAGE_BAZAR, null);
- register(AIGUILLAGE_BAZAR, VILLAGE_MAYA, UNKNOWN_4, MACCRAGE, BAZAR);
- register(BAZAR, null, AIGUILLAGE_BAZAR, null, WALL_STREET);
- register(WALL_STREET, null, BAZAR, null, NOT_FINISHED_1);
- register(CONSTRUCTEURS, new Station[] {null, UNKNOWN_3, null, UNKNOWN_2}, new PathType[] {PathType.OFFICIAL_RAIL, PathType.OFFICIAL_RAIL, PathType.OFFICIAL_RAIL, PathType.OFFICIAL_WALKING});
- register(UNKNOWN_3, null, null, UNKNOWN_4, CONSTRUCTEURS);
- register(UNKNOWN_4, UNKNOWN_3, null, ETHERNIA, AIGUILLAGE_BAZAR);
- register(UNKNOWN_5, new Station[] {ETHERNIA, CART_TOON, EURAZIE, null}, new PathType[] {PathType.OFFICIAL_RAIL, PathType.OFFICIAL_RAIL, PathType.OFFICIAL_WALKING, PathType.OFFICIAL_RAIL});
- register(ETHERNIA, UNKNOWN_4, null, UNKNOWN_5, null);
- register(CART_TOON, CENTRE_SPATIAL, GOULAG, MELBURNE, UNKNOWN_5);
- register(CENTRE_SPATIAL, ORDOGRAD, null, CART_TOON, null);
- register(ORDOGRAD, ILE_PRISTINE, null, CENTRE_SPATIAL, null);
- register(SPERANZA, null, SPERANZA_PRISTINE, null, MARAYA);
- register(ILE_PRISTINE, SPERANZA_PRISTINE, null, ORDOGRAD, null);
- register(GOULAG, null, HALDA, null, CART_TOON);
- register(HALDA, null, TASSE, null, GOULAG);
- register(TASSE, null, null, null, HALDA);
- register(EURAZIE, new Station[] {UNKNOWN_5, SILVERISLAND, TOUR_INFERNALE, AZIE}, new PathType[] {PathType.OFFICIAL_WALKING, PathType.OFFICIAL_RAIL, PathType.OFFICIAL_WALKING, PathType.OFFICIAL_RAIL}); //
- register(SECTEUR_GHASTS, new Station[] {null, CLEM, SANATORIUM_VERT, SILVERISLAND}, new PathType[] {PathType.OFFICIAL_RAIL, PathType.OFFICIAL_RAIL, PathType.OFFICIAL_WALKING, PathType.OFFICIAL_RAIL});
- register(CLEM, new Station[] {null, MELBURNE, LAPUTA, SECTEUR_GHASTS}, new PathType[] {PathType.OFFICIAL_RAIL, PathType.OFFICIAL_RAIL, PathType.UNOFFICIAL_RAIL, PathType.OFFICIAL_RAIL});
- register(LAPUTA, new Station[] {CLEM, null, INTERSECT_34, null}, new PathType[] {PathType.UNOFFICIAL_RAIL, PathType.OFFICIAL_RAIL, PathType.UNOFFICIAL_RAIL, PathType.OFFICIAL_RAIL});
- register(INTERSECT_34, new Station[] {LAPUTA, POSEIDOPOLIS, null, null}, new PathType[] {PathType.UNOFFICIAL_RAIL, PathType.UNOFFICIAL_RAIL, PathType.OFFICIAL_RAIL, PathType.OFFICIAL_RAIL});
- register(POSEIDOPOLIS, new Station[] {null, POSEIDOPOLIS_EST, null, INTERSECT_34}, new PathType[] {PathType.OFFICIAL_RAIL, PathType.OFFICIAL_RAIL, PathType.OFFICIAL_RAIL, PathType.UNOFFICIAL_RAIL});
- register(MELBURNE, CART_TOON, null, POSEIDOPOLIS_EST, CLEM);
- register(MACCRAGE, AIGUILLAGE_BAZAR, null, BALADE, null);
- register(BALADE, MACCRAGE, null, UNKNOWN_7, null);
- register(UNKNOWN_7, BALADE, UNKNOWN_8, UNKNOWN_9, null);
- register(UNKNOWN_8, ARENE_BLAZIQUE, FORTERESSE_LOUL, UNKNOWN_10, UNKNOWN_7);
- register(ARENE_BLAZIQUE, null, null, UNKNOWN_8, null);
- register(FORTERESSE_LOUL, null, null, null, UNKNOWN_8);
- register(UNKNOWN_9, UNKNOWN_7, UNKNOWN_10, GRAND_TEMPLE, null);
- register(UNKNOWN_10, UNKNOWN_8, CITE_SCIENCES, null, UNKNOWN_9);
- register(CITE_SCIENCES, null, null, null, UNKNOWN_10);
- register(GRAND_TEMPLE, UNKNOWN_9, COIN_NATURISTES, CHEZ_Z, null);
- register(COIN_NATURISTES, null, null, null, GRAND_TEMPLE);
- register(CHEZ_Z, GRAND_TEMPLE, null, VILLAGE_ELFIQUE, null);
- register(VILLAGE_ELFIQUE, CHEZ_Z, null, FORTERESSE_2, null);
- register(FORTERESSE_2, VILLAGE_ELFIQUE, null, FLANGORIA, null);
- register(FLANGORIA, FORTERESSE_2, null, ATTRACTION, null);
- register(ATTRACTION, FLANGORIA, null, UZINE_COCHON, null);
- register(UZINE_COCHON, ATTRACTION, null, VAALON, null);
- register(VAALON, new Station[] {UZINE_COCHON, MOBY_DICK, INTERSECT_18, COLLINE_JAMBES}, new PathType[] {PathType.OFFICIAL_RAIL, PathType.OFFICIAL_RAIL, PathType.OFFICIAL_WALKING, PathType.OFFICIAL_RAIL});
- register(MOBY_DICK, null, AGRISUB_1, null, VAALON);
- register(AGRISUB_1, null, UNKNOWN_11, null, MOBY_DICK);
- register(UNKNOWN_11, null, AZIE, null, AGRISUB_1);
- register(AZIE, new Station[] {null, EURAZIE, KASTOU, UNKNOWN_11}, new PathType[]{PathType.OFFICIAL_RAIL, PathType.OFFICIAL_RAIL, PathType.OFFICIAL_WALKING, PathType.OFFICIAL_RAIL});
- register(SILVERISLAND, null, SECTEUR_GHASTS, null, EURAZIE);
- register(COLLINE_JAMBES, null, VAALON, null, GRANDE_LOTTERIE);
- register(GRANDE_LOTTERIE, null, COLLINE_JAMBES, null, FORTERESSE_1);
- register(FORTERESSE_1, null, GRANDE_LOTTERIE, null, OCTOPUSSY);
- register(OCTOPUSSY, null, FORTERESSE_1, null, CHATEAU_GLACES);
- register(AIGUILLAGE_CHATEAUNOIR, null, CHATEAU_GLACES, ARRAKIS, PIXEL_ART);
- register(CARROUSEL_HOLERIBUS, ARRAKIS, UNKNOWN_17, null, null);
- register(UNKNOWN_17, null, null, CHATEAU_NOIR, CARROUSEL_HOLERIBUS);
- register(CHATEAU_NOIR, UNKNOWN_17, null, null, null);
- register(CHATEAU_GLACES, null, OCTOPUSSY, null, AIGUILLAGE_CHATEAUNOIR);
- register(ARRAKIS, AIGUILLAGE_CHATEAUNOIR, null, CARROUSEL_HOLERIBUS, null);
- register(PIXEL_ART, MUSEE_PIXEL, AIGUILLAGE_CHATEAUNOIR, null, BANANEROSE);
- register(MUSEE_PIXEL, null, null, PIXEL_ART, null);
- register(BANANEROSE, null, PIXEL_ART, null, CIUDAD);
- register(CIUDAD, BLAZES_POINT, BANANEROSE, null, SOMONITES);
- register(BLAZES_POINT, null, null, CIUDAD, null);
- register(UNKNOWN_12, null, null, GHAST, USINE_OR);
- register(USINE_OR, null, UNKNOWN_12, null, null);
- register(POSEIDOPOLIS_EST, MELBURNE, null, ILE_PARADISIAQUE_BOBBIX, POSEIDOPOLIS);
- register(ILE_PARADISIAQUE_BOBBIX, POSEIDOPOLIS_EST, null, SUDET, null);
- register(SUDET, ILE_PARADISIAQUE_BOBBIX, CARDINALE_EST, SURET, USINE_GARDIENS);
- register(CARDINALE_EST, null, null, null, SUDET);
- register(SURET, SUDET, null, null, null);
- register(USINE_GARDIENS, null, SUDET, null, FORTERESSE_MYSTERIEUSE);
- register(FORTERESSE_MYSTERIEUSE, null, USINE_GARDIENS, null, HASHTAG);
- register(HASHTAG, null, FORTERESSE_MYSTERIEUSE, null, ILE_ZACQUES);
- register(ILE_ZACQUES, null, HASHTAG, null, DEPOT);
- register(UNKNOWN_13, null, COLLINE_BOULEAUX, FJORDS, null);
- register(UNKNOWN_14, null, null, CHEZ_NAGAIWA, UNKNOWN_15);
- register(UNKNOWN_15, null, UNKNOWN_14, KERSUB, null);
- register(ILE_VOLCANIQUE, FALLEN_KINGDOM, null, OCEAN_GAUCHE, null);
- register(FJORD_SUD, FJORD_CENTRAL, null, ZIG_ZAG, null);
- register(FJORD_CENTRAL, FJORD_NORD, null, FJORD_SUD, null);
- register(FJORD_NORD, FJORDS, null, FJORD_CENTRAL, null);
- register(FLEURS_CREVASSES, null, FORTERESSE_DES_FLEURS, null, FLEURS);
- register(ISLA_SOMA, ZIG_ZAG, null, PEPINIERE_EST, null);
- register(CHEZ_CARANDOOM, PEPINIERE_EST, null, ISLA_NUBLAR, null);
- register(CHEZ_CANTIN, ISLA_NUBLAR, null, GLACIER, null);
- register(ISLA_PENA, null, RESERVE, null, ZIG_ZAG);
- register(NOT_FINISHED_4, null, null, SEPTENTRION, null);
-
- // Old foot-based network (so-called « Netherroutes »)
-
- registerWalk(INTERSECT_18, VAALON, null, ADELLIA, MORZAN);
- registerWalk(ADELLIA, INTERSECT_18, null, RAZIEL, null);
- registerWalk(RAZIEL, ADELLIA, null, INTERSECT_19, null);
- registerWalk(INTERSECT_19, RAZIEL, null, FORTERESSE_3, TAVERNE_BUNKER);
- registerWalk(FORTERESSE_3, INTERSECT_19, null, ARBRE_BIBLIOTHEQUE, null);
- registerWalk(ARBRE_BIBLIOTHEQUE, FORTERESSE_3, null, SIGICOAL, null);
- registerWalk(SIGICOAL, ARBRE_BIBLIOTHEQUE, null, null, null);
-
- registerWalk(MORZAN, null, INTERSECT_18, SMASTEN, INTERSECT_21);
- registerWalk(SMASTEN, MORZAN, null, null, null);
- registerWalk(INTERSECT_21, null, MORZAN, JUNGLE_PAUMEE, null);
- registerWalk(JUNGLE_PAUMEE, INTERSECT_21, null, null, null);
-
- registerWalk(TAVERNE_BUNKER, null, INTERSECT_19, INTERSECT_22, null);
- registerWalk(INTERSECT_22, TAVERNE_BUNKER, INTERSECT_23, null, null);
- registerWalk(INTERSECT_23, null, ELEVAGE_DE_MEUH, AMPHIPOLIS, INTERSECT_22);
- registerWalk(ELEVAGE_DE_MEUH, null, null, null, INTERSECT_23);
- registerWalk(AMPHIPOLIS, INTERSECT_23, null, REZERVE, null);
- registerWalk(REZERVE, AMPHIPOLIS, null, INTERSECT_26, null);
- registerWalk(INTERSECT_26, REZERVE, INTERSECT_27, null, null);
- registerWalk(INTERSECT_27, null, null, FOREST_OF_MAGIC_ISLAND, INTERSECT_26);
- registerWalk(FOREST_OF_MAGIC_ISLAND, INTERSECT_27, null, ILE_PARADISIAQUE, null);
- register(ILE_PARADISIAQUE, new Station[]{FOREST_OF_MAGIC_ISLAND, null, INTERSECT_30, null}, new PathType[] {PathType.OFFICIAL_WALKING, PathType.OFFICIAL_WALKING, PathType.UNOFFICIAL_WALKING, PathType.OFFICIAL_WALKING});
- register(INTERSECT_30, new Station[]{ILE_PARADISIAQUE, BAIE_HA_LONG, MONTAGNES_CREUSES, null}, new PathType[] {PathType.UNOFFICIAL_WALKING, PathType.OFFICIAL_WALKING, PathType.OFFICIAL_WALKING, PathType.OFFICIAL_WALKING});
- registerWalk(MONTAGNES_CREUSES, INTERSECT_30, null, null, null);
-
- registerWalk(BAIE_HA_LONG, STEP_31, MASTER_PWEL, null, INTERSECT_30);
- registerWalk(MASTER_PWEL, null, null, null, BAIE_HA_LONG);
- register(STEP_31, new Station[]{STEP_32, null, BAIE_HA_LONG, null}, new PathType[] {PathType.UNOFFICIAL_WALKING, PathType.OFFICIAL_WALKING, PathType.OFFICIAL_WALKING, PathType.OFFICIAL_WALKING});
- register(STEP_32, new Station[]{FORT_BOYAUX, null, STEP_31, null}, new PathType[] {PathType.OFFICIAL_WALKING, PathType.OFFICIAL_WALKING, PathType.UNOFFICIAL_WALKING, PathType.OFFICIAL_WALKING});
- registerWalk(FORT_BOYAUX, SANATORIUM_VERT, null, STEP_32, null);
- registerWalk(SANATORIUM_VERT, SECTEUR_GHASTS, null, FORT_BOYAUX, null);
-
- registerWalk(KASTOU, AZIE, null, SWAG_ISLAND, null);
- registerWalk(SWAG_ISLAND, KASTOU, null, null, null);
-
- registerWalk(TOUR_INFERNALE, EURAZIE, null, null, null);
-
- // check();
- }
-
-
- private final static int STATIONS_COUNT = 4;
-
- private final int X, Y;
- private final String NAME;
- private final boolean HIDDEN;
- private final boolean DANGER;
- private Station[] SUB_STATIONS;
- private double[] DISTANCES = new double[STATIONS_COUNT];
- private PathType[] PATH_TYPES;
- private final StationType TYPE;
-
- Station(final int x, final int y)
- {
- this(x, y, null);
- }
-
- Station(final int x, final int y, final String name)
- {
- this(x, y, name, StationType.PORTAL_ONLY);
- }
-
- Station(final int x, final int y, final String name, final StationType type)
- {
- this(x, y, name, type, false, false);
- }
-
- Station(final int x, final int y, final String name, final StationType type, final boolean isHidden, final boolean danger)
- {
- X = x;
- Y = y;
-
- NAME = name;
-
- TYPE = type;
-
- HIDDEN = isHidden;
- DANGER = danger;
- }
-
- public static void register(final Station station, final Station... stations)
- {
- register(station, stations, new PathType[]{PathType.OFFICIAL_RAIL, PathType.OFFICIAL_RAIL, PathType.OFFICIAL_RAIL, PathType.OFFICIAL_RAIL});
- }
-
- public static void registerWalk(final Station station, final Station... stations)
- {
- register(station, stations, new PathType[]{PathType.OFFICIAL_WALKING, PathType.OFFICIAL_WALKING, PathType.OFFICIAL_WALKING, PathType.OFFICIAL_WALKING});
- }
-
- public static void register(final Station station, final Station[] stations, final PathType[] paths)
- {
- if(stations.length != STATIONS_COUNT || paths.length != STATIONS_COUNT)
- throw new IllegalArgumentException(String.format("Arrays sizes must be %s for %s", STATIONS_COUNT, station.name()));
-
- station.SUB_STATIONS = stations;
-
- station.PATH_TYPES = paths;
-
- for(int i = 0; i < STATIONS_COUNT; i++)
- {
- Station sub = station.SUB_STATIONS[i];
- if(sub == null)
- continue;
-
- if(sub == station)
- throw new IllegalArgumentException("Array contains itself");
-
- station.DISTANCES[i] = Math.sqrt((station.X - sub.X) * (station.X - sub.X) + (station.Y - sub.Y) * (station.Y - sub.Y));
- }
- }
-
- public static void check()
- {
- for(Station station : values())
- {
-
- for(Direction direction : Direction.values())
- {
- if(!station.hasSubStation(direction))
- continue;
-
- Station next = station.getSubStation(direction);
- Station assertion = next.getSubStation(direction.opposite());
-
- if(assertion == null || assertion != station)
- {
- throw new IllegalArgumentException("Stations " + station + " and " + next + " does not verify themselves for direction " + direction);
- }
- }
- }
- }
-
- public Station getSubStation(Direction direction)
- {
- if(direction == null)
- throw new IllegalArgumentException("Direction cannot be null");
-
- return SUB_STATIONS[direction.getIndex()];
- }
-
- public Direction getDirection(Station sub)
- {
- for(Direction direction : Direction.values())
- if(getSubStation(direction) == sub)
- return direction;
-
- throw new IllegalArgumentException("Station " + sub + " was not found in station " + name());
- }
-
- public boolean hasSubStation(Direction direction)
- {
- return getSubStation(direction) != null;
- }
-
- public double getDistanceFrom(Direction direction)
- {
- if(direction == null)
- throw new IllegalArgumentException("Direction cannot be null");
-
- return DISTANCES[direction.getIndex()];
- }
-
- public double getDistanceFrom(Station station)
- {
- return getDistanceFrom(getDirection(station));
- }
-
- public boolean isVisible()
- {
- return !HIDDEN;
- }
-
- public PathType getPathType(Direction direction)
- {
- return PATH_TYPES[direction.getIndex()];
- }
-
- public PathType getPathType(Station station)
- {
- return getPathType(getDirection(station));
- }
-
- public boolean isDangerous()
- {
- return DANGER;
- }
-
- public static List getStationsAlphabetically()
- {
- List stations = Arrays.asList(Station.values());
- Collections.sort(stations, new StationComparator());
-
- return stations;
- }
-
- @Override
- public String toString()
- {
- if(!isVisible() || isDangerous())
- return "Station inconnue";
-
- if(NAME == null)
- {
- String[] split = name().toLowerCase().split("_");
-
- for(int i = 0; i < split.length; i++)
- {
- split[i] = split[i].substring(0, 1).toUpperCase() + split[i].substring(1);
- }
-
- return Utils.join(Arrays.asList(split), " ");
- }
-
-
- return NAME;
- }
-
- public static int getId(Station station)
- {
- for(int i = 0; i < values().length; i++)
- {
- if(station == values()[i])
- return i;
- }
-
- throw new Error("Not found : " + station);
- }
-
- public int getX()
- {
- return X;
- }
-
- public int getY()
- {
- return Y;
- }
-
- public boolean isPortal()
- {
- return TYPE == StationType.PORTAL_ONLY || TYPE == StationType.INTERSECTION_AND_PORTAL;
- }
-
- public boolean isIntersection()
- {
- return TYPE == StationType.INTERSECTION_ONLY || TYPE == StationType.INTERSECTION_AND_PORTAL;
- }
-
- public JsonObject toJson(boolean withNetwork)
- {
- JsonObject objectStation = new JsonObject();
-
- objectStation.add("id", new JsonPrimitive(Station.getId(this)));
- objectStation.add("code_name", new JsonPrimitive(this.name().toLowerCase()));
- objectStation.add("full_name", new JsonPrimitive(this.toString()));
-
- objectStation.add("x", new JsonPrimitive(this.getX()));
- objectStation.add("y", new JsonPrimitive(this.getY()));
-
- objectStation.add("is_visible", new JsonPrimitive(this.isVisible()));
- objectStation.add("is_safe", new JsonPrimitive(!this.isDangerous()));
-
- objectStation.add("is_portal", new JsonPrimitive(this.isPortal()));
- objectStation.add("is_intersection", new JsonPrimitive(this.isIntersection()));
-
- JsonArray network = new JsonArray();
-
- if(withNetwork)
- {
- for(Direction direction : Direction.values())
- {
- Station sub = this.getSubStation(direction);
-
- String key = direction.name().toLowerCase();
-
- if(sub != null)
- network.add(buildConnectionObject(this, sub));
- }
-
- objectStation.add("network", network);
- }
-
- return objectStation;
- }
-
-
- /**
- * Creates a json object representing this station and its path. The last station does not have any path.
- * @param station the station
- * @param next the next station
- * @return a json object
- */
- public static JsonObject buildStationPathObject(Station station, Station next)
- {
- JsonObject object = new JsonObject();
-
- JsonObject objectStation = station.toJson(false);
-
- object.add("station", objectStation);
-
- if(next != null)
- {
- JsonObject connection = Station.buildConnectionObject(station, next);
-
- object.add("connection", connection);
- }
-
- return object;
- }
-
- /**
- * Creates a json object representing a connection between two stations.
- * @param station the main station
- * @param sub the sub station
- * @return a json object
- */
- public static JsonObject buildConnectionObject(Station station, Station sub)
- {
- JsonObject object = new JsonObject();
-
- object.add("from", new JsonPrimitive(Station.getId(station)));
- object.add("to", new JsonPrimitive(Station.getId(sub)));
-
- object.add("direction", new JsonPrimitive(station.getDirection(sub).name().toLowerCase()));
-
- object.add("length", new JsonPrimitive((int) station.getDistanceFrom(sub)));
-
- PathType pathType = station.getPathType(sub);
-
- object.add("is_official", new JsonPrimitive(pathType.isOfficial()));
-
- object.add("is_rail", new JsonPrimitive(pathType.isRail()));
-
- return object;
- }
-}
-
-/**
- * The type of station.
- */
-enum StationType
-{
- INTERSECTION_ONLY,
- INTERSECTION_AND_PORTAL,
- PORTAL_ONLY
-}
-
-class StationComparator implements Comparator
-{
- @Override
- public int compare(Station station1, Station station2) {
- return Utils.stripAccents(station1.toString()).compareTo(Utils.stripAccents(station2.toString()));
- }
-}
diff --git a/src/main/java/me/cassayre/florian/netherrail/Utils.java b/src/main/java/me/cassayre/florian/netherrail/Utils.java
deleted file mode 100644
index 7f9f283..0000000
--- a/src/main/java/me/cassayre/florian/netherrail/Utils.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package me.cassayre.florian.netherrail;
-
-import java.text.Normalizer;
-import java.util.Collection;
-import java.util.Iterator;
-
-public final class Utils
-{
- private Utils()
- {
- }
-
- public static String stripAccents(String s)
- {
- s = Normalizer.normalize(s, Normalizer.Form.NFD);
- s = s.replaceAll("[\\p{InCombiningDiacriticalMarks}]", "");
- return s;
- }
-
- public static String join(Collection var0, String var1) {
- StringBuffer var2 = new StringBuffer();
-
- for(Iterator var3 = var0.iterator(); var3.hasNext(); var2.append((String)var3.next())) {
- if(var2.length() != 0) {
- var2.append(var1);
- }
- }
-
- return var2.toString();
- }
-}
diff --git a/tests/config.rs b/tests/config.rs
new file mode 100644
index 0000000..49d7d0c
--- /dev/null
+++ b/tests/config.rs
@@ -0,0 +1,83 @@
+extern crate zeps;
+extern crate failure;
+
+use zeps::data::universe::Universe;
+use failure::Error;
+
+fn load_from_fixture(fixture: &str) -> Result {
+ zeps::read_universe_from_file(format!("./tests/fixtures/{}.json", fixture))
+}
+
+#[test]
+fn it_fails_from_nothing() {
+ assert!(load_from_fixture("empty").is_err());
+}
+
+#[test]
+fn it_loads_without_data() {
+ let universe = load_from_fixture("no_data").unwrap();
+ assert_eq!(universe.stations().into_iter().fold(0, |acc, _| acc + 1), 0);
+}
+
+#[test]
+fn it_loads_with_data() {
+ let _ = load_from_fixture("with_data").unwrap();
+}
+
+#[test]
+fn stations_are_all_there() {
+ let universe = load_from_fixture("with_data").unwrap();
+ assert_eq!(universe.stations().into_iter().fold(0, |acc, _| acc + 1), 5);
+ assert_eq!(universe.get_network("netherrail").unwrap().stations().into_iter().fold(0, |acc, _| acc + 1), 3);
+ assert_eq!(universe.get_network("overworld").unwrap().stations().into_iter().fold(0, |acc, _| acc + 1), 2);
+}
+
+
+// TODO for the following reference tests: test if the correct error is returned too.
+
+#[test]
+fn it_fails_if_a_line_references_an_unknown_station() {
+ assert!(load_from_fixture("lines_invalid_ref").is_err());
+}
+
+#[test]
+fn it_fails_if_a_line_references_an_unknown_station_in_expanded_mode() {
+ assert!(load_from_fixture("lines_invalid_ref_expanded").is_err());
+}
+
+#[test]
+fn it_fails_if_a_connection_references_an_unknown_network() {
+ assert!(load_from_fixture("connections_invalid_ref_network").is_err());
+}
+
+#[test]
+fn it_fails_if_a_connection_references_an_unknown_station() {
+ assert!(load_from_fixture("connections_invalid_ref_station").is_err());
+}
+
+#[test]
+fn it_fails_if_a_connection_references_an_unknown_station_valid_in_the_other_network() {
+ assert!(load_from_fixture("connections_invalid_ref_station_but_exists_in_other_network").is_err());
+}
+
+
+#[test]
+fn the_coordinates_factor_defaults_to_one() {
+ let universe = load_from_fixture("coordinates_factor_default").unwrap();
+ let network = universe.get_network("netherrail").unwrap();
+ assert_eq!(network.coordinates_factor(), 1.0);
+}
+
+#[test]
+fn the_coordinates_factor_defaults_to_point_125_if_nether() {
+ let universe = load_from_fixture("coordinates_factor_default_nether").unwrap();
+ let network = universe.get_network("netherrail").unwrap();
+ assert_eq!(network.coordinates_factor(), 0.125);
+}
+
+#[test]
+fn the_coordinates_factor_overrides_is_nether_if_explicit() {
+ let universe = load_from_fixture("coordinates_factor_overridden").unwrap();
+ let network = universe.get_network("netherrail").unwrap();
+ assert_eq!(network.coordinates_factor(), 1.84);
+}
diff --git a/tests/fixtures/connections_invalid_ref_network.json b/tests/fixtures/connections_invalid_ref_network.json
new file mode 100644
index 0000000..58e8efd
--- /dev/null
+++ b/tests/fixtures/connections_invalid_ref_network.json
@@ -0,0 +1,23 @@
+{
+ "name": "Vessinque",
+ "networks": {
+ "netherrail": {
+ "name": "Netherrail",
+ "world": "v5_nether",
+
+ "is_nether": true,
+
+ "coordinates_factor": 0.125,
+
+ "stations": {},
+ "lines": []
+ }
+ },
+ "networks_connections": [
+ {
+ "networks": ["netherrail", "overworld"],
+ "autoconnect_by_name": true,
+ "autoconnect_by_proximity": 10
+ }
+ ]
+}
diff --git a/tests/fixtures/connections_invalid_ref_station.json b/tests/fixtures/connections_invalid_ref_station.json
new file mode 100644
index 0000000..177cedb
--- /dev/null
+++ b/tests/fixtures/connections_invalid_ref_station.json
@@ -0,0 +1,63 @@
+{
+ "name": "Vessinque",
+ "networks": {
+ "netherrail": {
+ "name": "Netherrail",
+ "world": "v5_nether",
+
+ "is_nether": true,
+
+ "coordinates_factor": 0.125,
+
+ "stations": {
+ "station_code_name": {
+ "name": "Displayed station name",
+ "sub_name": "For stations with a main name and another pomf",
+ "description": "If needed, displayed in the map balloon. Can be omitted.",
+ "coordinates": [0, 0, 0],
+ "real_coordinates": [0, 0, 0],
+
+ "is_main": true,
+
+ "has_fast_access": true,
+ "fast_access_time": 10
+ }
+ },
+
+ "lines": []
+ },
+
+ "overworld": {
+ "name": "Surface",
+ "world": "V5",
+
+ "stations": {
+ "overworld_station": {
+ "name": "Displayed station name",
+ "sub_name": "For stations with a main name and another pomf",
+ "description": "If needed, displayed in the map balloon. Can be omitted.",
+ "coordinates": [0, 0, 0],
+ "real_coordinates": [0, 0, 0],
+
+ "is_main": true,
+
+ "has_fast_access": true,
+ "fast_access_time": 10
+ }
+ },
+
+ "lines": []
+ }
+ },
+
+ "networks_connections": [
+ {
+ "networks": ["netherrail", "overworld"],
+ "autoconnect_by_name": true,
+ "autoconnect_by_proximity": 10,
+ "connections": [
+ ["station_code_name", "unknown_station"]
+ ]
+ }
+ ]
+}
diff --git a/tests/fixtures/connections_invalid_ref_station_but_exists_in_other_network.json b/tests/fixtures/connections_invalid_ref_station_but_exists_in_other_network.json
new file mode 100644
index 0000000..8572391
--- /dev/null
+++ b/tests/fixtures/connections_invalid_ref_station_but_exists_in_other_network.json
@@ -0,0 +1,75 @@
+{
+ "name": "Vessinque",
+ "networks": {
+ "netherrail": {
+ "name": "Netherrail",
+ "world": "v5_nether",
+
+ "is_nether": true,
+
+ "coordinates_factor": 0.125,
+
+ "stations": {
+ "station_code_name": {
+ "name": "Displayed station name",
+ "sub_name": "For stations with a main name and another pomf",
+ "description": "If needed, displayed in the map balloon. Can be omitted.",
+ "coordinates": [0, 0, 0],
+ "real_coordinates": [0, 0, 0],
+
+ "is_main": true,
+
+ "has_fast_access": true,
+ "fast_access_time": 10
+ },
+ "station_code_name_2": {
+ "name": "Displayed station name",
+ "sub_name": "For stations with a main name and another pomf",
+ "description": "If needed, displayed in the map balloon. Can be omitted.",
+ "coordinates": [0, 0, 0],
+ "real_coordinates": [0, 0, 0],
+
+ "is_main": true,
+
+ "has_fast_access": true,
+ "fast_access_time": 10
+ }
+ },
+
+ "lines": []
+ },
+
+ "overworld": {
+ "name": "Surface",
+ "world": "V5",
+
+ "stations": {
+ "overworld_station": {
+ "name": "Displayed station name",
+ "sub_name": "For stations with a main name and another pomf",
+ "description": "If needed, displayed in the map balloon. Can be omitted.",
+ "coordinates": [0, 0, 0],
+ "real_coordinates": [0, 0, 0],
+
+ "is_main": true,
+
+ "has_fast_access": true,
+ "fast_access_time": 10
+ }
+ },
+
+ "lines": []
+ }
+ },
+
+ "networks_connections": [
+ {
+ "networks": ["netherrail", "overworld"],
+ "autoconnect_by_name": true,
+ "autoconnect_by_proximity": 10,
+ "connections": [
+ ["station_code_name", "station_code_name_2"]
+ ]
+ }
+ ]
+}
diff --git a/tests/fixtures/coordinates_factor_default.json b/tests/fixtures/coordinates_factor_default.json
new file mode 100644
index 0000000..a1452a8
--- /dev/null
+++ b/tests/fixtures/coordinates_factor_default.json
@@ -0,0 +1,13 @@
+{
+ "name": "Empty universe",
+ "networks": {
+ "netherrail": {
+ "name": "Netherrail",
+ "world": "V5_nether",
+
+ "stations": {},
+ "lines": []
+ }
+ },
+ "networks_connections": []
+}
diff --git a/tests/fixtures/coordinates_factor_default_nether.json b/tests/fixtures/coordinates_factor_default_nether.json
new file mode 100644
index 0000000..674f8ab
--- /dev/null
+++ b/tests/fixtures/coordinates_factor_default_nether.json
@@ -0,0 +1,15 @@
+{
+ "name": "Empty universe",
+ "networks": {
+ "netherrail": {
+ "name": "Netherrail",
+ "world": "V5_nether",
+
+ "is_nether": true,
+
+ "stations": {},
+ "lines": []
+ }
+ },
+ "networks_connections": []
+}
diff --git a/tests/fixtures/coordinates_factor_overridden.json b/tests/fixtures/coordinates_factor_overridden.json
new file mode 100644
index 0000000..041bd87
--- /dev/null
+++ b/tests/fixtures/coordinates_factor_overridden.json
@@ -0,0 +1,16 @@
+{
+ "name": "Empty universe",
+ "networks": {
+ "netherrail": {
+ "name": "Netherrail",
+ "world": "V5_nether",
+
+ "is_nether": true,
+ "coordinates_factor": 1.84,
+
+ "stations": {},
+ "lines": []
+ }
+ },
+ "networks_connections": []
+}
diff --git a/tests/fixtures/empty.json b/tests/fixtures/empty.json
new file mode 100644
index 0000000..0967ef4
--- /dev/null
+++ b/tests/fixtures/empty.json
@@ -0,0 +1 @@
+{}
diff --git a/tests/fixtures/lines_invalid_ref.json b/tests/fixtures/lines_invalid_ref.json
new file mode 100644
index 0000000..e5af20d
--- /dev/null
+++ b/tests/fixtures/lines_invalid_ref.json
@@ -0,0 +1,39 @@
+{
+ "name": "Vessinque",
+ "networks": {
+ "netherrail": {
+ "name": "Netherrail",
+ "world": "v5_nether",
+
+ "is_nether": true,
+
+ "coordinates_factor": 0.125,
+
+ "stations": {
+ "station_code_name": {
+ "name": "Displayed station name",
+ "sub_name": "For stations with a main name and another pomf",
+ "description": "If needed, displayed in the map balloon. Can be omitted.",
+ "coordinates": [0, 0, 0],
+ "real_coordinates": [0, 0, 0],
+
+ "is_main": true,
+
+ "has_fast_access": true,
+ "fast_access_time": 10
+ }
+ },
+
+ "lines": [
+ {
+ "name": "(can be left empty or removed)",
+ "color": "#rrggbb",
+ "path": [
+ "station_code_name_unknown"
+ ]
+ }
+ ]
+ }
+ },
+ "networks_connections": []
+}
diff --git a/tests/fixtures/lines_invalid_ref_expanded.json b/tests/fixtures/lines_invalid_ref_expanded.json
new file mode 100644
index 0000000..82087c7
--- /dev/null
+++ b/tests/fixtures/lines_invalid_ref_expanded.json
@@ -0,0 +1,45 @@
+{
+ "name": "Vessinque",
+ "networks": {
+ "netherrail": {
+ "name": "Netherrail",
+ "world": "v5_nether",
+
+ "is_nether": true,
+
+ "coordinates_factor": 0.125,
+
+ "stations": {
+ "station_code_name": {
+ "name": "Displayed station name",
+ "sub_name": "For stations with a main name and another pomf",
+ "description": "If needed, displayed in the map balloon. Can be omitted.",
+ "coordinates": [0, 0, 0],
+ "real_coordinates": [0, 0, 0],
+
+ "is_main": true,
+
+ "has_fast_access": true,
+ "fast_access_time": 10
+ }
+ },
+
+ "lines": [
+ {
+ "name": "(can be left empty or removed)",
+ "color": "#rrggbb",
+ "path": [
+ "station_code_name",
+ {
+ "station": "station_code_name_unknown",
+ "path_type": "walk",
+ "path_secure": false,
+ "path_to_next": [[0, 0,0], [0, 0], [0, 0, 0]]
+ }
+ ]
+ }
+ ]
+ }
+ },
+ "networks_connections": []
+}
diff --git a/tests/fixtures/no_data.json b/tests/fixtures/no_data.json
new file mode 100644
index 0000000..2001d27
--- /dev/null
+++ b/tests/fixtures/no_data.json
@@ -0,0 +1,5 @@
+{
+ "name": "Empty universe",
+ "networks": {},
+ "networks_connections": []
+}
diff --git a/tests/fixtures/with_data.json b/tests/fixtures/with_data.json
new file mode 100644
index 0000000..2159401
--- /dev/null
+++ b/tests/fixtures/with_data.json
@@ -0,0 +1,112 @@
+{
+ "name": "Vessinque",
+ "networks": {
+ "netherrail": {
+ "name": "Netherrail",
+ "world": "v5_nether",
+
+ "is_nether": true,
+
+ "coordinates_factor": 0.125,
+
+ "stations": {
+ "station_code_name": {
+ "name": "Displayed station name",
+ "sub_name": "For stations with a main name and another pomf",
+ "description": "If needed, displayed in the map balloon. Can be omitted.",
+ "coordinates": [0, 0, 0],
+ "real_coordinates": [0, 0, 0],
+
+ "is_main": true,
+
+ "has_fast_access": true,
+ "fast_access_time": 10
+ },
+ "station_code_name_2": {
+ "name": "Displayed station name",
+ "sub_name": "For stations with a main name and another pomf",
+ "description": "If needed, displayed in the map balloon. Can be omitted.",
+ "coordinates": [0, 0, 0],
+ "real_coordinates": [0, 0, 0],
+
+ "is_main": true,
+
+ "has_fast_access": true,
+ "fast_access_time": 10
+ },
+ "station_code_name_3": {
+ "name": "Displayed station name",
+ "sub_name": "For stations with a main name and another pomf",
+ "description": "If needed, displayed in the map balloon. Can be omitted.",
+ "coordinates": [0, 0, 0],
+ "real_coordinates": [0, 0, 0],
+
+ "is_main": true,
+
+ "has_fast_access": true,
+ "fast_access_time": 10
+ }
+ },
+
+ "lines": [
+ {
+ "name": "(can be left empty or removed)",
+ "color": "#rrggbb",
+ "path": [
+ "station_code_name",
+ "station_code_name_2",
+ {
+ "station": "station_code_name_3",
+ "path_type": "walk",
+ "path_secure": false,
+ "path_to_next": [[0, 0,0], [0, 0], [0, 0, 0]]
+ }
+ ]
+ }
+ ]
+ },
+
+ "overworld": {
+ "name": "Surface",
+ "world": "V5",
+ "stations": {
+ "overworld_station": {
+ "name": "Displayed station name",
+ "sub_name": "For stations with a main name and another pomf",
+ "description": "If needed, displayed in the map balloon. Can be omitted.",
+ "coordinates": [0, 0, 0],
+ "real_coordinates": [0, 0, 0],
+
+ "is_main": true,
+
+ "has_fast_access": true,
+ "fast_access_time": 10
+ },
+ "overworld_station_2": {
+ "name": "Displayed station name",
+ "sub_name": "For stations with a main name and another pomf",
+ "description": "If needed, displayed in the map balloon. Can be omitted.",
+ "coordinates": [0, 0, 0],
+ "real_coordinates": [0, 0, 0],
+
+ "is_main": true,
+
+ "has_fast_access": true,
+ "fast_access_time": 10
+ }
+ },
+ "lines": []
+ }
+ },
+ "networks_connections": [
+ {
+ "networks": ["netherrail", "overworld"],
+ "autoconnect_by_name": true,
+ "autoconnect_by_proximity": 10,
+ "connections": [
+ ["station_code_name", "overworld_station"],
+ ["station_code_name_2", "overworld_station_2"]
+ ]
+ }
+ ]
+}