zDevelopers / ZePS-Core

Pathfinder for in-game Minecraft railway system.
https://zeps.zcraft.fr
Other
2 stars 1 forks source link

Modularization #4

Open FlorianCassayre opened 7 years ago

FlorianCassayre commented 7 years ago

The original structure slowly becomes depecrated, the following points need to be reconsidered:

AmauryCarrade commented 7 years ago

+1 for unit tests. Some are really easy to implement (or already implemented, like graph validity check).

@Coutume used to store the graph into a PostgreSQL database for a similar project, because there is an implementation of the Dijkstra and A* algorithms right into the database (in the form of an extension). It could be an option to investigate. JSON files would be great too. There is also specialised formats like GeoJSON, but I don't know if they are the best option for routing.

(Oh, just noticed you moved the repository to the zDevelopers org. For coherence or another reason?)

FlorianCassayre commented 7 years ago

(Oh, just noticed you moved the repository to the zDevelopers org. For coherence or another reason?)

It was supposed to be so at the very begining but I noticed it wasn't.

Also, since I moved the repository I lost most of my rights (I didn't try to push though).

AmauryCarrade commented 7 years ago

Also, since I moved the repository I lost most of my rights (I didn't try to push though).

All organization members have push access on any repository. I made you an admin of this repo.

AmauryCarrade commented 7 years ago

Ok so, some thoughts on this subject.

First of all, I definitely think we should merge ZéPS-Core and ZéPS-GUI into a single application, either in PHP (to avoid a partial GUI rewrite) or in Python (with Flask, for better performances and language—the rewrite would not be too large anyway, with a large part in unchanged JavaScript). In both cases, the path-finding performances could be a little worse than before, but remember, there is an aggressive cache policy, every path is only computed once. We could also build up some clever cache to pre-calculate popular or typical paths.

Regarding storage, the chosen option must be, in my opinion:

For the last point, we could use different file names, and put all data related to one multi-words network (e.g. Vessinque) in one file. Or in one folder, if we want to split data across multiple files.

I can't help but noticing that all stations are regrouped into lines (both netherrail, with the colors, and the overworld Grandes Routes). We could use that to simplify a lot the data input, with something like this (it's only a draft) (empty keys are comments).

{
    "name": "Vessinque",

    "networks": [
        {
            "id": "netherrail",
            "name": "Netherrail",
            "world": "v5_nether",

            "is_nether": true,
            "": "Currently, the fact that the network is in a Nether world is
                 sort of hardcoded into the ZéPS GUI, with links to “overworld
                 counterpart” using coordinates multiplied by eight, or messages
                 saying to “go into the Nether” for through-overworld paths (in
                 the alternative paths recommandations). This key will allows the
                 GUI to act knowing if the network is in the Nether, or not.",

            "coordinates_factor": 0.125,
            "": "This key is the factor to apply to the coordinates to get comparable
                 coordinates accross all networks. It is by default set to 1 if the
                 world is not a Nether one, and to 0.125 if it is. This key allows
                 to customize this value, if there is another non-vanilla kind of
                 world in the server with a factor other than 1 or 0.125.
                 It's very easy to implement and lead to a simpler code regarding to
                 coordinates (by using this factor instead of a systematic test on
                 “is that network in a Nether world?”), so here it is.",

            "stations": [
                {
                    "id": "station_code_name",
                    "name": "Displayed station name",
                    "subname": "For stations with a main name and another useful one,
                                e.g. Sanctuary. Displayed in the map under the main
                                label. Can be omitted.",
                    "description": "If needed, displayed in the map balloon. Can be omitted.",

                    "coordinates": [0, 0],
                    "": "x, z or x, y, z. In a single key for the sake of input simplicity,
                         but this could be changed.",
                    "real_coordinates": [0, 0],
                    "": "This is a new key used for geolocation purposes. In the
                         current map, most coordinates are the ones of the
                         projection of the portal location on the line, not the
                         real portal location. This would be the _real_ location,
                         not used for mapping, but used to geolocate users and
                         offer the nearest station. Can be omitted.",

                    "is_hidden": false,
                    "": "Used for the few intersections without station. If omitted,
                         false.",

                    "is_main": true,
                    "": "If exists and set to true, this is considered as a main
                         station (e.g. Nouvea, Tentaclès)",

                    "has_fast_access": true,
                    "fast_access_time": 10,
                    "": "This is meant to improve the alternative paths
                         recommandations:
                         1. stations with this tag existing and set to true will
                            be tested for shorter path;
                         2. the specified time (seconds) will be addded to the
                            whole time, to take into account the time needed to,
                            e.g., type “/spawn”, go to the portal and wait for
                            teleportation."
                }
            ],

            "lines": [
                {
                    "name": "(can be left empty or removed)",
                    "color": "#rrggbb",
                    "path": [
                        "station_1",
                        "station_2",
                        {
                            "station": "station_3",
                            "path_type": "walk",
                            "path_secure": false,
                            "path_to_next": [[0, 0], [0, 0, 0], [0, 0]],
                            "": "In a line path, we can place either stations
                                 names or objects like this.

                                 Stations names will be understood as stations
                                 objects with default values, i.e. path type to
                                 rail, considered secure, and with no specific
                                 path to the next stop (i.e. direct straight line
                                 path).

                                 path_type and path_secure should be pretty
                                 straightforward.

                                 path_to_next is my answer to complicated paths:
                                 it's an array of points the line pass by until
                                 the next stop. With this we can easily have very
                                 complex paths (in the nether but also with the
                                 overworld routes, way less straight than overworld
                                 ones)."
                        },
                        "station_4"
                    ]
                }
            ]
        }
    ],
    "networks_connections": [
        {
            "networks": ["netherrail", "overworld"],
            "autoconnect_by_name": true,
            "autonnect_by_proximity": 10,
            "connections": [
                ["station_in_the_netherrail", "station_in_the_overworld"],
                ["station_in_the_netherrail", "station_in_the_overworld"],
                ["station_in_the_netherrail", "station_in_the_overworld"]
            ],
            "": "Here, connections between the networks are defined. This
                 allows to route users through all the networks defined.

                 The connections key is easy to understand: each item in
                 the array is a connection between two networks: the one
                 from the first network in the “networks” key, the other
                 from the other one.

                 The “autoconnect_by_name” option is meant to simplify
                 our work by establishing connections automatically. It
                 would connect every station with the same “id” key in both
                 networks.

                 The idea behind the “autonnect_by_proximity” is the same,
                 but with coordinates proximity in mind. It would connect
                 stations that are closed than the amount of meters given.
                 It would take into account the world types (e.g. nether vs
                 overworld), by mutiplying or dividing by eight (or other
                 value, see “coordinates_factor”) if needed."
        }
    ]
}

As you can see, in this option, a lot of data would be auto generated, to simplify the input. I think we should, if we select an option like this one, pre-compute the networks into a real graph (my eyes are mainly looking at autoconnect_by_name and autonnect_by_proximity).

The option I propose here fulfils all points of my list but the 2nd one. I think it's a reasonable compromise.

A Bukkit plugin installed on the server to generate these JSON files could be very handful (with commands to add points or stations in lines, e.g. used through @prokopyl' CommandTools plugin).

One of the hardest thing to think about if we go into this way would be how to display in the map a path going to multiple networks. In my mind, in the main map (/plan), multiple networks are shown separately, as they would be stacked up if not. I don't have any good solution for this as for now, but I'm open to suggestions.

The router should have options to only use one or some of the defined networks, so an user can say « I only want to use the overworld network ». It would have to specify into the path when networks are changed (so the GUI can tell the user when to go to the Nether, the surface, or other).

Again these are only suggestions. Opinions?


/cc @FlorianCassayre @Coutume @prokopyl.

AmauryCarrade commented 7 years ago

@FlorianCassayre For reference, if you're still following this project, we started with @prokopyl a reimplementation of the core in Rust, based on my suggestion above. See the rust branch. Both the router and the server (for the REST API) will be in rust, in the same code base.

The Core and the GUI will not be merged, after discussion with ProkopyL.