ServerInterface
API package path: mcdreforged.api.types
- class mcdreforged.plugin.si.server_interface.ServerInterface(mcdr_server: MCDReforgedServer)[source]
ServerInterface is the interface with lots of API for plugins to interact with the server. Its subclass
PluginServerInterfacecontains extra APIs for plugins to control the plugin itselfIt’s recommend to use
serveras the variable name of the ServerInterface. This is widely used in this document
Instance Getters
- classmethod ServerInterface.get_instance() ServerInterface | None[source]
A class method, for plugins to get a ServerInterface instance anywhere as long as MCDR is running
- ServerInterface.as_basic_server_interface() ServerInterface[source]
Return a
ServerInterfaceinstance. The type of the return value is exactly theServerInterfaceIt’s used for removing the plugin information inside
PluginServerInterfacewhen you need to send aServerInterfaceas parameter
- ServerInterface.as_plugin_server_interface() PluginServerInterface | None[source]
Return a
PluginServerInterfaceinstance.If the object is exactly a
PluginServerInterfaceinstance, return itselfIf the plugin context is available, return the
PluginServerInterfacefor the related plugin. Currently, plugin context is only available inside the following scenarios:Plugin entrypoint module loading
Event listener callback invocation
Command callback invocation
- classmethod ServerInterface.si() ServerInterface[source]
Alias / Shortform of
get_instance(), and never returns None- Raises:
RuntimeError – If MCDR is not running
- classmethod ServerInterface.si_opt() ServerInterface | None[source]
Alias / Shortform of
get_instance(), get an optionalServerInterfaceinstance- Returns:
The
ServerInterfaceinstance, or None if failed
- classmethod ServerInterface.psi() PluginServerInterface[source]
Shortform of the combination of
get_instance()+as_plugin_server_interface(), and never returns None- Raises:
RuntimeError – Get
PluginServerInterfacefailed. This might occur because MCDR is not running (seesi()), or plugin context is unavailable (seeas_plugin_server_interface())
- classmethod ServerInterface.psi_opt() PluginServerInterface | None[source]
Shortform of the combination of
get_instance()+as_plugin_server_interface(), get an optionalPluginServerInterfaceinstance- Returns:
The
PluginServerInterfaceinstance for the current plugin, or None if failed
Utils
- ServerInterface.MCDR = True
An identifier field for MCDR
- ServerInterface.tr(translation_key: str, *args, _mcdr_tr_language: str | None = None, **kwargs) str | RTextBase[source]
Return a translated text corresponded to the translation key and format the text with given args and kwargs
If args or kwargs contains
RTextelement, then the result will be aRText, otherwise the result will be a regular strIf the translation key is not recognized, the return value will be the translation key itself
See here for the ways to register translations for your plugin
- Parameters:
translation_key – The key of the translation
args – The args to be formatted
_mcdr_tr_language – Specific language to be used in this translation, or the language that MCDR is using will be used
kwargs – The kwargs to be formatted
- ServerInterface.rtr(translation_key: str, *args, **kwargs) RTextMCDRTranslation[source]
Return a
RTextMCDRTranslationcomponent, that only translates itself right before displaying or serializingUsing this method instead of
tr()allows you to display your texts in user’s preferred language automaticallyOf course, you can construct
RTextMCDRTranslationyourself instead of using this method if you want- Parameters:
translation_key – The key of the translation
args – The args to be formatted
kwargs – The kwargs to be formatted
Added in version v2.1.0.
- ServerInterface.has_translation(translation_key: str, *, language: str | None = None, no_auto_fallback: bool = False)[source]
Check if the given translation exists
Notes that if the current language fails, MCDR will try to use “en_us” for a second attempt. If you don’t want this auto-fallback behavior, set argument no_auto_fallback to True
Also, you don’t need to pass
*argsand**kwargsfor the translation into this method, because existence check doesn’t need those- Parameters:
translation_key – The key of the translation
- Keyword Arguments:
language – Optional, the language to check for translation key existence
no_auto_fallback – When set to True, MCDR will not fall back to “en_us” and have another translation try, if translation failed
Added in version v2.12.0.
Server Control
- ServerInterface.start() bool[source]
Start the server. Return if the action succeed.
If the server is running or being starting by other plugin it will return
False- Returns:
If the operation succeed. The operation fails if the server is already started, or cannot start due to invalid command or current MCDR state
- ServerInterface.stop() bool[source]
Soft shutting down the server by sending the correct stop command to the server
This option will not stop MCDR. MCDR will keep running unless
exit()is invoked- Returns:
If the operation succeed. The operation fails if the server is already stopped
- ServerInterface.kill() bool[source]
Kill the entire server process group. A hard shutting down
MCDR will keep running unless
exit()is invoked- Returns:
If the operation succeed. The operation fails if the server is already stopped
- ServerInterface.wait_until_stop() None[source]
Wait until the server is stopped
Note
The current thread will be blocked
- ServerInterface.wait_for_start() None[source]
Wait until the server is able to start
Actually it’s an alias of
wait_until_stop()
- ServerInterface.restart() bool[source]
Restart the server
It will first
soft stopthe server and thenwaituntil the server is stopped, finallystartthe server up- Returns:
If the operation succeed. The operation fails if the server is already stopped
- ServerInterface.stop_exit() bool[source]
soft stopthe server and exit MCDR- Returns:
If the operation succeed. The operation fails if the server is already stopped
- ServerInterface.exit() bool[source]
Exit MCDR when the server is stopped
Basically it’s the same to invoking
set_exit_after_stop_flag()with parameterTrue, but with an extra server not running checkExample usage:
server.stop() # Stop the server # do something A server.wait_for_start() # Make sure the server is fully stopped. It's necessary to run it in your custom thread # do something B server.exit() # Exit MCDR
- Returns:
If the operation succeed. The operation fails if the server is still running
- ServerInterface.set_exit_after_stop_flag(flag_value: bool) None[source]
Set the flag that indicating if MCDR should exit when the server has stopped
If set to
True, after the server stops MCDR will exit, otherwise (set toFalse) MCDR will just keep runningThe flag value will be set to
Trueeverytime when the server startsThe flag value is displayed in line 5 in command
!!MCDR status
- ServerInterface.get_server_pid() int | None[source]
Return the pid of the server process
Notes the process with this pid is a bash process, which is the parent process of real server process you might be interested in
- Returns:
The pid of the server. None if the server is stopped
- ServerInterface.get_server_pid_all() List[int][source]
Return a list of pid of all processes in the server’s process group
- Returns:
A list of pid. It will be empty if the server is stopped or the pid query failed
Added in version v2.6.0.
- ServerInterface.get_server_information() ServerInformation[source]
Return a
ServerInformationobject indicating the information of the current server, interred from the output of the serverIt’s field(s) might be None if the server is offline, or the related information has not been parsed
Added in version v2.1.0.
Text Interaction
- ServerInterface.execute(text: str, *, encoding: str | None = None) None[source]
Execute a server command by sending the command content to server’s standard input stream
See also
execute_command()if you want to execute command in MCDR’s command system- Parameters:
text – The content of the command you want to send
- Keyword Arguments:
encoding – The encoding method for the text. Leave it empty to use the encoding method from the configuration of MCDR
- ServerInterface.tell(player: str, text: str | RTextBase, *, encoding: str | None = None) None[source]
Use command like
/tellrawto send the message to the specific player- Parameters:
player – The name of the player you want to tell
text – The message you want to send to the player
- Keyword Arguments:
encoding – The encoding method for the text. Leave it empty to use the encoding method from the configuration of MCDR
- ServerInterface.say(text: str | RTextBase, *, encoding: str | None = None) None[source]
Use command like
/tellraw @ato broadcast the message in game- Parameters:
text – The message you want to send
- Keyword Arguments:
encoding – The encoding method for the text. Leave it empty to use the encoding method from the configuration of MCDR
- ServerInterface.broadcast(text: str | RTextBase, *, encoding: str | None = None) None[source]
Broadcast the message in game and to the console
If the server is not running, send the message to console only
- Parameters:
text – The message you want to send
- Keyword Arguments:
encoding – The encoding method for the text. Leave it empty to use the encoding method from the configuration of MCDR
- ServerInterface.reply(info: Info, text: str | RTextBase, *, encoding: str | None = None, console_text: str | RTextBase | None = None)[source]
Reply to the source of the Info
If the Info is from a player, then use tell to reply the player; if the Info is from the console, then use
server.logger.infoto output to the console; In the rest of the situations, the Info is not from a user, aIllegalCallErroris raised- Parameters:
info – the Info you want to reply to
text – The message you want to send
- Keyword Arguments:
encoding – The encoding method for the text
console_text – If it’s specified, console_text will be used instead of text when replying to console
- Raises:
IllegalCallError – If the Info is not from a user
Plugin Queries
- ServerInterface.get_plugin_metadata(plugin_id: str) Metadata | None[source]
Return the metadata of the specified plugin, or None if the plugin doesn’t exist
- Parameters:
plugin_id – The id of the plugin to query metadata
- ServerInterface.get_plugin_type(plugin_id: str) PluginType | None[source]
Return the type of the specified plugin, or None if the plugin doesn’t exist
- Parameters:
plugin_id – The id of the plugin to query type
Added in version v2.13.0.
- ServerInterface.get_plugin_file_path(plugin_id: str) str | None[source]
Return the file path of the specified plugin, or None if the plugin doesn’t exist
- Parameters:
plugin_id – The id of the plugin to query file path
- ServerInterface.is_plugin_file_changed(plugin_id: str) bool | None[source]
Return if the given plugin has its plugin file changed, or None if the plugin doesn’t exist
Notes: Directory Plugin is always considered as changed
- Parameters:
plugin_id – The id of the plugin to query file change state
Added in version v2.13.0.
- ServerInterface.get_plugin_instance(plugin_id: str) Any | None[source]
Return the entrypoint module instance of the specific plugin, or None if the plugin doesn’t exist
If the target plugin is a solo plugin and it needs to react to events from MCDR, it’s quite important to use this instead of manually import the plugin you want, since it’s the only way to make your plugin be able to access the same plugin instance to MCDR
Example usage:
The entrypoint module of my API plugin with id
my_api:def some_api(item): pass
Another plugin that needs my API plugin:
server.get_plugin_instance('my_api').some_api(an_item)
- Parameters:
plugin_id – The id of the plugin you want to get entrypoint module instance
- Returns:
A entrypoint module instance, or None if the plugin doesn’t exist
- ServerInterface.get_plugin_list() List[str][source]
Return a list containing all loaded plugin id like
["my_plugin", "another_plugin"]
- ServerInterface.get_unloaded_plugin_list() List[str][source]
Return a list containing all unloaded plugin file path like
["plugins/MyPlugin.mcdr"]Added in version v2.3.0.
Plugin Operations
Warning
All plugin manipulation will trigger a dependency check, which might cause unwanted plugin operations
It’s not suggested to trigger plugin operations during on_load or on_unload plugin events. During these events, MCDR is in a process of an ongoing plugin operation, which is not suitable to triggered another plugin operation
If you do trigger a plugin operation during on_load or on_unload plugin events, MCDR will delay the new operations till the first operation finishes. In this delayed operation case, the return value of following APIs will always be false or None
- ServerInterface.load_plugin(plugin_file_path: str) bool[source]
Load a plugin from the given file path
- Parameters:
plugin_file_path – The file path of the plugin to load. Example: “plugins/my_plugin.py”
- Returns:
If the plugin gets loaded successfully
- ServerInterface.enable_plugin(plugin_file_path: str) bool[source]
Enable a disabled plugin from the given path
- Parameters:
plugin_file_path – The file path of the plugin to enable. Example: “plugins/my_plugin.py.disabled”
- Returns:
If the plugin gets enabled successfully
- ServerInterface.reload_plugin(plugin_id: str) bool | None[source]
Reload a plugin specified by plugin id
- Parameters:
plugin_id – The id of the plugin to reload. Example:
"my_plugin"- Returns:
A bool indicating if the plugin gets reloaded successfully, or None if plugin not found
- ServerInterface.unload_plugin(plugin_id: str) bool | None[source]
Unload a plugin specified by plugin id
- Parameters:
plugin_id – The id of the plugin to unload. Example:
"my_plugin"- Returns:
A bool indicating if the plugin gets unloaded successfully, or None if plugin not found
- ServerInterface.disable_plugin(plugin_id: str) bool | None[source]
Disable an unloaded plugin specified by plugin id
- Parameters:
plugin_id – The id of the plugin to disable. Example:
"my_plugin"- Returns:
A bool indicating if the plugin gets disabled successfully, or None if plugin not found
- ServerInterface.refresh_all_plugins() None[source]
Reload all plugins, load all new plugins and then unload all removed plugins
- ServerInterface.refresh_changed_plugins() None[source]
Reload all changed plugins, load all new plugins and then unload all removed plugins
- ServerInterface.manipulate_plugins(*, load: Sequence[Path | str] | None = None, unload: Sequence[str] | None = None, reload: Sequence[str] | None = None, enable: Sequence[Path | str] | None = None, disable: Sequence[str] | None = None) bool | None[source]
A highly-customizable plugin manipulate API that provides fine-grain control on what to be manipulated: load / unload / reload / enable / disable the provided plugins, in a single action
Tip
Here some different plugin “reload” cases and what actions you should actually provide
MyPlugin.mcdrremains unchanged: reloadmy_pluginMyPlugin.mcdrchanges its content: reloadmy_pluginMyPlugin.mcdris replaced with an upgradedMyPlugin_v2.mcdr: unloadmy_pluginand loadMyPlugin_v2.mcdrin one call
- Parameters:
load – An optional plugin file path list containing plugins to be loaded
unload – An optional plugin ID list containing plugins to be loaded
reload – An optional plugin ID list containing plugins to be reloaded
enable – An optional plugin file path list containing plugins to be enabled
disable – An optional plugin ID list containing plugins to be disabled
- Returns:
True if all operation succeeded, False if failed, None if it’s a not-suggested chained sync plugin operation
Added in version v2.13.0.
- ServerInterface.dispatch_event(event: PluginEvent, args: Tuple[Any, ...], *, on_executor_thread: bool = True) None[source]
Dispatch an event to all loaded plugins
The event will be immediately dispatch if it’s on the task executor thread, or gets enqueued if it’s on other thread
Note
You cannot dispatch an event with the same event id to any MCDR built-in event
Example
For the event dispatcher plugin:
server.dispatch_event(LiteralEvent('my_plugin.my_event'), (1, 'a'))
For the event listener plugin:
def do_something(server: PluginServerInterface, int_data: int, str_data: str): pass server.register_event_listener('my_plugin.my_event', do_something)
- Parameters:
event – The event to dispatch. It needs to be a
PluginEventinstance. For simple usage, you can create aLiteralEventinstance for this argumentargs – The argument that will be used to invoke the event listeners. An
PluginServerInterfaceinstance will be automatically added to the beginning of the argument list
- Keyword Arguments:
on_executor_thread – By default the event will be dispatched in a new task in task executor thread If it’s set to False. The event will be dispatched immediately
Configuration
- ServerInterface.modify_mcdr_config(changes: Dict[Tuple[str, ...] | str, Any])[source]
Modify the configuration of MCDR
The modification will be written to the disk and take effect immediately
Currently, MCDR will not validate the type of the value
Example usages:
server.modify_mcdr_config({'encoding': 'utf8'}) server.modify_mcdr_config({'rcon.address': '127.0.0.1', 'rcon.port': 23000}) server.modify_mcdr_config({('debug', 'command'): True})
- Parameters:
changes – A dict storing the changes to the config. For the entries of the dict: The key can be a tuple storing the path to the config value, or a str that concat the path with
"."; The value is the config value to be set
Added in version v2.7.0.
Permission
- ServerInterface.get_permission_level(obj: str | Info | CommandSource) int[source]
Return an int indicating permission level number the given object has
The object could be a str indicating the name of a player, an
Infoinstance or acommand source- Parameters:
obj – The object you are querying
- Raises:
TypeError – If the type of the given object is not supported for permission querying
- ServerInterface.set_permission_level(player: str, value: str | int) None[source]
Set the permission level of the given player
- Parameters:
player – The name of the player that you want to set his/her permission level
value – The target permission level you want to set the player to. It can be an int or a str as long as it’s related to the permission level. Available examples:
1,"1","user"
- Raises:
TypeError – If the value parameter doesn’t properly represent a permission level
Command
- ServerInterface.get_plugin_command_source() PluginCommandSource[source]
Return a plugin command source, which can be used to execute MCDR commands
It’s not player or console, it has maximum permission level, it uses
loggerfor replying
- ServerInterface.get_player_command_source(player: str) PlayerCommandSource[source]
Return a player command source, which can be used to simulate a player executing MCDR commands
Note: the
Infoinstance bound to the returned command source is a dummy one that contains nothing- Parameters:
player – The name of the player
Added in version v2.15.0.
- ServerInterface.get_console_command_source() ConsoleCommandSource[source]
Return a console command source, which can be used to simulate the console executing MCDR commands
Note: the
Infoinstance bound to the returned command source is a dummy one that contains nothingAdded in version v2.15.0.
- ServerInterface.execute_command(command: str, source: CommandSource | None = None) None[source]
Execute a single command in MCDR’s command system
See also
execute()if you want to send some text to server’s standard input stream- Parameters:
command – The command you want to execute
source – The command source that is used to execute the command. If it’s not specified MCDR will use
get_plugin_command_source()to get a fallback command source
Preference
- ServerInterface.get_preference(obj: str | PlayerCommandSource | ConsoleCommandSource) PreferenceItem[source]
Get the MCDR preference of the given object
The object can be a str indicating the name of a player, or a command source. For command source, only
PlayerCommandSourceandConsoleCommandSourceare supported- Parameters:
obj – The object to query preference
- Raises:
TypeError – If the type of the given object is not supported for preference querying
Added in version v2.1.0.
- ServerInterface.get_default_preference() PreferenceItem[source]
Get the default MCDR preference
Added in version v2.8.0.
- ServerInterface.set_preference(obj: str | PlayerCommandSource | ConsoleCommandSource, preference: PreferenceItem)[source]
Set the MCDR preference of the given object
The object can be a str indicating the name of a player, or a command source. For command source, only
PlayerCommandSourceandConsoleCommandSourceare supported- Parameters:
obj – The object to set preference
preference – The preference to be set
- Raises:
TypeError – If the type of the given object is not supported for preference querying
Added in version v2.8.0.
Misc
- ServerInterface.is_on_executor_thread() bool[source]
Return if the current thread is the task executor thread
Task executor thread is the main thread to parse messages and trigger listeners where some ServerInterface APIs are required to be invoked on
- ServerInterface.is_on_async_executor_thread() bool[source]
Return if the current thread is the async task executor thread
Async task executor thread is where all async event listener callbacks are invoked
Added in version v2.14.0.
Warning
Beta API
- ServerInterface.get_event_loop() AbstractEventLoop[source]
Return the event loop running in the async executor thread, which will be used for all async event listener callbacks
Added in version v2.14.0.
Warning
Beta API
- ServerInterface.rcon_query(command: str) str | None[source]
Send command to the server through rcon connection
- Parameters:
command – The command you want to send to the rcon server
- Returns:
The result that server returned from rcon. Return None if rcon is not running or rcon query failed
- ServerInterface.schedule_task(callable_: Callable[[], _T] | Coroutine[Any, Any, _T], *, block: bool = False, timeout: float | None = None) Future[_T][source]
Schedule a callback task to be run in task executor / async task executor thread
- Parameters:
callable – The callable or coroutine object to be run. It should accept 0 parameter
- Keyword Arguments:
block – If blocks until the callable finished execution
timeout – The timeout of the blocking operation if
block=True
Added in version v2.14.0: The callback param now supports
coroutine objectorcoroutine functionThe return value is now a
FutureWarning
Beta API