pybedrock-net 0.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,179 @@
1
+ Metadata-Version: 2.4
2
+ Name: pybedrock-net
3
+ Version: 0.0.1
4
+ Summary: A Python-native RakNet foundation for Minecraft Bedrock protocol experiments.
5
+ Author: ZENKAI
6
+ Project-URL: Homepage, https://pypi.org/project/pybedrock-net/
7
+ Project-URL: YouTube, https://www.youtube.com/@szewq
8
+ Keywords: minecraft,bedrock,raknet,udp,protocol,bot
9
+ Classifier: Development Status :: 2 - Pre-Alpha
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3 :: Only
13
+ Classifier: Topic :: Internet
14
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
15
+ Requires-Python: >=3.9
16
+ Description-Content-Type: text/markdown
17
+ Requires-Dist: build>=1.4.4
18
+ Requires-Dist: pytest>=8.4.2
19
+ Requires-Dist: twine>=6.2.0
20
+
21
+ # pybedrock-net
22
+
23
+ Python-native RakNet foundations for Minecraft Bedrock protocol experiments.
24
+
25
+ Developed by ZENKAI, with Sader (سادر) leading the development and protocol
26
+ implementation work.
27
+
28
+ ## Overview
29
+
30
+ `pybedrock-net` is an early development project focused on understanding and
31
+ implementing Minecraft Bedrock networking directly in Python. Bedrock uses
32
+ RakNet as an important networking foundation. The long-term goal is a reusable
33
+ Python foundation for programmable Bedrock clients, bots, protocol tools,
34
+ testing tools, experiments, and automation systems.
35
+
36
+ This project targets the network protocol rather than requiring a complete
37
+ Minecraft game client. It is not a Minecraft server and is not a replacement
38
+ for Minecraft.
39
+
40
+ ## Current implementation
41
+
42
+ Version 0.0.1 contains a real UDP implementation of the RakNet offline
43
+ handshake:
44
+
45
+ ```text
46
+ 0x05 OpenConnectionRequest1
47
+
48
+ 0x06 OpenConnectionReply1
49
+
50
+ 0x07 OpenConnectionRequest2
51
+
52
+ 0x08 OpenConnectionReply2
53
+ ```
54
+
55
+ `RakNetSession` creates a UDP socket, sends Request1, parses Reply1, sends
56
+ Request2, and parses Reply2. The command-line probe performs this exchange
57
+ against a reachable Bedrock UDP endpoint.
58
+
59
+ Successful Reply2 means only that the RakNet offline handshake completed. It
60
+ does not mean the client logged into Minecraft or entered the world.
61
+
62
+ ## Architecture
63
+
64
+ ```text
65
+ Python application / Bot
66
+
67
+ UDP transport
68
+
69
+ RakNet
70
+
71
+ Minecraft Bedrock protocol
72
+
73
+ Minecraft Bedrock server
74
+ ```
75
+
76
+ The transport layer owns UDP communication. RakNet provides the connection and
77
+ reliability foundation. The Bedrock layer will eventually provide login, world,
78
+ player, chat, and command protocol support.
79
+
80
+ ## Live connection probe
81
+
82
+ Run this against a real Bedrock UDP endpoint:
83
+
84
+ ```bash
85
+ pybedrock-net example.org --port 19132
86
+ ```
87
+
88
+ The host and port are supplied by the user and are never embedded in the
89
+ package. No credentials or server infrastructure are included.
90
+
91
+ ## Usage
92
+
93
+ The current session API is experimental:
94
+
95
+ ```python
96
+ import asyncio
97
+ from pybedrock_net import RakNetSession
98
+
99
+
100
+ async def main() -> None:
101
+ session = RakNetSession("example.org", port=19132)
102
+ try:
103
+ reply = await session.connect()
104
+ print(reply.server_guid, reply.mtu)
105
+ finally:
106
+ session.close()
107
+
108
+
109
+ asyncio.run(main())
110
+ ```
111
+
112
+ This connects to RakNet only. It does not log in, move a player, follow a
113
+ player, send chat, or execute commands yet.
114
+
115
+ ## Current limitations
116
+
117
+ - Connected RakNet framing is not implemented.
118
+ - Complete reliability, ACK, NAK, ordering, and channel handling are not
119
+ implemented.
120
+ - RakNet connection request and accepted-connection stages are not implemented.
121
+ - Bedrock login, encryption, network settings, start game, and play state are
122
+ not implemented.
123
+ - Player position tracking and movement packets are not implemented.
124
+ - Following a player, chat messages, and command execution are not implemented.
125
+ - No stable high-level bot API is available.
126
+
127
+ These limitations are explicit because sending guessed Bedrock packets can
128
+ disconnect a server or corrupt a session.
129
+
130
+ ## Roadmap
131
+
132
+ 1. **RakNet offline handshake** — implemented and locally tested; real-server
133
+ verification depends on a reachable endpoint.
134
+ 2. **Connected RakNet framing** — in development.
135
+ 3. **Reliability, ACK/NAK, ordering, and session lifecycle** — planned.
136
+ 4. **Bedrock login and encryption** — planned.
137
+ 5. **Bedrock play protocol and player tracking** — planned.
138
+ 6. **Movement, follow-player behavior, chat, and permitted commands** — planned.
139
+ 7. **High-level Bedrock bot API** — long-term goal.
140
+
141
+ ## Installation
142
+
143
+ ```bash
144
+ pip install pybedrock-net
145
+ ```
146
+
147
+ Version 0.0.1 is an early foundation/development release. APIs may change,
148
+ protocol implementation is incomplete, and the package is not production-ready.
149
+
150
+ ## Development
151
+
152
+ ```bash
153
+ python -m pytest
154
+ python -m build
155
+ python -m twine check dist/*
156
+ ```
157
+
158
+ ## Developer & Community
159
+
160
+ - **Developer:** ZENKAI
161
+ - **Development:** Sader (سادر)
162
+ - **Telegram:** `s_xwn`
163
+ - **TikTok:** `s_xwn`
164
+ - **YouTube:** https://www.youtube.com/@szewq
165
+
166
+ An official support/community link may be added in a future release.
167
+
168
+ ## Future Support
169
+
170
+ The intended future bot layer may allow Python programs to connect to Bedrock
171
+ servers where supported, authenticate, receive player events, follow a target
172
+ player, move, send chat, issue permitted commands, and automate protocol-level
173
+ tasks. These are future capabilities, not features available in 0.0.1.
174
+
175
+ ## License
176
+
177
+ No license file was present when this distribution was prepared. A license
178
+ should be selected before the project is treated as a fully licensed
179
+ open-source distribution.
@@ -0,0 +1,159 @@
1
+ # pybedrock-net
2
+
3
+ Python-native RakNet foundations for Minecraft Bedrock protocol experiments.
4
+
5
+ Developed by ZENKAI, with Sader (سادر) leading the development and protocol
6
+ implementation work.
7
+
8
+ ## Overview
9
+
10
+ `pybedrock-net` is an early development project focused on understanding and
11
+ implementing Minecraft Bedrock networking directly in Python. Bedrock uses
12
+ RakNet as an important networking foundation. The long-term goal is a reusable
13
+ Python foundation for programmable Bedrock clients, bots, protocol tools,
14
+ testing tools, experiments, and automation systems.
15
+
16
+ This project targets the network protocol rather than requiring a complete
17
+ Minecraft game client. It is not a Minecraft server and is not a replacement
18
+ for Minecraft.
19
+
20
+ ## Current implementation
21
+
22
+ Version 0.0.1 contains a real UDP implementation of the RakNet offline
23
+ handshake:
24
+
25
+ ```text
26
+ 0x05 OpenConnectionRequest1
27
+
28
+ 0x06 OpenConnectionReply1
29
+
30
+ 0x07 OpenConnectionRequest2
31
+
32
+ 0x08 OpenConnectionReply2
33
+ ```
34
+
35
+ `RakNetSession` creates a UDP socket, sends Request1, parses Reply1, sends
36
+ Request2, and parses Reply2. The command-line probe performs this exchange
37
+ against a reachable Bedrock UDP endpoint.
38
+
39
+ Successful Reply2 means only that the RakNet offline handshake completed. It
40
+ does not mean the client logged into Minecraft or entered the world.
41
+
42
+ ## Architecture
43
+
44
+ ```text
45
+ Python application / Bot
46
+
47
+ UDP transport
48
+
49
+ RakNet
50
+
51
+ Minecraft Bedrock protocol
52
+
53
+ Minecraft Bedrock server
54
+ ```
55
+
56
+ The transport layer owns UDP communication. RakNet provides the connection and
57
+ reliability foundation. The Bedrock layer will eventually provide login, world,
58
+ player, chat, and command protocol support.
59
+
60
+ ## Live connection probe
61
+
62
+ Run this against a real Bedrock UDP endpoint:
63
+
64
+ ```bash
65
+ pybedrock-net example.org --port 19132
66
+ ```
67
+
68
+ The host and port are supplied by the user and are never embedded in the
69
+ package. No credentials or server infrastructure are included.
70
+
71
+ ## Usage
72
+
73
+ The current session API is experimental:
74
+
75
+ ```python
76
+ import asyncio
77
+ from pybedrock_net import RakNetSession
78
+
79
+
80
+ async def main() -> None:
81
+ session = RakNetSession("example.org", port=19132)
82
+ try:
83
+ reply = await session.connect()
84
+ print(reply.server_guid, reply.mtu)
85
+ finally:
86
+ session.close()
87
+
88
+
89
+ asyncio.run(main())
90
+ ```
91
+
92
+ This connects to RakNet only. It does not log in, move a player, follow a
93
+ player, send chat, or execute commands yet.
94
+
95
+ ## Current limitations
96
+
97
+ - Connected RakNet framing is not implemented.
98
+ - Complete reliability, ACK, NAK, ordering, and channel handling are not
99
+ implemented.
100
+ - RakNet connection request and accepted-connection stages are not implemented.
101
+ - Bedrock login, encryption, network settings, start game, and play state are
102
+ not implemented.
103
+ - Player position tracking and movement packets are not implemented.
104
+ - Following a player, chat messages, and command execution are not implemented.
105
+ - No stable high-level bot API is available.
106
+
107
+ These limitations are explicit because sending guessed Bedrock packets can
108
+ disconnect a server or corrupt a session.
109
+
110
+ ## Roadmap
111
+
112
+ 1. **RakNet offline handshake** — implemented and locally tested; real-server
113
+ verification depends on a reachable endpoint.
114
+ 2. **Connected RakNet framing** — in development.
115
+ 3. **Reliability, ACK/NAK, ordering, and session lifecycle** — planned.
116
+ 4. **Bedrock login and encryption** — planned.
117
+ 5. **Bedrock play protocol and player tracking** — planned.
118
+ 6. **Movement, follow-player behavior, chat, and permitted commands** — planned.
119
+ 7. **High-level Bedrock bot API** — long-term goal.
120
+
121
+ ## Installation
122
+
123
+ ```bash
124
+ pip install pybedrock-net
125
+ ```
126
+
127
+ Version 0.0.1 is an early foundation/development release. APIs may change,
128
+ protocol implementation is incomplete, and the package is not production-ready.
129
+
130
+ ## Development
131
+
132
+ ```bash
133
+ python -m pytest
134
+ python -m build
135
+ python -m twine check dist/*
136
+ ```
137
+
138
+ ## Developer & Community
139
+
140
+ - **Developer:** ZENKAI
141
+ - **Development:** Sader (سادر)
142
+ - **Telegram:** `s_xwn`
143
+ - **TikTok:** `s_xwn`
144
+ - **YouTube:** https://www.youtube.com/@szewq
145
+
146
+ An official support/community link may be added in a future release.
147
+
148
+ ## Future Support
149
+
150
+ The intended future bot layer may allow Python programs to connect to Bedrock
151
+ servers where supported, authenticate, receive player events, follow a target
152
+ player, move, send chat, issue permitted commands, and automate protocol-level
153
+ tasks. These are future capabilities, not features available in 0.0.1.
154
+
155
+ ## License
156
+
157
+ No license file was present when this distribution was prepared. A license
158
+ should be selected before the project is treated as a fully licensed
159
+ open-source distribution.
@@ -0,0 +1,7 @@
1
+ """Python-native foundations for Minecraft Bedrock networking."""
2
+
3
+ __version__ = "0.0.1"
4
+
5
+ from .protocol.raknet.session import RakNetSession
6
+
7
+ __all__ = ["RakNetSession", "__version__"]
@@ -0,0 +1,53 @@
1
+ """Command-line tools for checking a Bedrock server's RakNet endpoint."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ import asyncio
7
+ import sys
8
+
9
+ from .protocol.raknet.session import RakNetSession
10
+
11
+
12
+ def build_parser() -> argparse.ArgumentParser:
13
+ parser = argparse.ArgumentParser(
14
+ prog="pybedrock-net",
15
+ description="Run the RakNet offline handshake against a Bedrock server.",
16
+ )
17
+ parser.add_argument("host", help="Bedrock server hostname or IPv4 address")
18
+ parser.add_argument("--port", type=int, default=19132, help="Bedrock UDP port")
19
+ parser.add_argument("--mtu", type=int, default=1492, help="Requested MTU (576-1492)")
20
+ parser.add_argument("--timeout", type=float, default=5.0, help="Reply timeout in seconds")
21
+ return parser
22
+
23
+
24
+ async def _run(args: argparse.Namespace) -> int:
25
+ session = RakNetSession(
26
+ args.host, port=args.port, mtu=args.mtu, timeout=args.timeout
27
+ )
28
+ try:
29
+ reply = await session.connect()
30
+ print(f"Connected to {args.host}:{args.port}")
31
+ print(f"Server GUID: {reply.server_guid}")
32
+ print(f"Negotiated MTU: {reply.mtu}")
33
+ print(f"Security enabled: {reply.security_enabled}")
34
+ print("RakNet offline handshake complete (0x05 → 0x06 → 0x07 → 0x08).")
35
+ print(
36
+ "Bedrock login/play is not completed by this release; "
37
+ "no movement or chat packets are sent."
38
+ )
39
+ return 0
40
+ except (OSError, TimeoutError, ValueError) as exc:
41
+ print(f"Connection failed: {exc}", file=sys.stderr)
42
+ return 1
43
+ finally:
44
+ session.close()
45
+
46
+
47
+ def main() -> int:
48
+ args = build_parser().parse_args()
49
+ return asyncio.run(_run(args))
50
+
51
+
52
+ if __name__ == "__main__":
53
+ raise SystemExit(main())
@@ -0,0 +1 @@
1
+ """Minecraft protocol implementations."""
@@ -0,0 +1,12 @@
1
+ """RakNet protocol primitives used by Minecraft Bedrock."""
2
+
3
+ from .constants import OFFLINE_MAGIC
4
+ from .packets import OpenConnectionReply1, OpenConnectionReply2
5
+ from .session import RakNetSession
6
+
7
+ __all__ = [
8
+ "OFFLINE_MAGIC",
9
+ "OpenConnectionReply1",
10
+ "OpenConnectionReply2",
11
+ "RakNetSession",
12
+ ]
@@ -0,0 +1,33 @@
1
+ """RakNet constants."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import struct
6
+
7
+ OFFLINE_MAGIC = bytes.fromhex("00ffff00fefefefefdfdfdfd12345678")
8
+ OPEN_CONNECTION_REQUEST_1 = 0x05
9
+ OPEN_CONNECTION_REPLY_1 = 0x06
10
+ OPEN_CONNECTION_REQUEST_2 = 0x07
11
+ OPEN_CONNECTION_REPLY_2 = 0x08
12
+
13
+
14
+ def pack_u16(value: int) -> bytes:
15
+ return struct.pack(">H", value)
16
+
17
+
18
+ def pack_u64(value: int) -> bytes:
19
+ return struct.pack(">Q", value)
20
+
21
+
22
+ def unpack_u16(data: bytes, offset: int) -> tuple[int, int]:
23
+ end = offset + 2
24
+ if len(data) < end:
25
+ raise ValueError("packet ended while reading uint16")
26
+ return struct.unpack(">H", data[offset:end])[0], end
27
+
28
+
29
+ def unpack_u64(data: bytes, offset: int) -> tuple[int, int]:
30
+ end = offset + 8
31
+ if len(data) < end:
32
+ raise ValueError("packet ended while reading uint64")
33
+ return struct.unpack(">Q", data[offset:end])[0], end
@@ -0,0 +1,81 @@
1
+ """RakNet offline packet encoding and decoding."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import ipaddress
6
+
7
+ from .constants import (
8
+ OFFLINE_MAGIC,
9
+ OPEN_CONNECTION_REPLY_1,
10
+ OPEN_CONNECTION_REPLY_2,
11
+ OPEN_CONNECTION_REQUEST_1,
12
+ OPEN_CONNECTION_REQUEST_2,
13
+ pack_u16,
14
+ pack_u64,
15
+ unpack_u16,
16
+ unpack_u64,
17
+ )
18
+
19
+
20
+ def encode_ipv4(address: str) -> bytes:
21
+ ip = ipaddress.ip_address(address)
22
+ if ip.version != 4:
23
+ raise ValueError("RakNet Bedrock transport currently requires an IPv4 address")
24
+ return bytes((0x04,)) + bytes((octet ^ 0xFF for octet in ip.packed))
25
+
26
+
27
+ def decode_ipv4(data: bytes, offset: int = 0) -> tuple[str, int]:
28
+ if len(data) < offset + 5 or data[offset] != 0x04:
29
+ raise ValueError("expected RakNet IPv4 address")
30
+ raw = bytes(octet ^ 0xFF for octet in data[offset + 1 : offset + 5])
31
+ return str(ipaddress.ip_address(raw)), offset + 5
32
+
33
+
34
+ def build_open_connection_request_1(mtu: int, protocol_version: int = 11) -> bytes:
35
+ if not 576 <= mtu <= 1492:
36
+ raise ValueError("MTU must be between 576 and 1492 bytes")
37
+ # Request1 is padded to the requested datagram size.
38
+ header = bytes((OPEN_CONNECTION_REQUEST_1,)) + OFFLINE_MAGIC + bytes((protocol_version,))
39
+ return header + bytes(max(0, mtu - len(header)))
40
+
41
+
42
+ def build_open_connection_request_2(
43
+ server_host: str, server_port: int, mtu: int, client_guid: int
44
+ ) -> bytes:
45
+ if not 0 <= server_port <= 65535:
46
+ raise ValueError("server port must be between 0 and 65535")
47
+ return (
48
+ bytes((OPEN_CONNECTION_REQUEST_2,))
49
+ + OFFLINE_MAGIC
50
+ + encode_ipv4(server_host)
51
+ + pack_u16(server_port)
52
+ + pack_u16(mtu)
53
+ + pack_u64(client_guid)
54
+ )
55
+
56
+
57
+ class OpenConnectionReply1:
58
+ """Parsed 0x06 OpenConnectionReply1."""
59
+
60
+ def __init__(self, data: bytes) -> None:
61
+ if len(data) < 28 or data[0] != OPEN_CONNECTION_REPLY_1:
62
+ raise ValueError("not an OpenConnectionReply1 packet")
63
+ if data[1:17] != OFFLINE_MAGIC:
64
+ raise ValueError("invalid RakNet offline magic")
65
+ self.server_guid, offset = unpack_u64(data, 17)
66
+ self.security_enabled = bool(data[offset])
67
+ self.mtu, _ = unpack_u16(data, offset + 1)
68
+
69
+
70
+ class OpenConnectionReply2:
71
+ """Parsed 0x08 OpenConnectionReply2."""
72
+
73
+ def __init__(self, data: bytes) -> None:
74
+ if len(data) < 35 or data[0] != OPEN_CONNECTION_REPLY_2:
75
+ raise ValueError("not an OpenConnectionReply2 packet")
76
+ if data[1:17] != OFFLINE_MAGIC:
77
+ raise ValueError("invalid RakNet offline magic")
78
+ self.server_guid, offset = unpack_u64(data, 17)
79
+ self.client_address, offset = decode_ipv4(data, offset)
80
+ self.server_port, offset = unpack_u16(data, offset)
81
+ self.mtu, _ = unpack_u16(data, offset)
@@ -0,0 +1,5 @@
1
+ """Compatibility exports for RakNet offline packet types."""
2
+
3
+ from .offline import OpenConnectionReply1, OpenConnectionReply2
4
+
5
+ __all__ = ["OpenConnectionReply1", "OpenConnectionReply2"]
@@ -0,0 +1,66 @@
1
+ """RakNet session lifecycle for the offline Bedrock handshake."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+ import secrets
7
+
8
+ from .offline import (
9
+ OpenConnectionReply1,
10
+ OpenConnectionReply2,
11
+ build_open_connection_request_1,
12
+ build_open_connection_request_2,
13
+ )
14
+ from .transport import UdpTransport
15
+
16
+
17
+ class RakNetSession:
18
+ """Perform the real RakNet offline handshake over UDP.
19
+
20
+ This intentionally stops after Reply2. Connected RakNet and Bedrock login
21
+ require additional protocol stages and encryption that are not silently
22
+ approximated here.
23
+ """
24
+
25
+ def __init__(
26
+ self,
27
+ host: str,
28
+ *,
29
+ port: int = 19132,
30
+ mtu: int = 1492,
31
+ timeout: float = 5.0,
32
+ client_guid: int | None = None,
33
+ ) -> None:
34
+ self.host = host
35
+ self.port = port
36
+ self.mtu = mtu
37
+ self.timeout = timeout
38
+ self.client_guid = client_guid if client_guid is not None else secrets.randbits(64)
39
+ self.transport = UdpTransport(host, port, timeout)
40
+ self.reply1: OpenConnectionReply1 | None = None
41
+ self.reply2: OpenConnectionReply2 | None = None
42
+
43
+ async def connect(self) -> OpenConnectionReply2:
44
+ await self.transport.open()
45
+ await self.transport.send(build_open_connection_request_1(self.mtu))
46
+ self.reply1 = OpenConnectionReply1(await self.transport.receive())
47
+ await self.transport.send(
48
+ build_open_connection_request_2(
49
+ self.transport.peer_host or self.host,
50
+ self.port,
51
+ self.reply1.mtu,
52
+ self.client_guid,
53
+ )
54
+ )
55
+ self.reply2 = OpenConnectionReply2(await self.transport.receive())
56
+ return self.reply2
57
+
58
+ async def run(self) -> None:
59
+ """Keep the UDP session available for future connected-RakNet work."""
60
+ if self.reply2 is None:
61
+ raise RuntimeError("call connect() before run()")
62
+ while True:
63
+ await self.transport.receive()
64
+
65
+ def close(self) -> None:
66
+ self.transport.close()
@@ -0,0 +1,47 @@
1
+ """Async UDP transport for RakNet datagrams."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+ import socket
7
+
8
+
9
+ class UdpTransport:
10
+ def __init__(self, host: str, port: int, timeout: float) -> None:
11
+ self.host = host
12
+ self.port = port
13
+ self.timeout = timeout
14
+ self._socket: socket.socket | None = None
15
+ self.peer_host: str | None = None
16
+
17
+ async def open(self) -> None:
18
+ infos = await asyncio.get_running_loop().getaddrinfo(
19
+ self.host, self.port, type=socket.SOCK_DGRAM
20
+ )
21
+ if not infos:
22
+ raise OSError(f"could not resolve {self.host}")
23
+ family, socktype, proto, _, address = infos[0]
24
+ self.peer_host = address[0]
25
+ sock = socket.socket(family, socktype, proto)
26
+ sock.setblocking(False)
27
+ await asyncio.get_running_loop().sock_connect(sock, address)
28
+ self._socket = sock
29
+
30
+ async def send(self, packet: bytes) -> None:
31
+ if self._socket is None:
32
+ raise RuntimeError("transport is not open")
33
+ await asyncio.get_running_loop().sock_sendall(self._socket, packet)
34
+
35
+ async def receive(self, max_size: int = 2048) -> bytes:
36
+ if self._socket is None:
37
+ raise RuntimeError("transport is not open")
38
+ return await asyncio.wait_for(
39
+ asyncio.get_running_loop().sock_recv(self._socket, max_size),
40
+ timeout=self.timeout,
41
+ )
42
+
43
+ def close(self) -> None:
44
+ if self._socket is not None:
45
+ self._socket.close()
46
+ self._socket = None
47
+ self.peer_host = None
@@ -0,0 +1,179 @@
1
+ Metadata-Version: 2.4
2
+ Name: pybedrock-net
3
+ Version: 0.0.1
4
+ Summary: A Python-native RakNet foundation for Minecraft Bedrock protocol experiments.
5
+ Author: ZENKAI
6
+ Project-URL: Homepage, https://pypi.org/project/pybedrock-net/
7
+ Project-URL: YouTube, https://www.youtube.com/@szewq
8
+ Keywords: minecraft,bedrock,raknet,udp,protocol,bot
9
+ Classifier: Development Status :: 2 - Pre-Alpha
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3 :: Only
13
+ Classifier: Topic :: Internet
14
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
15
+ Requires-Python: >=3.9
16
+ Description-Content-Type: text/markdown
17
+ Requires-Dist: build>=1.4.4
18
+ Requires-Dist: pytest>=8.4.2
19
+ Requires-Dist: twine>=6.2.0
20
+
21
+ # pybedrock-net
22
+
23
+ Python-native RakNet foundations for Minecraft Bedrock protocol experiments.
24
+
25
+ Developed by ZENKAI, with Sader (سادر) leading the development and protocol
26
+ implementation work.
27
+
28
+ ## Overview
29
+
30
+ `pybedrock-net` is an early development project focused on understanding and
31
+ implementing Minecraft Bedrock networking directly in Python. Bedrock uses
32
+ RakNet as an important networking foundation. The long-term goal is a reusable
33
+ Python foundation for programmable Bedrock clients, bots, protocol tools,
34
+ testing tools, experiments, and automation systems.
35
+
36
+ This project targets the network protocol rather than requiring a complete
37
+ Minecraft game client. It is not a Minecraft server and is not a replacement
38
+ for Minecraft.
39
+
40
+ ## Current implementation
41
+
42
+ Version 0.0.1 contains a real UDP implementation of the RakNet offline
43
+ handshake:
44
+
45
+ ```text
46
+ 0x05 OpenConnectionRequest1
47
+
48
+ 0x06 OpenConnectionReply1
49
+
50
+ 0x07 OpenConnectionRequest2
51
+
52
+ 0x08 OpenConnectionReply2
53
+ ```
54
+
55
+ `RakNetSession` creates a UDP socket, sends Request1, parses Reply1, sends
56
+ Request2, and parses Reply2. The command-line probe performs this exchange
57
+ against a reachable Bedrock UDP endpoint.
58
+
59
+ Successful Reply2 means only that the RakNet offline handshake completed. It
60
+ does not mean the client logged into Minecraft or entered the world.
61
+
62
+ ## Architecture
63
+
64
+ ```text
65
+ Python application / Bot
66
+
67
+ UDP transport
68
+
69
+ RakNet
70
+
71
+ Minecraft Bedrock protocol
72
+
73
+ Minecraft Bedrock server
74
+ ```
75
+
76
+ The transport layer owns UDP communication. RakNet provides the connection and
77
+ reliability foundation. The Bedrock layer will eventually provide login, world,
78
+ player, chat, and command protocol support.
79
+
80
+ ## Live connection probe
81
+
82
+ Run this against a real Bedrock UDP endpoint:
83
+
84
+ ```bash
85
+ pybedrock-net example.org --port 19132
86
+ ```
87
+
88
+ The host and port are supplied by the user and are never embedded in the
89
+ package. No credentials or server infrastructure are included.
90
+
91
+ ## Usage
92
+
93
+ The current session API is experimental:
94
+
95
+ ```python
96
+ import asyncio
97
+ from pybedrock_net import RakNetSession
98
+
99
+
100
+ async def main() -> None:
101
+ session = RakNetSession("example.org", port=19132)
102
+ try:
103
+ reply = await session.connect()
104
+ print(reply.server_guid, reply.mtu)
105
+ finally:
106
+ session.close()
107
+
108
+
109
+ asyncio.run(main())
110
+ ```
111
+
112
+ This connects to RakNet only. It does not log in, move a player, follow a
113
+ player, send chat, or execute commands yet.
114
+
115
+ ## Current limitations
116
+
117
+ - Connected RakNet framing is not implemented.
118
+ - Complete reliability, ACK, NAK, ordering, and channel handling are not
119
+ implemented.
120
+ - RakNet connection request and accepted-connection stages are not implemented.
121
+ - Bedrock login, encryption, network settings, start game, and play state are
122
+ not implemented.
123
+ - Player position tracking and movement packets are not implemented.
124
+ - Following a player, chat messages, and command execution are not implemented.
125
+ - No stable high-level bot API is available.
126
+
127
+ These limitations are explicit because sending guessed Bedrock packets can
128
+ disconnect a server or corrupt a session.
129
+
130
+ ## Roadmap
131
+
132
+ 1. **RakNet offline handshake** — implemented and locally tested; real-server
133
+ verification depends on a reachable endpoint.
134
+ 2. **Connected RakNet framing** — in development.
135
+ 3. **Reliability, ACK/NAK, ordering, and session lifecycle** — planned.
136
+ 4. **Bedrock login and encryption** — planned.
137
+ 5. **Bedrock play protocol and player tracking** — planned.
138
+ 6. **Movement, follow-player behavior, chat, and permitted commands** — planned.
139
+ 7. **High-level Bedrock bot API** — long-term goal.
140
+
141
+ ## Installation
142
+
143
+ ```bash
144
+ pip install pybedrock-net
145
+ ```
146
+
147
+ Version 0.0.1 is an early foundation/development release. APIs may change,
148
+ protocol implementation is incomplete, and the package is not production-ready.
149
+
150
+ ## Development
151
+
152
+ ```bash
153
+ python -m pytest
154
+ python -m build
155
+ python -m twine check dist/*
156
+ ```
157
+
158
+ ## Developer & Community
159
+
160
+ - **Developer:** ZENKAI
161
+ - **Development:** Sader (سادر)
162
+ - **Telegram:** `s_xwn`
163
+ - **TikTok:** `s_xwn`
164
+ - **YouTube:** https://www.youtube.com/@szewq
165
+
166
+ An official support/community link may be added in a future release.
167
+
168
+ ## Future Support
169
+
170
+ The intended future bot layer may allow Python programs to connect to Bedrock
171
+ servers where supported, authenticate, receive player events, follow a target
172
+ player, move, send chat, issue permitted commands, and automate protocol-level
173
+ tasks. These are future capabilities, not features available in 0.0.1.
174
+
175
+ ## License
176
+
177
+ No license file was present when this distribution was prepared. A license
178
+ should be selected before the project is treated as a fully licensed
179
+ open-source distribution.
@@ -0,0 +1,18 @@
1
+ README.md
2
+ pyproject.toml
3
+ pybedrock_net/__init__.py
4
+ pybedrock_net/cli.py
5
+ pybedrock_net.egg-info/PKG-INFO
6
+ pybedrock_net.egg-info/SOURCES.txt
7
+ pybedrock_net.egg-info/dependency_links.txt
8
+ pybedrock_net.egg-info/entry_points.txt
9
+ pybedrock_net.egg-info/requires.txt
10
+ pybedrock_net.egg-info/top_level.txt
11
+ pybedrock_net/protocol/__init__.py
12
+ pybedrock_net/protocol/raknet/__init__.py
13
+ pybedrock_net/protocol/raknet/constants.py
14
+ pybedrock_net/protocol/raknet/offline.py
15
+ pybedrock_net/protocol/raknet/packets.py
16
+ pybedrock_net/protocol/raknet/session.py
17
+ pybedrock_net/protocol/raknet/transport.py
18
+ tests/test_offline.py
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ pybedrock-net = pybedrock_net.cli:main
@@ -0,0 +1,3 @@
1
+ build>=1.4.4
2
+ pytest>=8.4.2
3
+ twine>=6.2.0
@@ -0,0 +1 @@
1
+ pybedrock_net
@@ -0,0 +1,35 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "pybedrock-net"
7
+ version = "0.0.1"
8
+ description = "A Python-native RakNet foundation for Minecraft Bedrock protocol experiments."
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ authors = [{ name = "ZENKAI" }]
12
+ keywords = ["minecraft", "bedrock", "raknet", "udp", "protocol", "bot"]
13
+ classifiers = [
14
+ "Development Status :: 2 - Pre-Alpha",
15
+ "Intended Audience :: Developers",
16
+ "Programming Language :: Python :: 3",
17
+ "Programming Language :: Python :: 3 :: Only",
18
+ "Topic :: Internet",
19
+ "Topic :: Software Development :: Libraries :: Python Modules",
20
+ ]
21
+ dependencies = [
22
+ "build>=1.4.4",
23
+ "pytest>=8.4.2",
24
+ "twine>=6.2.0",
25
+ ]
26
+
27
+ [project.scripts]
28
+ pybedrock-net = "pybedrock_net.cli:main"
29
+
30
+ [project.urls]
31
+ Homepage = "https://pypi.org/project/pybedrock-net/"
32
+ YouTube = "https://www.youtube.com/@szewq"
33
+
34
+ [tool.setuptools.packages.find]
35
+ include = ["pybedrock_net*"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,38 @@
1
+ import pytest
2
+
3
+ from pybedrock_net.protocol.raknet.constants import OFFLINE_MAGIC
4
+ from pybedrock_net.protocol.raknet.offline import (
5
+ OpenConnectionReply1,
6
+ build_open_connection_request_1,
7
+ encode_ipv4,
8
+ )
9
+
10
+
11
+ def test_request_one_has_magic_and_requested_mtu():
12
+ packet = build_open_connection_request_1(1492)
13
+ assert packet[0] == 0x05
14
+ assert packet[1:17] == OFFLINE_MAGIC
15
+ assert len(packet) == 1492
16
+
17
+
18
+ def test_ipv4_is_encoded_in_raknet_complement_form():
19
+ assert encode_ipv4("127.0.0.1") == b"\x04\x80\xff\xff\xfe"
20
+
21
+
22
+ def test_reply_one_parses_fields():
23
+ packet = (
24
+ b"\x06"
25
+ + OFFLINE_MAGIC
26
+ + (123).to_bytes(8, "big")
27
+ + b"\x00"
28
+ + (1400).to_bytes(2, "big")
29
+ )
30
+ reply = OpenConnectionReply1(packet)
31
+ assert reply.server_guid == 123
32
+ assert reply.mtu == 1400
33
+ assert reply.security_enabled is False
34
+
35
+
36
+ def test_bad_magic_is_rejected():
37
+ with pytest.raises(ValueError, match="offline magic"):
38
+ OpenConnectionReply1(b"\x06" + b"\x00" * 30)