-
Notifications
You must be signed in to change notification settings - Fork 44
Contributing
First off, we'd like to thank you for helping improve mark2 and maintain it for the future of Minecraft server Admins everywhere
To get started you're going to need to setup an development environment to develop for mark2. The easiest way to do this would be to work on linux (since mark2 requires a UNIX-like operating system to function), but if you aren't willing to run linux on your main computer, you can install a VM or use a spare computer to run the code. The setup process is identical to that of the install guide
mark2 is not strict with code style. A small project like this that has a history of swapping maintainers can't be super picky about code style.
The only vital thing is that your code is neat, efficient, readable and doesn't use aspects of Python 3 not available in earlier versions, no f'strings'
or walrus operators (:=
)!
mark2 aims to be backwards compatible with early versions of Python 3, roughly shooting for compatibility with Python 3.5 or later
Mark2 uses Twisted's reactor system and custom events to run servers in the background and provides a detachable client.
The effect of using an event based programming system allows mark2 to reload large portions of its services and plugins without needing to restart the server process.
All of mark2's commands are processed inside the launcher. All entry points to the other parts of mark2 start there in the main()
function located at the bottom of that file.
From there, various aspects of the code that makes up the twisted framework are setup and run.
When the mark2 start
command is received, it will use the manager to gather the necessary information to create and spawn a server process. The manager manages the services and plugins that dispatch and handle a lot of the twisted events and those events make up the IO between the Server and the Clients as well as IO between plugins and services.
The difference between a plugin and a service is that services are always run as they make up the core functionality of mark2, whereas plugins can be disabled if their function is not needed.
One of those super important services, is the process service. It actually creates and spawns the java process that runs the server by listening to the ServerStart
event generated in the manager (see Process.server_start
where it uses the twisted reactor to spawn the server process).
Certain services cannot be reloaded without consequences, for example, the Process
service cannot be reloaded as it would kill your minecraft server. Another example is the User Server
service cannot be reloaded as it would detach all clients and lose the cached data that clients need when they attach (More on that in the User Server section).
In the process service, it also handles all the events for the actual IO to the server process by using the ProcessProtocol
for dispatching ServerOutput
events for all the other aspects of mark2 and the main process services handles writing data to the server's STDIN (see Process.server_input
)
Generally, mark2's detachable client is split into two sections, the user client and the user server.
Both contain twisted "Factories" that handle attaching and detaching from the server as well as sending user commands to the server process via the event system.
When the mark2 attach
command is received, it creates an instance of UserClientFactory
class and runs it's main()
function. In there, it uses urwid to make a graphical user interface.
The UserClientFactory
connects to the UserServerFactory
socket (see UserClientFactory.connect_to_server()
) and twisted builds a protocol using the UserClientFactory.buildProtocol
method. This builds an instance of mark2's UserClientProtocol
which actually handles the IO with the server factory socket.
The UserClientProtocol
uses the lineReceived
method to process received data and uses it's send_helper
method to request data from the UserServerFactory
such as the player counts, server stats and current users attached.
All the data it receives are displayed using the UI
class.
The user server is an essential service to the function of mark2. It does some similar stuff to the UserClientFactory
such as building a twisted protocol, but this time it creates the unix socket that clients can connect to.
The user server uses this socket to process requests from the UserClientFactory
to respond with useful data it collects from various events broadcasted by the server process (console output, server stats, player counts, attached users).
It uses the UserServerProtocol
to receive data from the client and uses it's event handlers to store data for query by the UserClientFactory
. The UserServerFactory
runs as long as the server is running and will cache parts of the server's state for the clients to query when they attach so they can build the UI.
NOTE: If an event doesn't have values for it's contents listed under it, you should probably not be listening to it in scripts! Use common sense!
A good message from edk0 covered some of what will be outlined here, it's suggested you read it before continuing.
Events are how plugins communicate with each other and how almost everything that happens is orchestrated.
Some of these events can be used in conjunction with the scripts plugin to execute commands (shell and minecraft!) as well as mark2 commands when a certain event is fired. Only some of these events make sense to be used with the scripts plugin, if they have their contents listed or a note about a common use case, you can use them, otherwise you probably should not. The reason events can be used in scripts is because it was a convenient. As such, scripts can technically listen to any mark2 event when they definitely should not use most of them.
To get a list of all events mark2 has, open up a server console and type ~events
in it.
Here is a brief overview of the events mark2 has to offer
Issued by the manager when the server gives output
Used by plugins (like the user server) to handle console output from the server
Unused event for a generic error
Base event class used for all other events
Issued when a fatal error causes the server process to close. Issued from the Process
service
Tells the manager to exit with an error message
-
exception
[Optional]- The exception that caused the error
-
reason
[Optional]- The reason for the FatalError event
Issued as a general purpose event to have dynamically addable events Only used at the moment for mark2 prompt commands
Issued from the ConsoleTracking
service
Base player event class used for all other player events
Issued when a player sends a chat message. Triggered by chat messages in the console
-
username
- The player's username
-
message
- The chat message they sent
Issued when a player dies. Generally doesn't work in recent minecraft versions due to changes with the death messages
-
text
[Optional]- The full death message
- While technically optional, is always present in my testing. It's generally the best thing to use if you just want the message.
-
username
- The player's username
-
cause
- What killed the player
-
killer
[Optional]- Who killed the player
-
weapon
[Optional]- What was used to kill the player
Issued when a player connects to the server. Triggered by the <username> logged in...
message
-
username
- The player's username
-
message
- The chat message sent when they joined
Issued when a player disconnects from the server. Triggered by the <username> lost connection...
message
-
username
- The player's username
-
message
- The chat message sent when they quit
Issued to inform plugins something is happening with the server Mainly used in the push plugin to send a push notifications
-
cause
- The cause of the server event (Generally it looks like
server/error/<theerror>
orserver/warning/<thewarning>
)
- The cause of the server event (Generally it looks like
-
data
- The reason why the server event was fired (Example:
server crashed for unknown reason
)
- The reason why the server event was fired (Example:
Issued to send data to the server's stdin
Issued when the server gives a line on stdout. Allows the use of a pattern to only receive lines matching the pattern
Issued to start the server
Issued when the server has finished starting. Triggered by the Done (123.456s)!
message and fired from the Process
service
Typical usage of this event in the scripts is for scheduling a server restart with the ~restart
command
Issued to inform plugins the server is starting
Issued to stop the server
Issued to inform plugins the server is stopping
-
reason
- The reason the server stopped
-
respawn
- Whether the server will restart afterwards or not
- Respawn Types
- TERMINATE = 0
- RESTART = 1
- HOLD = 2
-
kill
- Is it a force kill
Issued when the server stops fully
Base stat event class used for all other stat events
Issued by the Ping
service to send the number of players and max number of players on a server to plugins
-
players_current
- Number of players on the server
-
players_max
- Max number of players allowed on the server
Issued by the manager to send a list of players to plugins Player information is gathered by the player events
-
players
- A list of players on the server
Issued by the Process
service to inform plugins of the CPU and memory usage of the server process
-
cpu
- CPU usage in percentage
-
memory
- Memory usage in percentage
Issued from the UserServer
service after receiving data from the UserClient
Issued to alert plugins that a user attached to the console
Issued to alert plugins that a user detached from the console
Issued when a user sends a line in the prompt. Handled by the manager to either forward the input to plugins as a Hook event or to dispatch a ServerInput event