1 """API for the Minecraft Server integration."""
3 from dataclasses
import dataclass
4 from enum
import StrEnum
7 from dns.resolver
import LifetimeTimeout
8 from mcstatus
import BedrockServer, JavaServer
9 from mcstatus.status_response
import BedrockStatusResponse, JavaStatusResponse
13 _LOGGER = logging.getLogger(__name__)
15 LOOKUP_TIMEOUT: float = 10
16 DATA_UPDATE_TIMEOUT: float = 10
17 DATA_UPDATE_RETRIES: int = 3
22 """Representation of Minecraft Server data."""
33 players_list: list[str] |
None =
None
36 edition: str |
None =
None
37 game_mode: str |
None =
None
38 map_name: str |
None =
None
42 """Enumeration of Minecraft Server types."""
44 BEDROCK_EDITION =
"Bedrock Edition"
45 JAVA_EDITION =
"Java Edition"
49 """Raised when the input address is invalid."""
52 class MinecraftServerConnectionError(Exception):
53 """Raised when no data can be fechted from the server."""
57 """Raised when APIs are used although server instance is not initialized yet."""
61 """Minecraft Server wrapper class for 3rd party library mcstatus."""
63 _server: BedrockServer | JavaServer |
None
66 self, hass: HomeAssistant, server_type: MinecraftServerType, address: str
68 """Initialize server instance."""
75 """Perform async initialization of server instance."""
77 if self.
_server_type_server_type == MinecraftServerType.JAVA_EDITION:
78 self.
_server_server = await JavaServer.async_lookup(self.
_address_address)
80 self.
_server_server = await self.
_hass_hass.async_add_executor_job(
81 BedrockServer.lookup, self.
_address_address
83 except (ValueError, LifetimeTimeout)
as error:
85 f
"Lookup of '{self._address}' failed: {self._get_error_message(error)}"
88 self.
_server_server.timeout = DATA_UPDATE_TIMEOUT
91 "Initialized %s server instance with address '%s'",
97 """Check if the server is online, supporting both Java and Bedrock Edition servers."""
101 MinecraftServerConnectionError,
102 MinecraftServerNotInitializedError,
105 "Connection check of %s server failed: %s",
114 """Get updated data from the server, supporting both Java and Bedrock Edition servers."""
115 status_response: BedrockStatusResponse | JavaStatusResponse
117 if self.
_server_server
is None:
119 f
"Server instance with address '{self._address}' is not initialized"
123 status_response = await self.
_server_server.async_status(tries=DATA_UPDATE_RETRIES)
124 except OSError
as error:
126 f
"Status request to '{self._address}' failed: {self._get_error_message(error)}"
129 if isinstance(status_response, JavaStatusResponse):
137 self, status_response: JavaStatusResponse
138 ) -> MinecraftServerData:
139 """Extract Java Edition server data out of status response."""
140 players_list: list[str] = []
142 if players := status_response.players.sample:
143 players_list.extend(player.name
for player
in players)
147 latency=status_response.latency,
148 motd=status_response.motd.to_plain(),
149 players_max=status_response.players.max,
150 players_online=status_response.players.online,
151 protocol_version=status_response.version.protocol,
152 version=status_response.version.name,
153 players_list=players_list,
157 self, status_response: BedrockStatusResponse
158 ) -> MinecraftServerData:
159 """Extract Bedrock Edition server data out of status response."""
161 latency=status_response.latency,
162 motd=status_response.motd.to_plain(),
163 players_max=status_response.players.max,
164 players_online=status_response.players.online,
165 protocol_version=status_response.version.protocol,
166 version=status_response.version.name,
167 edition=status_response.version.brand,
168 game_mode=status_response.gamemode,
169 map_name=status_response.map_name,
173 """Get error message of an exception."""
None __init__(self, HomeAssistant hass, MinecraftServerType server_type, str address)
MinecraftServerData _extract_java_data(self, JavaStatusResponse status_response)
bool async_is_online(self)
None async_initialize(self)
MinecraftServerData async_get_data(self)
MinecraftServerData _extract_bedrock_data(self, BedrockStatusResponse status_response)
str _get_error_message(self, BaseException error)