Project Architecture (How the plugin is put together)
This page attempts to help new developers start contributing to Plan.
It does not go over the build tool & commands for building as those are detailed in Project Setup.
Page version: 5.4 build 1651 Commit
Table of contents
- Java
- Level 1: System overview
- Level 2: Module level overview
- Level 3: Package level overview
- Web dev
- Level 1: Technology stack overview
- Level 2: Directory level overview
Java
Level 1: System overview
Plan runs as a plugin on top of various Minecraft server platforms. A lot of the platform specific code required to do this is abstracted away for easier development. Below is a system overview diagram.
Level 2: Module level overview
Module | Role |
---|---|
api |
Contains code for public API interface classes |
extensions |
Contains built-in extensions that use DataExtension API (in public API) |
common |
Main package for everything |
bukkit , bungee , sponge , velocity , nukkit , fabric |
Platform specific modules |
plugin |
Creates a single jar out of the modules |
Most of the time work is done in common
module as platforms are abstracted away.
Build order
api
->extensions
->common
->bukkit
,bungee
,sponge
,velocity
,nukkit
->plugin
api
->extensions
->common
->fabric
From the build order, the dependencies between the modules should be apparent.
Level 3: Package level overview
Structure outline of common
-module
Below are packages that are in package common/src/java/com.djrapitops.plan
New modules use net.playeranalytics.plan
package, old package name is used for backwards compatibility and clarity in older modules.
Package | Role |
---|---|
api |
Deprecated. Plan API v4. |
capability |
Capability Service implementation (APIv5) |
commands |
Implementation for commands (plan , planproxy /planbungee /planvelocity ) |
commands.use |
Abstraction layer & framework for commands |
commands.subcommands |
Execution code for different commands |
data |
Deprecated. Contains APIv4 data classes. |
delivery |
Output related packages |
delivery.domain |
Data objects related to delivering web content & doing analysis |
delivery.export |
Export System and its utilities, for exporting html and json files |
delivery.formatting |
Date, time & data formatting utilities |
delivery.rendering |
Utilities for writing html and json |
delivery.web |
PageExtension API implementation (APIv5) |
delivery.webserver |
WebServer implementation & Request resolving |
exceptions |
Exceptions used around the plugin |
extension |
Implementation for DataExtension API (APIv5) |
gathering |
Input related packages |
gathering.afk |
AFK Tracking |
gathering.cache |
Caches for gathered data like Sessions |
gathering.domain |
Data objects related to gathered data |
gathering.importing |
Import system |
gathering.listeners |
Basis for event listeners (mostly platform based) |
gathering.timed |
Timed tasks related to data gathering |
identification |
Identification of current server and UUID utilities |
modules |
Dagger related dependency resolution classes |
processing |
Extra execution service for async processing |
query |
Implementation for Query API (APIv5) |
settings |
Everything that user can configure (Config, Locale, Theme) |
storage |
Database & resource (file/jar) management |
`storage.database.queries | SQL queries for the database |
storage.database.transactions |
Transactions for the database |
utilities |
Utilities used in the plugin |
utilities.analysis |
Mathematical utilities |
utilities.chat |
In-game chat-box space formatting utility |
utilities.comparators |
Sorting utilities |
utilities.html.icon |
Deprecated. APIv4 html utilities |
utilities.java |
Java language extending utilities |
utilities.logging |
Error logging code |
version |
System that checks for new version |
Dagger & Dependency Injection
Dagger (https://dagger.dev/) is used extensively around the project. It was used as a remedy to reduce static usage. (See decisions here Refactor plugin to use static getters and Dependency Injection: Dagger)
@Singleton
annotations are used to tell Dagger that only a single instance should exist per initialized Component (So that each PlanSystem
only has one DatabaseSystem
instead of returning a new one every time the database is needed.)
@Inject
annotations are used in Constructors to tell Dagger to resolve the dependencies for constructing a new instance of this class.
Most of the plugin uses Inject annotations, but some dagger related things can be found from modules
package
Note that the Inject constructors allow Injecting an instance of the class the constructor is in to another object:
public class Foo {
@Inject
public Foo() {}
}
public class Bar {
@Inject
public Bar(Foo foo) {}
}
This is the main mechanism used for instantiating different system level objects, more about those below.
Lifecycle
The process begins in a platform specific module by creating a new Dagger Component
that resolves all dependencies for PlanSystem
.
- When the plugin is enabled by the platform it is running on
PlanSystem#enable
is called, which will lead to all subsystems getting started in a specific order. This order is determined by dependencies between the subsystems. When parts of these subsystems are injected in any constructor, I've tried to keep the same order as they are enabled. - When the plugin is reloaded with
plan reload
command by user, first the plugin is disabled and then enabled. A new Dagger component is created in the process, soPlanSystem
instance is new each time the process enables. - When the platform is shutting down and the plugin is disabled
PlanSystem#disable
is called, which stops all extra threads and closes resources the plugin is using. Platform specific shutdown such as cancelling runnables happens in the plugin class of the platform.
Abstraction layer for platforms
Different server platforms offer more or less the same sort of functionality, but with a different API. This is why in Plan some of it is abstracted away with Platform abstraction layer.
This is mostly limited to Task scheduling and logging.
RunnableFactory
can be injected to create and schedule tasks (remember to schedule after creation).PluginLogger
can be injected to log stuff to the console.
Other abstraction is achieved by using PlanSystem
and Dagger to inject interface implementations from other modules.
Platform Modules
Platform modules include only the implementation for the specific platform. Code from Bukkit is not available in sponge
module and so on.
In the platform modules you can find implementations for Listeners and some tasks that require platform specific function calls.
Note that proxy implementations (Bungee, Velocity) have different gathering behaviors and deliver different pages - this is done with the listeners and the different execution paths are done in the common
module by using ServerInfo#isProxy
method.
Web Dev
Level 1: Technology stack overview
The Plan frontend is currently being rewritten in React, so the two web stacks exist in parallel.
Level 2: Directory level overview
- Web files served by the webserver in the plugin live in
/Plan/common/src/main/resources/assets/plan/web
.- The files are the old frontend stack.
- Gradle task copies
/Plan/react/dashboard/build
to/Plan/common/build/resources/assets/plan/web
during build so the built bundle is available to the webserver in the same way.- The files in
/Plan/react/dashboard
are the new frontend stack.
- The files in
Export consideration
- Web files are written for static webserver deployments in
/Plan/common/src/main/java/com/djrapitops/plan/delivery/export
and new files added to old frontend stack should be reflected there.
Development
Developing old frontend stack from IDE
- Start Game/Proxy server with Plan webserver on port 8804
- Enable web developer mode
Developing new frontend stack from IDE
- Start Game/Proxy server with Plan webserver on port 8804
- Change proxy address to
http://localhost:8804
in/Plan/react/dashboard/package.json
- Go to
/Plan/react/dashboard/
- run
yarn start
If you have any questions you can open an issue or join the discord server.
Documentation
Tutorials
Configuration
- Game server Set-up
- Network Set-up
- Game server Configuration
- Network Configuration
- Login / HTTPS Set-Up
- Commands & Permissions
- Database management
- PlaceholderAPI