mcapibridge 0.1.0__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,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 TaotianZhufang
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,280 @@
1
+ Metadata-Version: 2.4
2
+ Name: mcapibridge
3
+ Version: 0.1.0
4
+ Summary: Python libary for MCAPIBridge
5
+ Author: TaotianZhufang
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 TaotianZhufang
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Requires-Python: >=3.7
29
+ Description-Content-Type: text/markdown
30
+ License-File: LICENSE
31
+ Dynamic: license-file
32
+
33
+ # MCAPIBridge Python Libary
34
+
35
+ MCAPIBridge is a mod for Minecraft loaded with Fabric.This libary offers some ways to connect Minecraft with this mod in Python.
36
+
37
+ ## QuickStart
38
+
39
+ ### Install
40
+ Ensure your mod loaded.
41
+
42
+ Put`mc.py`into your project folder or use pip to install this.
43
+ ```
44
+ pip install mcapibridge
45
+ ```
46
+ This is a simple example to connect.
47
+ ```
48
+ from mc import Minecraft
49
+ import time
50
+
51
+ # Default ip is localhost and port is 4711
52
+ # You can use mc = Minecraft(host=YOURIP,port=YOURPORT) to change
53
+ mc = Minecraft()
54
+
55
+ # Show a message
56
+ mc.postToChat("§aHello, Minecraft! Python is here.")
57
+ ```
58
+
59
+ ---
60
+
61
+ ## Usage
62
+
63
+ ### Basic
64
+
65
+ #### `postToChat(msg)`
66
+ Send a message to chat screen.
67
+ * **msg**: String message.Support `§` .You can check it on Minecraft wiki.
68
+
69
+ #### `runCommand(cmd)`
70
+ Run commands as Server.
71
+ * **cmd**: Srting command without '/'
72
+
73
+ Ex: `mc.runCommand("time set day")`
74
+
75
+ ---
76
+
77
+ ### World
78
+
79
+ #### `setBlock(x, y, z, block_id, dimension=None)`
80
+ Set a block at the point given.
81
+ * **x, y, z**: Int positions.
82
+ * **block_id**: String ID.If it is Minecraft vanilla,the ID can be written without `Minecraft:`. Ex:`"stone"`, `"diamond_block"`.Support other namespaces.
83
+ * **dimension**: Optional String target dimension/player name.
84
+
85
+ #### `getBlock(x, y, z, dimension=None)`
86
+ Gets the block ID at the specified coordinates.
87
+ * **x, y, z**: Int positions.
88
+ * **dimension**: Optional String target dimension/player name.
89
+ * **return**: String block ID.Ex.`"minecraft:grass_block"`.
90
+
91
+ #### `spawnEntity(x, y, z, entity_id, yaw=0.0, pitch=0.0, dimension=None)`
92
+ Spawn an entity at the point given.
93
+ * **entity_id**: String ID.If it is Minecraft vanilla,the ID can be written without `Minecraft:`. Ex:`"zombie"`, `"pig"`, `"lightning_bolt"`.Support other namespaces.
94
+ * **yaw**: Optional Int degree.Horizontal degree.
95
+ * **pitch**: Optional Int degree.Vertical degree.
96
+ * **dimension**: Optional String target dimension/player name.
97
+
98
+ #### `setEntityVelocity(entity_id, vx, vy, vz)`
99
+ Sets the velocity of an entity.
100
+ * **entity_id**: Int ID.
101
+ * **vx, vy, vz**: Double velocity components.
102
+
103
+ #### `setEntityNoGravity(entity_id, enable=True)`
104
+ Enables or disables gravity for an entity.
105
+ * **entity_id**: Int ID.
106
+
107
+ #### `getEntities(x, y, z, radius=10, dimension=None)`
108
+ Gets the block ID at the specified coordinates.
109
+ * **x, y, z**: Double positions.
110
+ * **radius**: Double search radius.
111
+ * **dimension**: Optional String target dimension/player name.
112
+ * **return**: List of Dicts: [{'id': 123, 'type': 'minecraft:zombie', 'pos': Vec3}, ...]
113
+
114
+ #### `spawnParticle(x, y, z, particle_id, count=10, dx=0.0, dy=0.0, dz=0.0, speed=0.0, dimension=None)`
115
+ Spawn particle at the point given.
116
+ * **particle_id**: String ID.If it is Minecraft vanilla,the ID can be written without `Minecraft:`. Ex:`"flame"`, `"heart"`.Support other namespaces.
117
+ * **count**: Int count.
118
+ * **dx, dy, dz**: Optional double diffusion ranges.(when count=0, it represents the direction vector)
119
+ * **speed**: Optional double speed.
120
+ * **dimension**: Optional String target dimension/player name.
121
+
122
+ #### `setSign(x, y, z, line1="", line2="", line3="", line4="", dimension=None)`
123
+ Sets the text on a sign block.
124
+ * **x, y, z**: Int positions.
125
+ * **line1-4**: String text for each line.
126
+ * **dimension**: Optional String target dimension/player name.
127
+
128
+ **The block at the position must already be a sign.**
129
+
130
+ ---
131
+
132
+ ### Info
133
+
134
+ #### `getOnlinePlayers()`
135
+ Get players' name online.
136
+ * **return**: Dict: `[{'name': 'Steve', 'id': 123}, ...]`。
137
+
138
+ #### `getPlayerPos(target="")`
139
+ Get player's position and yaw and pitch.
140
+ * **target**: String player name.
141
+ * **return**: Int x,y,z and Double yaw,pitch.
142
+
143
+ #### `getPlayerEntityId(name)`
144
+ Get player's ID.
145
+ * **name**: String player name.
146
+ * **return**: Int ID.
147
+
148
+ #### `getPlayerName(entity_id)`
149
+ Get player's ID.
150
+ * **entity_id**: Int ID.
151
+ * **return**: String player name.
152
+
153
+ #### `getPlayerDetails(target="")`
154
+ Get player's details.
155
+ * **target**: String player name.
156
+ * **return**: Dict including
157
+ * `name`: String player name
158
+ * `id`: Int ID
159
+ * `mode`: String gamemode
160
+ * `health`: Double health
161
+ * `max_health`: Double max health
162
+ * `food`: Int food
163
+ * `held_item`: String item held
164
+ * `held_count`: Int item held count
165
+
166
+ ---
167
+
168
+ ### State
169
+
170
+ #### `setHealth(target, amount)`
171
+ Set player's health.
172
+ * **target**: String player name.
173
+ * **amount**: Double health.
174
+
175
+ #### `setFood(target, amount)`
176
+ Set player's food.
177
+ * **target**: String player name.
178
+ * **amount**: Int food(0-20).
179
+
180
+ #### `giveEffect(target, effect_name, duration_sec=30, amplifier=1)`
181
+ Effect player.
182
+ * **effect_name**: String effect ID.Ex:`"speed"`,`"night_vision"`.
183
+ * **duration_sec**: Int seconds.
184
+ * **amplifier**: Int amplifier.
185
+
186
+ #### `setFlying(target, allow_flight=True, is_flying=True)`
187
+ Enable player to fly in survival mode.
188
+ * **target**: String player name.
189
+
190
+ #### `setFlySpeed(target, speed=0.05)`
191
+ Set flight speed.
192
+ * **target**: String player name.
193
+ * **speed**: Double speed.Default 0.05.
194
+
195
+ #### `setWalkSpeed(target, speed=0.1)`
196
+ Set walk speed.
197
+ * **target**: String player name.
198
+ * **speed**: Double speed.Default 0.1.
199
+
200
+ #### `setGodMode(target, enable=True)`
201
+ Enable invulnerability.
202
+ * **target**: String player name.
203
+
204
+ ---
205
+
206
+ ### Inventory
207
+
208
+ #### `getInventory(target="")`
209
+ Get player's inventory.
210
+ * **return**: List of Dicts.Every dict has `{'slot': block_ID, 'id': item_ID, 'count': item_count}`.
211
+
212
+ #### `give(target, item_id, count=1)`
213
+ Give player item.
214
+ * **item_id**: String item ID.
215
+ * **count**: Int count.
216
+
217
+ #### `clearInventory(target, item_id="")`
218
+ Clear inventory.
219
+ * **target**: String player name.
220
+ * **item_id**: String item ID.
221
+
222
+ ---
223
+
224
+ ### TP
225
+
226
+ #### `teleport(x, y, z, target="")`
227
+ TP player.
228
+ * **x, y, z**: Int target x,y,z.
229
+ * **target**: String player ID.
230
+
231
+ #### `teleportEntity(entity_id, x, y, z)`
232
+ TP entitie.
233
+ * **entity_id**: Int entity id.
234
+
235
+ ---
236
+
237
+ ### Events
238
+
239
+ #### `pollBlockHits()`
240
+ Get click events.
241
+ * **return**: List Class `[BlockHit1,BlockHit2,.....]`
242
+ * **pos**: Class Vec3
243
+ * Double x
244
+ * Double y
245
+ * Double z
246
+ * **face**: Int click face.
247
+ * **entityId**: Int ID of clicking on entity.
248
+ * **action**: Int action type:1--left click,2--right click.(Left click event is only affected by player clicking where which can reach)
249
+ * **type**: String action:"LEFT_CLICK" or "RIGHT_CLICK"
250
+
251
+ #### `pollChatPosts()`
252
+ Get player message events.
253
+ * **return**: List Class `[ChatPost1,ChatPost2,.....]`
254
+ * **name**: String player name.
255
+ * **message**: String message.
256
+
257
+ ---
258
+
259
+ ### Helper Methods
260
+
261
+ #### `getDirectionVector(target="")`
262
+ Calculates the direction vector based on a player's rotation. Useful for shooting projectiles.
263
+ * **target**: String player ID.
264
+ * **return**: Class `Vec3` normalized direction vector.
265
+
266
+ ---
267
+
268
+ ### Helper Classes
269
+
270
+ #### `Vec3`
271
+ Represents a 3D vector/coordinate.
272
+ * **properties**: `x`,`y`,`z`.
273
+ * **Methods**:
274
+ * **length()**: Returns vector length.
275
+
276
+ #### `PlayerPos`
277
+ **Inherits Vec3.**Represents player position with rotation.
278
+ * **properties**: `x`,`y`,`z`,`yaw`,`pitch`.
279
+ * **Methods**:
280
+ * **forward(distance=1.0)**: Returns a new `Vec3` position at `distance` blocks ahead of the player's view.
@@ -0,0 +1,248 @@
1
+ # MCAPIBridge Python Libary
2
+
3
+ MCAPIBridge is a mod for Minecraft loaded with Fabric.This libary offers some ways to connect Minecraft with this mod in Python.
4
+
5
+ ## QuickStart
6
+
7
+ ### Install
8
+ Ensure your mod loaded.
9
+
10
+ Put`mc.py`into your project folder or use pip to install this.
11
+ ```
12
+ pip install mcapibridge
13
+ ```
14
+ This is a simple example to connect.
15
+ ```
16
+ from mc import Minecraft
17
+ import time
18
+
19
+ # Default ip is localhost and port is 4711
20
+ # You can use mc = Minecraft(host=YOURIP,port=YOURPORT) to change
21
+ mc = Minecraft()
22
+
23
+ # Show a message
24
+ mc.postToChat("§aHello, Minecraft! Python is here.")
25
+ ```
26
+
27
+ ---
28
+
29
+ ## Usage
30
+
31
+ ### Basic
32
+
33
+ #### `postToChat(msg)`
34
+ Send a message to chat screen.
35
+ * **msg**: String message.Support `§` .You can check it on Minecraft wiki.
36
+
37
+ #### `runCommand(cmd)`
38
+ Run commands as Server.
39
+ * **cmd**: Srting command without '/'
40
+
41
+ Ex: `mc.runCommand("time set day")`
42
+
43
+ ---
44
+
45
+ ### World
46
+
47
+ #### `setBlock(x, y, z, block_id, dimension=None)`
48
+ Set a block at the point given.
49
+ * **x, y, z**: Int positions.
50
+ * **block_id**: String ID.If it is Minecraft vanilla,the ID can be written without `Minecraft:`. Ex:`"stone"`, `"diamond_block"`.Support other namespaces.
51
+ * **dimension**: Optional String target dimension/player name.
52
+
53
+ #### `getBlock(x, y, z, dimension=None)`
54
+ Gets the block ID at the specified coordinates.
55
+ * **x, y, z**: Int positions.
56
+ * **dimension**: Optional String target dimension/player name.
57
+ * **return**: String block ID.Ex.`"minecraft:grass_block"`.
58
+
59
+ #### `spawnEntity(x, y, z, entity_id, yaw=0.0, pitch=0.0, dimension=None)`
60
+ Spawn an entity at the point given.
61
+ * **entity_id**: String ID.If it is Minecraft vanilla,the ID can be written without `Minecraft:`. Ex:`"zombie"`, `"pig"`, `"lightning_bolt"`.Support other namespaces.
62
+ * **yaw**: Optional Int degree.Horizontal degree.
63
+ * **pitch**: Optional Int degree.Vertical degree.
64
+ * **dimension**: Optional String target dimension/player name.
65
+
66
+ #### `setEntityVelocity(entity_id, vx, vy, vz)`
67
+ Sets the velocity of an entity.
68
+ * **entity_id**: Int ID.
69
+ * **vx, vy, vz**: Double velocity components.
70
+
71
+ #### `setEntityNoGravity(entity_id, enable=True)`
72
+ Enables or disables gravity for an entity.
73
+ * **entity_id**: Int ID.
74
+
75
+ #### `getEntities(x, y, z, radius=10, dimension=None)`
76
+ Gets the block ID at the specified coordinates.
77
+ * **x, y, z**: Double positions.
78
+ * **radius**: Double search radius.
79
+ * **dimension**: Optional String target dimension/player name.
80
+ * **return**: List of Dicts: [{'id': 123, 'type': 'minecraft:zombie', 'pos': Vec3}, ...]
81
+
82
+ #### `spawnParticle(x, y, z, particle_id, count=10, dx=0.0, dy=0.0, dz=0.0, speed=0.0, dimension=None)`
83
+ Spawn particle at the point given.
84
+ * **particle_id**: String ID.If it is Minecraft vanilla,the ID can be written without `Minecraft:`. Ex:`"flame"`, `"heart"`.Support other namespaces.
85
+ * **count**: Int count.
86
+ * **dx, dy, dz**: Optional double diffusion ranges.(when count=0, it represents the direction vector)
87
+ * **speed**: Optional double speed.
88
+ * **dimension**: Optional String target dimension/player name.
89
+
90
+ #### `setSign(x, y, z, line1="", line2="", line3="", line4="", dimension=None)`
91
+ Sets the text on a sign block.
92
+ * **x, y, z**: Int positions.
93
+ * **line1-4**: String text for each line.
94
+ * **dimension**: Optional String target dimension/player name.
95
+
96
+ **The block at the position must already be a sign.**
97
+
98
+ ---
99
+
100
+ ### Info
101
+
102
+ #### `getOnlinePlayers()`
103
+ Get players' name online.
104
+ * **return**: Dict: `[{'name': 'Steve', 'id': 123}, ...]`。
105
+
106
+ #### `getPlayerPos(target="")`
107
+ Get player's position and yaw and pitch.
108
+ * **target**: String player name.
109
+ * **return**: Int x,y,z and Double yaw,pitch.
110
+
111
+ #### `getPlayerEntityId(name)`
112
+ Get player's ID.
113
+ * **name**: String player name.
114
+ * **return**: Int ID.
115
+
116
+ #### `getPlayerName(entity_id)`
117
+ Get player's ID.
118
+ * **entity_id**: Int ID.
119
+ * **return**: String player name.
120
+
121
+ #### `getPlayerDetails(target="")`
122
+ Get player's details.
123
+ * **target**: String player name.
124
+ * **return**: Dict including
125
+ * `name`: String player name
126
+ * `id`: Int ID
127
+ * `mode`: String gamemode
128
+ * `health`: Double health
129
+ * `max_health`: Double max health
130
+ * `food`: Int food
131
+ * `held_item`: String item held
132
+ * `held_count`: Int item held count
133
+
134
+ ---
135
+
136
+ ### State
137
+
138
+ #### `setHealth(target, amount)`
139
+ Set player's health.
140
+ * **target**: String player name.
141
+ * **amount**: Double health.
142
+
143
+ #### `setFood(target, amount)`
144
+ Set player's food.
145
+ * **target**: String player name.
146
+ * **amount**: Int food(0-20).
147
+
148
+ #### `giveEffect(target, effect_name, duration_sec=30, amplifier=1)`
149
+ Effect player.
150
+ * **effect_name**: String effect ID.Ex:`"speed"`,`"night_vision"`.
151
+ * **duration_sec**: Int seconds.
152
+ * **amplifier**: Int amplifier.
153
+
154
+ #### `setFlying(target, allow_flight=True, is_flying=True)`
155
+ Enable player to fly in survival mode.
156
+ * **target**: String player name.
157
+
158
+ #### `setFlySpeed(target, speed=0.05)`
159
+ Set flight speed.
160
+ * **target**: String player name.
161
+ * **speed**: Double speed.Default 0.05.
162
+
163
+ #### `setWalkSpeed(target, speed=0.1)`
164
+ Set walk speed.
165
+ * **target**: String player name.
166
+ * **speed**: Double speed.Default 0.1.
167
+
168
+ #### `setGodMode(target, enable=True)`
169
+ Enable invulnerability.
170
+ * **target**: String player name.
171
+
172
+ ---
173
+
174
+ ### Inventory
175
+
176
+ #### `getInventory(target="")`
177
+ Get player's inventory.
178
+ * **return**: List of Dicts.Every dict has `{'slot': block_ID, 'id': item_ID, 'count': item_count}`.
179
+
180
+ #### `give(target, item_id, count=1)`
181
+ Give player item.
182
+ * **item_id**: String item ID.
183
+ * **count**: Int count.
184
+
185
+ #### `clearInventory(target, item_id="")`
186
+ Clear inventory.
187
+ * **target**: String player name.
188
+ * **item_id**: String item ID.
189
+
190
+ ---
191
+
192
+ ### TP
193
+
194
+ #### `teleport(x, y, z, target="")`
195
+ TP player.
196
+ * **x, y, z**: Int target x,y,z.
197
+ * **target**: String player ID.
198
+
199
+ #### `teleportEntity(entity_id, x, y, z)`
200
+ TP entitie.
201
+ * **entity_id**: Int entity id.
202
+
203
+ ---
204
+
205
+ ### Events
206
+
207
+ #### `pollBlockHits()`
208
+ Get click events.
209
+ * **return**: List Class `[BlockHit1,BlockHit2,.....]`
210
+ * **pos**: Class Vec3
211
+ * Double x
212
+ * Double y
213
+ * Double z
214
+ * **face**: Int click face.
215
+ * **entityId**: Int ID of clicking on entity.
216
+ * **action**: Int action type:1--left click,2--right click.(Left click event is only affected by player clicking where which can reach)
217
+ * **type**: String action:"LEFT_CLICK" or "RIGHT_CLICK"
218
+
219
+ #### `pollChatPosts()`
220
+ Get player message events.
221
+ * **return**: List Class `[ChatPost1,ChatPost2,.....]`
222
+ * **name**: String player name.
223
+ * **message**: String message.
224
+
225
+ ---
226
+
227
+ ### Helper Methods
228
+
229
+ #### `getDirectionVector(target="")`
230
+ Calculates the direction vector based on a player's rotation. Useful for shooting projectiles.
231
+ * **target**: String player ID.
232
+ * **return**: Class `Vec3` normalized direction vector.
233
+
234
+ ---
235
+
236
+ ### Helper Classes
237
+
238
+ #### `Vec3`
239
+ Represents a 3D vector/coordinate.
240
+ * **properties**: `x`,`y`,`z`.
241
+ * **Methods**:
242
+ * **length()**: Returns vector length.
243
+
244
+ #### `PlayerPos`
245
+ **Inherits Vec3.**Represents player position with rotation.
246
+ * **properties**: `x`,`y`,`z`,`yaw`,`pitch`.
247
+ * **Methods**:
248
+ * **forward(distance=1.0)**: Returns a new `Vec3` position at `distance` blocks ahead of the player's view.
@@ -0,0 +1,21 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "mcapibridge"
7
+ version = "0.1.0"
8
+ description = "Python libary for MCAPIBridge"
9
+ requires-python = ">=3.7"
10
+ license = { file = "LICENSE" }
11
+ readme = "README.MD"
12
+ authors = [
13
+ { name = "TaotianZhufang" }
14
+ ]
15
+
16
+ [tool.setuptools]
17
+ package-dir = {"" = "src"}
18
+
19
+ [tool.setuptools.packages.find]
20
+ where = ["src"]
21
+
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,9 @@
1
+ from .minecraft import Minecraft, Vec3, PlayerPos, BlockHit, ChatPost
2
+
3
+ __all__ = [
4
+ "Minecraft",
5
+ "Vec3",
6
+ "PlayerPos",
7
+ "BlockHit",
8
+ "ChatPost",
9
+ ]
@@ -0,0 +1,342 @@
1
+ import socket
2
+ import math
3
+ import time
4
+
5
+ class Vec3:
6
+ def __init__(self, x, y, z):
7
+ self.x, self.y, self.z = x, y, z
8
+ def __repr__(self): return f"Vec3({self.x:.2f}, {self.y:.2f}, {self.z:.2f})"
9
+ def __sub__(self, o): return Vec3(self.x-o.x, self.y-o.y, self.z-o.z)
10
+ def length(self): return math.sqrt(self.x**2 + self.y**2 + self.z**2)
11
+
12
+ class PlayerPos(Vec3):
13
+ def __init__(self, x, y, z, yaw, pitch):
14
+ super().__init__(x, y, z)
15
+ self.yaw = yaw
16
+ self.pitch = pitch
17
+
18
+ def __repr__(self):
19
+ return f"PlayerPos(x={self.x:.1f}, y={self.y:.1f}, z={self.z:.1f}, yaw={self.yaw:.1f}, pitch={self.pitch:.1f})"
20
+
21
+ def forward(self, distance=1.0):
22
+ yaw_rad = math.radians(self.yaw)
23
+ pitch_rad = math.radians(self.pitch)
24
+
25
+ vx = -math.sin(yaw_rad) * math.cos(pitch_rad)
26
+ vy = -math.sin(pitch_rad)
27
+ vz = math.cos(yaw_rad) * math.cos(pitch_rad)
28
+
29
+ return Vec3(self.x + vx * distance, self.y + vy * distance, self.z + vz * distance)
30
+
31
+ class ChatPost:
32
+ def __init__(self, name, message):
33
+ self.name = name
34
+ self.message = message
35
+
36
+ def __repr__(self):
37
+ return f"[{self.name}]: {self.message}"
38
+
39
+ class BlockHit:
40
+ def __init__(self, x, y, z, face, entityId, action):
41
+ self.pos = Vec3(x, y, z)
42
+ self.face = face
43
+ self.entityId = entityId
44
+ self.action = action # 1=Left, 2=Right
45
+ self.type = "RIGHT_CLICK" if action == 2 else "LEFT_CLICK"
46
+
47
+ class Minecraft:
48
+ def __init__(self, host="localhost", port=4711):
49
+ self.host = host
50
+ self.port = port
51
+ self.socket = None
52
+ self.file_reader = None
53
+ self.connected = False
54
+ self._connect()
55
+
56
+ def _connect(self):
57
+ try:
58
+ if self.socket:
59
+ try: self.socket.close()
60
+ except: pass
61
+
62
+ self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
63
+ self.socket.settimeout(5)
64
+ self.socket.connect((self.host, self.port))
65
+
66
+ self.file_reader = self.socket.makefile('r', encoding='utf-8')
67
+ self.connected = True
68
+ print(f"[MCAPI] Connected ({self.host}:{self.port}).")
69
+ return True
70
+ except (ConnectionRefusedError, socket.timeout):
71
+ print("[MCAPI] Lost connection.Retry...")
72
+ self.connected = False
73
+ return False
74
+
75
+ def _send(self, cmd):
76
+ try:
77
+ if not self.connected:
78
+ if not self._connect(): return
79
+
80
+ self.socket.sendall((cmd + "\n").encode("utf-8"))
81
+ except (BrokenPipeError, ConnectionResetError, socket.timeout, OSError):
82
+ print("[MCAPI] Lost connection.Retry...")
83
+ if self._connect():
84
+ try:
85
+ self.socket.sendall((cmd + "\n").encode("utf-8"))
86
+ except:
87
+ print("[MCAPI] Retry failed.")
88
+
89
+ def _recv(self):
90
+ if not self.connected: return ""
91
+ try:
92
+ line = self.file_reader.readline()
93
+ if not line:
94
+ print("[MCAPI] Retry.")
95
+ self.connected = False
96
+ for i in range(3):
97
+ time.sleep(1)
98
+ if self._connect():
99
+ return self._recv()
100
+ return ""
101
+ return line.strip()
102
+ except (socket.timeout, OSError):
103
+ return ""
104
+
105
+ def postToChat(self, msg):
106
+ self._send(f"chat.post({msg})")
107
+
108
+ def runCommand(self, cmd):
109
+ if cmd.startswith("/"): cmd = cmd[1:]
110
+ self._send(f"server.runCommand({cmd})")
111
+
112
+ def setBlock(self, x, y, z, block_id, dimension=None):
113
+ if dimension:
114
+ self._send(f"world.setBlock({int(x)},{int(y)},{int(z)},{block_id},{dimension})")
115
+ else:
116
+ self._send(f"world.setBlock({int(x)},{int(y)},{int(z)},{block_id})")
117
+
118
+ def spawnEntity(self, x, y, z, entity_id, yaw=0.0, pitch=0.0, dimension=None):
119
+ if dimension:
120
+ self._send(f"world.spawnEntity({x},{y},{z},{entity_id},{yaw},{pitch},{dimension})")
121
+ else:
122
+ self._send(f"world.spawnEntity({x},{y},{z},{entity_id},{yaw},{pitch})")
123
+
124
+ return int(self._recv())
125
+
126
+ def spawnParticle(self, x, y, z, particle_id, count=10, dx=0.0, dy=0.0, dz=0.0, speed=0.0, dimension=None):
127
+ cmd = f"{x},{y},{z},{particle_id},{count},{dx},{dy},{dz},{speed}"
128
+ if dimension:
129
+ cmd += f",{dimension}"
130
+ self._send(f"world.spawnParticle({cmd})")
131
+
132
+ def setEntityVelocity(self, entity_id, vx, vy, vz):
133
+ self._send(f"entity.setVelocity({entity_id},{vx},{vy},{vz})")
134
+
135
+ def getDirectionVector(self,target=""):
136
+ pos = self.getPlayerPos(target=target)
137
+
138
+ self._send("player.getPos()")
139
+ data = self._recv().split(",")
140
+ if len(data) < 5: return Vec3(0,0,1)
141
+
142
+ yaw = float(data[3])
143
+ pitch = float(data[4])
144
+
145
+ yaw_rad = math.radians(yaw)
146
+ pitch_rad = math.radians(pitch)
147
+
148
+ vx = -math.sin(yaw_rad) * math.cos(pitch_rad)
149
+ vy = -math.sin(pitch_rad)
150
+ vz = math.cos(yaw_rad) * math.cos(pitch_rad)
151
+
152
+ return Vec3(vx, vy, vz)
153
+
154
+ def setEntityNoGravity(self, entity_id, enable=True):
155
+ val = "true" if enable else "false"
156
+ self._send(f"entity.setNoGravity({entity_id},{val})")
157
+
158
+ def getPlayerPos(self, target=""):
159
+ self._send(f"player.getPos({target})")
160
+ data = self._recv()
161
+ if not data: return PlayerPos(0,0,0,0,0)
162
+ # x, y, z, yaw, pitch
163
+ parts = data.split(",")
164
+ if len(parts) >= 5:
165
+ return PlayerPos(
166
+ float(parts[0]), float(parts[1]), float(parts[2]),
167
+ float(parts[3]), float(parts[4])
168
+ )
169
+ return PlayerPos(0,0,0,0,0)
170
+
171
+ def getOnlinePlayers(self):
172
+ self._send("world.getPlayers()")
173
+ d = self._recv()
174
+ if not d: return []
175
+ players = []
176
+ for item in d.split("|"):
177
+ parts = item.split(",")
178
+ if len(parts) == 2:
179
+ players.append({"name": parts[0], "id": int(parts[1])})
180
+ return players
181
+
182
+ def getPlayerDetails(self, target=""):
183
+ self._send(f"player.getDetails({target})")
184
+ d = self._recv()
185
+ if not d or "Error" in d: return None
186
+ p = d.split(",")
187
+ # Name,ID,Mode,HP,MaxHP,Food,HeldItem,Count
188
+ return {
189
+ "name": p[0],
190
+ "id": int(p[1]),
191
+ "mode": p[2],
192
+ "health": float(p[3]),
193
+ "max_health": float(p[4]),
194
+ "food": int(p[5]),
195
+ "held_item": p[6],
196
+ "held_count": int(p[7])
197
+ }
198
+
199
+ def getPlayerEntityId(self, name):
200
+ players = self.getOnlinePlayers()
201
+ for p in players:
202
+ if p['name'] == name:
203
+ return p['id']
204
+ return None
205
+
206
+ def getPlayerName(self, entity_id):
207
+ players = self.getOnlinePlayers()
208
+ for p in players:
209
+ if p['id'] == entity_id:
210
+ return p['name']
211
+ return None
212
+
213
+ def getInventory(self, target=""):
214
+ self._send(f"player.getInventory({target})")
215
+ d = self._recv()
216
+
217
+ if not d or "EMPTY" in d or "ERROR" in d: return []
218
+
219
+ items = []
220
+ for item_str in d.split("|"):
221
+ parts = item_str.split(":")
222
+ if len(parts) == 3:
223
+ items.append({
224
+ "slot": int(parts[0]),
225
+ "id": parts[1],
226
+ "count": int(parts[2])
227
+ })
228
+ elif len(parts) == 4:
229
+ items.append({
230
+ "slot": int(parts[0]),
231
+ "id": f"{parts[1]}:{parts[2]}",
232
+ "count": int(parts[3])
233
+ })
234
+ return items
235
+
236
+ def setHealth(self, target, amount):
237
+ self._send(f"player.setHealth({target},{amount})")
238
+
239
+ def setFood(self, target, amount):
240
+ self._send(f"player.setFood({target},{amount})")
241
+
242
+ def give(self, target, item_id, count=1):
243
+ self._send(f"player.give({target},{item_id},{count})")
244
+
245
+ def clearInventory(self, target, item_id=""):
246
+ self._send(f"player.clear({target},{item_id})")
247
+
248
+ def giveEffect(self, target, effect_name, duration_sec=30, amplifier=1):
249
+ self._send(f"player.effect({target},{effect_name},{duration_sec},{amplifier})")
250
+
251
+ def teleport(self, x, y, z, target=""):
252
+ if target:
253
+ self._send(f"player.teleport({target},{x},{y},{z})")
254
+ else:
255
+ self._send(f"player.teleport({x},{y},{z})")
256
+
257
+ def teleportEntity(self, entity_id, x, y, z):
258
+ self._send(f"entity.teleport({entity_id},{x},{y},{z})")
259
+
260
+ def pollBlockHits(self):
261
+ self._send("events.block.hits()")
262
+ d = self._recv()
263
+ hits = []
264
+ if not d: return hits
265
+ for item in d.split("|"):
266
+ p = item.split(",")
267
+ if len(p) >= 6:
268
+ hits.append(BlockHit(
269
+ int(p[0]), int(p[1]), int(p[2]),
270
+ int(p[3]), int(p[4]), int(p[5])
271
+ ))
272
+ return hits
273
+
274
+ def pollChatPosts(self):
275
+ """
276
+ [ChatPost(name='Steve', message='Hello'), ...]
277
+ """
278
+ self._send("events.chat.posts()")
279
+ data = self._recv()
280
+ posts = []
281
+ if not data: return posts
282
+
283
+ for item in data.split("|"):
284
+ parts = item.split(",", 1)
285
+ if len(parts) == 2:
286
+ posts.append(ChatPost(parts[0], parts[1]))
287
+ return posts
288
+
289
+ def setFlying(self, target, allow_flight=True, is_flying=True):
290
+ a = "true" if allow_flight else "false"
291
+ f = "true" if is_flying else "false"
292
+ self._send(f"player.setFlying({target},{a},{f})")
293
+
294
+ def setFlySpeed(self, target, speed=0.05):
295
+ # Default speed:0.05
296
+ self._send(f"player.setSpeed({target},true,{speed})")
297
+
298
+ def setWalkSpeed(self, target, speed=0.1):
299
+ # Default speed:0.1
300
+ self._send(f"player.setSpeed({target},false,{speed})")
301
+
302
+ def setGodMode(self, target, enable=True):
303
+ val = "true" if enable else "false"
304
+ self._send(f"player.setGod({target},{val})")
305
+
306
+ def getBlock(self, x, y, z, dimension=None):
307
+ cmd = f"world.getBlock({int(x)},{int(y)},{int(z)})"
308
+ if dimension: cmd = f"world.getBlock({int(x)},{int(y)},{int(z)},{dimension})"
309
+ self._send(cmd)
310
+ return self._recv()
311
+
312
+ def getEntities(self, x, y, z, radius=10, dimension=None):
313
+ """
314
+ [{'id': 123, 'type': 'zombie', 'pos': Vec3}, ...]
315
+ """
316
+ cmd = f"world.getEntities({x},{y},{z},{radius})"
317
+ if dimension: cmd = f"world.getEntities({x},{y},{z},{radius},{dimension})"
318
+ self._send(cmd)
319
+ data = self._recv()
320
+ if not data: return []
321
+
322
+ entities = []
323
+ for item in data.split("|"):
324
+ # ID,Type,X,Y,Z
325
+ p = item.split(",")
326
+ if len(p) >= 5:
327
+ entities.append({
328
+ "id": int(p[0]),
329
+ "type": p[1],
330
+ "pos": Vec3(float(p[2]), float(p[3]), float(p[4]))
331
+ })
332
+ return entities
333
+
334
+ def setSign(self, x, y, z, line1="", line2="", line3="", line4="", dimension=None):
335
+ l1 = line1.replace(",", ",")
336
+ l2 = line2.replace(",", ",")
337
+ l3 = line3.replace(",", ",")
338
+ l4 = line4.replace(",", ",")
339
+
340
+ cmd = f"world.setSign({int(x)},{int(y)},{int(z)},{l1},{l2},{l3},{l4})"
341
+ if dimension: cmd += f",{dimension}"
342
+ self._send(cmd)
@@ -0,0 +1,280 @@
1
+ Metadata-Version: 2.4
2
+ Name: mcapibridge
3
+ Version: 0.1.0
4
+ Summary: Python libary for MCAPIBridge
5
+ Author: TaotianZhufang
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 TaotianZhufang
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Requires-Python: >=3.7
29
+ Description-Content-Type: text/markdown
30
+ License-File: LICENSE
31
+ Dynamic: license-file
32
+
33
+ # MCAPIBridge Python Libary
34
+
35
+ MCAPIBridge is a mod for Minecraft loaded with Fabric.This libary offers some ways to connect Minecraft with this mod in Python.
36
+
37
+ ## QuickStart
38
+
39
+ ### Install
40
+ Ensure your mod loaded.
41
+
42
+ Put`mc.py`into your project folder or use pip to install this.
43
+ ```
44
+ pip install mcapibridge
45
+ ```
46
+ This is a simple example to connect.
47
+ ```
48
+ from mc import Minecraft
49
+ import time
50
+
51
+ # Default ip is localhost and port is 4711
52
+ # You can use mc = Minecraft(host=YOURIP,port=YOURPORT) to change
53
+ mc = Minecraft()
54
+
55
+ # Show a message
56
+ mc.postToChat("§aHello, Minecraft! Python is here.")
57
+ ```
58
+
59
+ ---
60
+
61
+ ## Usage
62
+
63
+ ### Basic
64
+
65
+ #### `postToChat(msg)`
66
+ Send a message to chat screen.
67
+ * **msg**: String message.Support `§` .You can check it on Minecraft wiki.
68
+
69
+ #### `runCommand(cmd)`
70
+ Run commands as Server.
71
+ * **cmd**: Srting command without '/'
72
+
73
+ Ex: `mc.runCommand("time set day")`
74
+
75
+ ---
76
+
77
+ ### World
78
+
79
+ #### `setBlock(x, y, z, block_id, dimension=None)`
80
+ Set a block at the point given.
81
+ * **x, y, z**: Int positions.
82
+ * **block_id**: String ID.If it is Minecraft vanilla,the ID can be written without `Minecraft:`. Ex:`"stone"`, `"diamond_block"`.Support other namespaces.
83
+ * **dimension**: Optional String target dimension/player name.
84
+
85
+ #### `getBlock(x, y, z, dimension=None)`
86
+ Gets the block ID at the specified coordinates.
87
+ * **x, y, z**: Int positions.
88
+ * **dimension**: Optional String target dimension/player name.
89
+ * **return**: String block ID.Ex.`"minecraft:grass_block"`.
90
+
91
+ #### `spawnEntity(x, y, z, entity_id, yaw=0.0, pitch=0.0, dimension=None)`
92
+ Spawn an entity at the point given.
93
+ * **entity_id**: String ID.If it is Minecraft vanilla,the ID can be written without `Minecraft:`. Ex:`"zombie"`, `"pig"`, `"lightning_bolt"`.Support other namespaces.
94
+ * **yaw**: Optional Int degree.Horizontal degree.
95
+ * **pitch**: Optional Int degree.Vertical degree.
96
+ * **dimension**: Optional String target dimension/player name.
97
+
98
+ #### `setEntityVelocity(entity_id, vx, vy, vz)`
99
+ Sets the velocity of an entity.
100
+ * **entity_id**: Int ID.
101
+ * **vx, vy, vz**: Double velocity components.
102
+
103
+ #### `setEntityNoGravity(entity_id, enable=True)`
104
+ Enables or disables gravity for an entity.
105
+ * **entity_id**: Int ID.
106
+
107
+ #### `getEntities(x, y, z, radius=10, dimension=None)`
108
+ Gets the block ID at the specified coordinates.
109
+ * **x, y, z**: Double positions.
110
+ * **radius**: Double search radius.
111
+ * **dimension**: Optional String target dimension/player name.
112
+ * **return**: List of Dicts: [{'id': 123, 'type': 'minecraft:zombie', 'pos': Vec3}, ...]
113
+
114
+ #### `spawnParticle(x, y, z, particle_id, count=10, dx=0.0, dy=0.0, dz=0.0, speed=0.0, dimension=None)`
115
+ Spawn particle at the point given.
116
+ * **particle_id**: String ID.If it is Minecraft vanilla,the ID can be written without `Minecraft:`. Ex:`"flame"`, `"heart"`.Support other namespaces.
117
+ * **count**: Int count.
118
+ * **dx, dy, dz**: Optional double diffusion ranges.(when count=0, it represents the direction vector)
119
+ * **speed**: Optional double speed.
120
+ * **dimension**: Optional String target dimension/player name.
121
+
122
+ #### `setSign(x, y, z, line1="", line2="", line3="", line4="", dimension=None)`
123
+ Sets the text on a sign block.
124
+ * **x, y, z**: Int positions.
125
+ * **line1-4**: String text for each line.
126
+ * **dimension**: Optional String target dimension/player name.
127
+
128
+ **The block at the position must already be a sign.**
129
+
130
+ ---
131
+
132
+ ### Info
133
+
134
+ #### `getOnlinePlayers()`
135
+ Get players' name online.
136
+ * **return**: Dict: `[{'name': 'Steve', 'id': 123}, ...]`。
137
+
138
+ #### `getPlayerPos(target="")`
139
+ Get player's position and yaw and pitch.
140
+ * **target**: String player name.
141
+ * **return**: Int x,y,z and Double yaw,pitch.
142
+
143
+ #### `getPlayerEntityId(name)`
144
+ Get player's ID.
145
+ * **name**: String player name.
146
+ * **return**: Int ID.
147
+
148
+ #### `getPlayerName(entity_id)`
149
+ Get player's ID.
150
+ * **entity_id**: Int ID.
151
+ * **return**: String player name.
152
+
153
+ #### `getPlayerDetails(target="")`
154
+ Get player's details.
155
+ * **target**: String player name.
156
+ * **return**: Dict including
157
+ * `name`: String player name
158
+ * `id`: Int ID
159
+ * `mode`: String gamemode
160
+ * `health`: Double health
161
+ * `max_health`: Double max health
162
+ * `food`: Int food
163
+ * `held_item`: String item held
164
+ * `held_count`: Int item held count
165
+
166
+ ---
167
+
168
+ ### State
169
+
170
+ #### `setHealth(target, amount)`
171
+ Set player's health.
172
+ * **target**: String player name.
173
+ * **amount**: Double health.
174
+
175
+ #### `setFood(target, amount)`
176
+ Set player's food.
177
+ * **target**: String player name.
178
+ * **amount**: Int food(0-20).
179
+
180
+ #### `giveEffect(target, effect_name, duration_sec=30, amplifier=1)`
181
+ Effect player.
182
+ * **effect_name**: String effect ID.Ex:`"speed"`,`"night_vision"`.
183
+ * **duration_sec**: Int seconds.
184
+ * **amplifier**: Int amplifier.
185
+
186
+ #### `setFlying(target, allow_flight=True, is_flying=True)`
187
+ Enable player to fly in survival mode.
188
+ * **target**: String player name.
189
+
190
+ #### `setFlySpeed(target, speed=0.05)`
191
+ Set flight speed.
192
+ * **target**: String player name.
193
+ * **speed**: Double speed.Default 0.05.
194
+
195
+ #### `setWalkSpeed(target, speed=0.1)`
196
+ Set walk speed.
197
+ * **target**: String player name.
198
+ * **speed**: Double speed.Default 0.1.
199
+
200
+ #### `setGodMode(target, enable=True)`
201
+ Enable invulnerability.
202
+ * **target**: String player name.
203
+
204
+ ---
205
+
206
+ ### Inventory
207
+
208
+ #### `getInventory(target="")`
209
+ Get player's inventory.
210
+ * **return**: List of Dicts.Every dict has `{'slot': block_ID, 'id': item_ID, 'count': item_count}`.
211
+
212
+ #### `give(target, item_id, count=1)`
213
+ Give player item.
214
+ * **item_id**: String item ID.
215
+ * **count**: Int count.
216
+
217
+ #### `clearInventory(target, item_id="")`
218
+ Clear inventory.
219
+ * **target**: String player name.
220
+ * **item_id**: String item ID.
221
+
222
+ ---
223
+
224
+ ### TP
225
+
226
+ #### `teleport(x, y, z, target="")`
227
+ TP player.
228
+ * **x, y, z**: Int target x,y,z.
229
+ * **target**: String player ID.
230
+
231
+ #### `teleportEntity(entity_id, x, y, z)`
232
+ TP entitie.
233
+ * **entity_id**: Int entity id.
234
+
235
+ ---
236
+
237
+ ### Events
238
+
239
+ #### `pollBlockHits()`
240
+ Get click events.
241
+ * **return**: List Class `[BlockHit1,BlockHit2,.....]`
242
+ * **pos**: Class Vec3
243
+ * Double x
244
+ * Double y
245
+ * Double z
246
+ * **face**: Int click face.
247
+ * **entityId**: Int ID of clicking on entity.
248
+ * **action**: Int action type:1--left click,2--right click.(Left click event is only affected by player clicking where which can reach)
249
+ * **type**: String action:"LEFT_CLICK" or "RIGHT_CLICK"
250
+
251
+ #### `pollChatPosts()`
252
+ Get player message events.
253
+ * **return**: List Class `[ChatPost1,ChatPost2,.....]`
254
+ * **name**: String player name.
255
+ * **message**: String message.
256
+
257
+ ---
258
+
259
+ ### Helper Methods
260
+
261
+ #### `getDirectionVector(target="")`
262
+ Calculates the direction vector based on a player's rotation. Useful for shooting projectiles.
263
+ * **target**: String player ID.
264
+ * **return**: Class `Vec3` normalized direction vector.
265
+
266
+ ---
267
+
268
+ ### Helper Classes
269
+
270
+ #### `Vec3`
271
+ Represents a 3D vector/coordinate.
272
+ * **properties**: `x`,`y`,`z`.
273
+ * **Methods**:
274
+ * **length()**: Returns vector length.
275
+
276
+ #### `PlayerPos`
277
+ **Inherits Vec3.**Represents player position with rotation.
278
+ * **properties**: `x`,`y`,`z`,`yaw`,`pitch`.
279
+ * **Methods**:
280
+ * **forward(distance=1.0)**: Returns a new `Vec3` position at `distance` blocks ahead of the player's view.
@@ -0,0 +1,9 @@
1
+ LICENSE
2
+ README.MD
3
+ pyproject.toml
4
+ src/mc/__init__.py
5
+ src/mc/minecraft.py
6
+ src/mcapibridge.egg-info/PKG-INFO
7
+ src/mcapibridge.egg-info/SOURCES.txt
8
+ src/mcapibridge.egg-info/dependency_links.txt
9
+ src/mcapibridge.egg-info/top_level.txt