pumpkin-api-py 0.1.0.dev0__py3-none-any.whl
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.
- pumpkin_api/__init__.py +139 -0
- pumpkin_api/app.py +8 -0
- pumpkin_api/build.py +35 -0
- pumpkin_api/wit/componentize_py_async_support/__init__.py +529 -0
- pumpkin_api/wit/componentize_py_async_support/futures.py +93 -0
- pumpkin_api/wit/componentize_py_async_support/streams.py +189 -0
- pumpkin_api/wit/componentize_py_runtime.pyi +34 -0
- pumpkin_api/wit/componentize_py_types.py +19 -0
- pumpkin_api/wit/poll_loop.py +440 -0
- pumpkin_api/wit/wit_world/__init__.py +70 -0
- pumpkin_api/wit/wit_world/exports/__init__.py +19 -0
- pumpkin_api/wit/wit_world/exports/metadata.py +22 -0
- pumpkin_api/wit/wit_world/imports/__init__.py +0 -0
- pumpkin_api/wit/wit_world/imports/command.py +539 -0
- pumpkin_api/wit/wit_world/imports/common.py +213 -0
- pumpkin_api/wit/wit_world/imports/context.py +70 -0
- pumpkin_api/wit/wit_world/imports/entity.py +84 -0
- pumpkin_api/wit/wit_world/imports/event.py +434 -0
- pumpkin_api/wit/wit_world/imports/gui.py +61 -0
- pumpkin_api/wit/wit_world/imports/i18n.py +35 -0
- pumpkin_api/wit/wit_world/imports/logging.py +30 -0
- pumpkin_api/wit/wit_world/imports/permission.py +71 -0
- pumpkin_api/wit/wit_world/imports/player.py +350 -0
- pumpkin_api/wit/wit_world/imports/scheduler.py +44 -0
- pumpkin_api/wit/wit_world/imports/scoreboard.py +95 -0
- pumpkin_api/wit/wit_world/imports/server.py +75 -0
- pumpkin_api/wit/wit_world/imports/text.py +89 -0
- pumpkin_api/wit/wit_world/imports/world.py +215 -0
- pumpkin_api/wit_files/command.wit +189 -0
- pumpkin_api/wit_files/common.wit +201 -0
- pumpkin_api/wit_files/componentize_py_async_support/__init__.py +529 -0
- pumpkin_api/wit_files/componentize_py_async_support/futures.py +93 -0
- pumpkin_api/wit_files/componentize_py_async_support/streams.py +189 -0
- pumpkin_api/wit_files/componentize_py_runtime.pyi +34 -0
- pumpkin_api/wit_files/componentize_py_types.py +19 -0
- pumpkin_api/wit_files/context.wit +33 -0
- pumpkin_api/wit_files/entity.wit +36 -0
- pumpkin_api/wit_files/event.wit +311 -0
- pumpkin_api/wit_files/gui.wit +38 -0
- pumpkin_api/wit_files/i18n.wit +21 -0
- pumpkin_api/wit_files/log.wit +14 -0
- pumpkin_api/wit_files/metadata.wit +15 -0
- pumpkin_api/wit_files/permission.wit +46 -0
- pumpkin_api/wit_files/player.wit +172 -0
- pumpkin_api/wit_files/plugin.wit +61 -0
- pumpkin_api/wit_files/poll_loop.py +440 -0
- pumpkin_api/wit_files/scheduler.wit +24 -0
- pumpkin_api/wit_files/scoreboard.wit +72 -0
- pumpkin_api/wit_files/server.wit +41 -0
- pumpkin_api/wit_files/text.wit +41 -0
- pumpkin_api/wit_files/wit_world/__init__.py +70 -0
- pumpkin_api/wit_files/wit_world/exports/__init__.py +19 -0
- pumpkin_api/wit_files/wit_world/exports/metadata.py +22 -0
- pumpkin_api/wit_files/wit_world/imports/__init__.py +0 -0
- pumpkin_api/wit_files/wit_world/imports/command.py +539 -0
- pumpkin_api/wit_files/wit_world/imports/common.py +213 -0
- pumpkin_api/wit_files/wit_world/imports/context.py +70 -0
- pumpkin_api/wit_files/wit_world/imports/entity.py +84 -0
- pumpkin_api/wit_files/wit_world/imports/event.py +434 -0
- pumpkin_api/wit_files/wit_world/imports/gui.py +61 -0
- pumpkin_api/wit_files/wit_world/imports/i18n.py +35 -0
- pumpkin_api/wit_files/wit_world/imports/logging.py +30 -0
- pumpkin_api/wit_files/wit_world/imports/permission.py +71 -0
- pumpkin_api/wit_files/wit_world/imports/player.py +350 -0
- pumpkin_api/wit_files/wit_world/imports/scheduler.py +44 -0
- pumpkin_api/wit_files/wit_world/imports/scoreboard.py +95 -0
- pumpkin_api/wit_files/wit_world/imports/server.py +75 -0
- pumpkin_api/wit_files/wit_world/imports/text.py +89 -0
- pumpkin_api/wit_files/wit_world/imports/world.py +215 -0
- pumpkin_api/wit_files/world.wit +169 -0
- pumpkin_api_py-0.1.0.dev0.dist-info/METADATA +58 -0
- pumpkin_api_py-0.1.0.dev0.dist-info/RECORD +75 -0
- pumpkin_api_py-0.1.0.dev0.dist-info/WHEEL +4 -0
- pumpkin_api_py-0.1.0.dev0.dist-info/entry_points.txt +2 -0
- pumpkin_api_py-0.1.0.dev0.dist-info/licenses/LICENSE +677 -0
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
"""Defines a custom `asyncio` event loop backed by `wasi:io/poll#poll`.
|
|
2
|
+
|
|
3
|
+
This also includes helper classes and functions for working with `wasi:http`.
|
|
4
|
+
|
|
5
|
+
This is only useful for `wasi:http@0.2.x`; `wasi:http@0.3.x` uses a different
|
|
6
|
+
mechanism to model concurrency.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import asyncio
|
|
10
|
+
import socket
|
|
11
|
+
import subprocess
|
|
12
|
+
|
|
13
|
+
from componentize_py_types import Ok, Err
|
|
14
|
+
from wit_world.imports import types, streams, poll, outgoing_handler
|
|
15
|
+
from wit_world.imports.types import (
|
|
16
|
+
IncomingBody,
|
|
17
|
+
OutgoingBody,
|
|
18
|
+
OutgoingRequest,
|
|
19
|
+
IncomingResponse,
|
|
20
|
+
)
|
|
21
|
+
from wit_world.imports.streams import StreamError_Closed, InputStream
|
|
22
|
+
from wit_world.imports.poll import Pollable
|
|
23
|
+
from typing import Optional, cast
|
|
24
|
+
|
|
25
|
+
# Maximum number of bytes to read at a time
|
|
26
|
+
READ_SIZE: int = 16 * 1024
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
async def send(request: OutgoingRequest) -> IncomingResponse:
|
|
30
|
+
"""Send the specified request and wait asynchronously for the response."""
|
|
31
|
+
|
|
32
|
+
future = outgoing_handler.handle(request, None)
|
|
33
|
+
|
|
34
|
+
while True:
|
|
35
|
+
response = future.get()
|
|
36
|
+
if response is None:
|
|
37
|
+
await register(cast(PollLoop, asyncio.get_event_loop()), future.subscribe())
|
|
38
|
+
else:
|
|
39
|
+
if isinstance(response, Ok):
|
|
40
|
+
if isinstance(response.value, Ok):
|
|
41
|
+
return response.value.value
|
|
42
|
+
else:
|
|
43
|
+
raise response.value
|
|
44
|
+
else:
|
|
45
|
+
raise response
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class Stream:
|
|
49
|
+
"""Reader abstraction over `wasi:http/types#incoming-body`."""
|
|
50
|
+
|
|
51
|
+
def __init__(self, body: IncomingBody):
|
|
52
|
+
self.body: Optional[IncomingBody] = body
|
|
53
|
+
self.stream: Optional[InputStream] = body.stream()
|
|
54
|
+
|
|
55
|
+
async def next(self) -> Optional[bytes]:
|
|
56
|
+
"""Wait for the next chunk of data to arrive on the stream.
|
|
57
|
+
|
|
58
|
+
This will return `None` when the end of the stream has been reached.
|
|
59
|
+
"""
|
|
60
|
+
while True:
|
|
61
|
+
try:
|
|
62
|
+
if self.stream is None:
|
|
63
|
+
return None
|
|
64
|
+
else:
|
|
65
|
+
buffer = self.stream.read(READ_SIZE)
|
|
66
|
+
if len(buffer) == 0:
|
|
67
|
+
await register(
|
|
68
|
+
cast(PollLoop, asyncio.get_event_loop()),
|
|
69
|
+
self.stream.subscribe(),
|
|
70
|
+
)
|
|
71
|
+
else:
|
|
72
|
+
return buffer
|
|
73
|
+
except Err as e:
|
|
74
|
+
if isinstance(e.value, StreamError_Closed):
|
|
75
|
+
if self.stream is not None:
|
|
76
|
+
self.stream.__exit__(None, None, None)
|
|
77
|
+
self.stream = None
|
|
78
|
+
if self.body is not None:
|
|
79
|
+
IncomingBody.finish(self.body)
|
|
80
|
+
self.body = None
|
|
81
|
+
else:
|
|
82
|
+
raise e
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class Sink:
|
|
86
|
+
"""Writer abstraction over `wasi:http/types#outgoing-body`."""
|
|
87
|
+
|
|
88
|
+
def __init__(self, body: OutgoingBody):
|
|
89
|
+
self.body = body
|
|
90
|
+
self.stream = body.write()
|
|
91
|
+
|
|
92
|
+
async def send(self, chunk: bytes):
|
|
93
|
+
"""Write the specified bytes to the sink.
|
|
94
|
+
|
|
95
|
+
This may need to yield according to the backpressure requirements of the sink.
|
|
96
|
+
"""
|
|
97
|
+
offset = 0
|
|
98
|
+
flushing = False
|
|
99
|
+
while True:
|
|
100
|
+
count = self.stream.check_write()
|
|
101
|
+
if count == 0:
|
|
102
|
+
await register(
|
|
103
|
+
cast(PollLoop, asyncio.get_event_loop()), self.stream.subscribe()
|
|
104
|
+
)
|
|
105
|
+
elif offset == len(chunk):
|
|
106
|
+
if flushing:
|
|
107
|
+
return
|
|
108
|
+
else:
|
|
109
|
+
self.stream.flush()
|
|
110
|
+
flushing = True
|
|
111
|
+
else:
|
|
112
|
+
count = min(count, len(chunk) - offset)
|
|
113
|
+
self.stream.write(chunk[offset : offset + count])
|
|
114
|
+
offset += count
|
|
115
|
+
|
|
116
|
+
def close(self):
|
|
117
|
+
"""Close the stream, indicating no further data will be written."""
|
|
118
|
+
|
|
119
|
+
self.stream.__exit__(None, None, None)
|
|
120
|
+
self.stream = None
|
|
121
|
+
OutgoingBody.finish(self.body, None)
|
|
122
|
+
self.body = None
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
class PollLoop(asyncio.AbstractEventLoop):
|
|
126
|
+
"""Custom `asyncio` event loop backed by `wasi:io/poll#poll`."""
|
|
127
|
+
|
|
128
|
+
def __init__(self):
|
|
129
|
+
self.wakers = []
|
|
130
|
+
self.running = False
|
|
131
|
+
self.handles = []
|
|
132
|
+
self.exception = None
|
|
133
|
+
|
|
134
|
+
def get_debug(self):
|
|
135
|
+
return False
|
|
136
|
+
|
|
137
|
+
def run_until_complete(self, future):
|
|
138
|
+
future = asyncio.ensure_future(future, loop=self)
|
|
139
|
+
|
|
140
|
+
self.running = True
|
|
141
|
+
asyncio.events._set_running_loop(self)
|
|
142
|
+
while self.running and not future.done():
|
|
143
|
+
handles = self.handles
|
|
144
|
+
self.handles = []
|
|
145
|
+
for handle in handles:
|
|
146
|
+
if not handle._cancelled:
|
|
147
|
+
handle._run()
|
|
148
|
+
|
|
149
|
+
if self.wakers:
|
|
150
|
+
[pollables, wakers] = list(map(list, zip(*self.wakers)))
|
|
151
|
+
|
|
152
|
+
new_wakers = []
|
|
153
|
+
ready = [False] * len(pollables)
|
|
154
|
+
for index in poll.poll(pollables):
|
|
155
|
+
ready[index] = True
|
|
156
|
+
|
|
157
|
+
for (ready, pollable), waker in zip(zip(ready, pollables), wakers):
|
|
158
|
+
if ready:
|
|
159
|
+
pollable.__exit__(None, None, None)
|
|
160
|
+
waker.set_result(None)
|
|
161
|
+
else:
|
|
162
|
+
new_wakers.append((pollable, waker))
|
|
163
|
+
|
|
164
|
+
self.wakers = new_wakers
|
|
165
|
+
|
|
166
|
+
if self.exception is not None:
|
|
167
|
+
raise self.exception
|
|
168
|
+
|
|
169
|
+
return future.result()
|
|
170
|
+
|
|
171
|
+
def is_running(self):
|
|
172
|
+
return self.running
|
|
173
|
+
|
|
174
|
+
def is_closed(self):
|
|
175
|
+
return not self.running
|
|
176
|
+
|
|
177
|
+
def stop(self):
|
|
178
|
+
self.running = False
|
|
179
|
+
|
|
180
|
+
def close(self):
|
|
181
|
+
self.running = False
|
|
182
|
+
|
|
183
|
+
def shutdown_asyncgens(self):
|
|
184
|
+
pass
|
|
185
|
+
|
|
186
|
+
def call_exception_handler(self, context):
|
|
187
|
+
self.exception = context.get("exception", None)
|
|
188
|
+
|
|
189
|
+
def call_soon(self, callback, *args, context=None):
|
|
190
|
+
handle = asyncio.Handle(callback, args, self, context)
|
|
191
|
+
self.handles.append(handle)
|
|
192
|
+
return handle
|
|
193
|
+
|
|
194
|
+
def create_task(self, coroutine):
|
|
195
|
+
return asyncio.Task(coroutine, loop=self)
|
|
196
|
+
|
|
197
|
+
def create_future(self):
|
|
198
|
+
return asyncio.Future(loop=self)
|
|
199
|
+
|
|
200
|
+
# The remaining methods should be irrelevant for our purposes and thus unimplemented
|
|
201
|
+
|
|
202
|
+
def run_forever(self):
|
|
203
|
+
raise NotImplementedError
|
|
204
|
+
|
|
205
|
+
async def shutdown_default_executor(self):
|
|
206
|
+
raise NotImplementedError
|
|
207
|
+
|
|
208
|
+
def _timer_handle_cancelled(self, handle):
|
|
209
|
+
raise NotImplementedError
|
|
210
|
+
|
|
211
|
+
def call_later(self, delay, callback, *args, context=None):
|
|
212
|
+
raise NotImplementedError
|
|
213
|
+
|
|
214
|
+
def call_at(self, when, callback, *args, context=None):
|
|
215
|
+
raise NotImplementedError
|
|
216
|
+
|
|
217
|
+
def time(self):
|
|
218
|
+
raise NotImplementedError
|
|
219
|
+
|
|
220
|
+
def call_soon_threadsafe(self, callback, *args, context=None):
|
|
221
|
+
raise NotImplementedError
|
|
222
|
+
|
|
223
|
+
def run_in_executor(self, executor, func, *args):
|
|
224
|
+
raise NotImplementedError
|
|
225
|
+
|
|
226
|
+
def set_default_executor(self, executor):
|
|
227
|
+
raise NotImplementedError
|
|
228
|
+
|
|
229
|
+
async def getaddrinfo(self, host, port, *, family=0, type=0, proto=0, flags=0):
|
|
230
|
+
raise NotImplementedError
|
|
231
|
+
|
|
232
|
+
async def getnameinfo(self, sockaddr, flags=0):
|
|
233
|
+
raise NotImplementedError
|
|
234
|
+
|
|
235
|
+
async def create_connection(
|
|
236
|
+
self,
|
|
237
|
+
protocol_factory,
|
|
238
|
+
host=None,
|
|
239
|
+
port=None,
|
|
240
|
+
*,
|
|
241
|
+
ssl=None,
|
|
242
|
+
family=0,
|
|
243
|
+
proto=0,
|
|
244
|
+
flags=0,
|
|
245
|
+
sock=None,
|
|
246
|
+
local_addr=None,
|
|
247
|
+
server_hostname=None,
|
|
248
|
+
ssl_handshake_timeout=None,
|
|
249
|
+
ssl_shutdown_timeout=None,
|
|
250
|
+
happy_eyeballs_delay=None,
|
|
251
|
+
interleave=None,
|
|
252
|
+
):
|
|
253
|
+
raise NotImplementedError
|
|
254
|
+
|
|
255
|
+
async def create_server(
|
|
256
|
+
self,
|
|
257
|
+
protocol_factory,
|
|
258
|
+
host=None,
|
|
259
|
+
port=None,
|
|
260
|
+
*,
|
|
261
|
+
family=socket.AF_UNSPEC,
|
|
262
|
+
flags=socket.AI_PASSIVE,
|
|
263
|
+
sock=None,
|
|
264
|
+
backlog=100,
|
|
265
|
+
ssl=None,
|
|
266
|
+
reuse_address=None,
|
|
267
|
+
reuse_port=None,
|
|
268
|
+
ssl_handshake_timeout=None,
|
|
269
|
+
ssl_shutdown_timeout=None,
|
|
270
|
+
start_serving=True,
|
|
271
|
+
):
|
|
272
|
+
raise NotImplementedError
|
|
273
|
+
|
|
274
|
+
async def sendfile(self, transport, file, offset=0, count=None, *, fallback=True):
|
|
275
|
+
raise NotImplementedError
|
|
276
|
+
|
|
277
|
+
async def start_tls(
|
|
278
|
+
self,
|
|
279
|
+
transport,
|
|
280
|
+
protocol,
|
|
281
|
+
sslcontext,
|
|
282
|
+
*,
|
|
283
|
+
server_side=False,
|
|
284
|
+
server_hostname=None,
|
|
285
|
+
ssl_handshake_timeout=None,
|
|
286
|
+
ssl_shutdown_timeout=None,
|
|
287
|
+
):
|
|
288
|
+
raise NotImplementedError
|
|
289
|
+
|
|
290
|
+
async def create_unix_connection(
|
|
291
|
+
self,
|
|
292
|
+
protocol_factory,
|
|
293
|
+
path=None,
|
|
294
|
+
*,
|
|
295
|
+
ssl=None,
|
|
296
|
+
sock=None,
|
|
297
|
+
server_hostname=None,
|
|
298
|
+
ssl_handshake_timeout=None,
|
|
299
|
+
ssl_shutdown_timeout=None,
|
|
300
|
+
):
|
|
301
|
+
raise NotImplementedError
|
|
302
|
+
|
|
303
|
+
async def create_unix_server(
|
|
304
|
+
self,
|
|
305
|
+
protocol_factory,
|
|
306
|
+
path=None,
|
|
307
|
+
*,
|
|
308
|
+
sock=None,
|
|
309
|
+
backlog=100,
|
|
310
|
+
ssl=None,
|
|
311
|
+
ssl_handshake_timeout=None,
|
|
312
|
+
ssl_shutdown_timeout=None,
|
|
313
|
+
start_serving=True,
|
|
314
|
+
):
|
|
315
|
+
raise NotImplementedError
|
|
316
|
+
|
|
317
|
+
async def connect_accepted_socket(
|
|
318
|
+
self,
|
|
319
|
+
protocol_factory,
|
|
320
|
+
sock,
|
|
321
|
+
*,
|
|
322
|
+
ssl=None,
|
|
323
|
+
ssl_handshake_timeout=None,
|
|
324
|
+
ssl_shutdown_timeout=None,
|
|
325
|
+
):
|
|
326
|
+
raise NotImplementedError
|
|
327
|
+
|
|
328
|
+
async def create_datagram_endpoint(
|
|
329
|
+
self,
|
|
330
|
+
protocol_factory,
|
|
331
|
+
local_addr=None,
|
|
332
|
+
remote_addr=None,
|
|
333
|
+
*,
|
|
334
|
+
family=0,
|
|
335
|
+
proto=0,
|
|
336
|
+
flags=0,
|
|
337
|
+
reuse_address=None,
|
|
338
|
+
reuse_port=None,
|
|
339
|
+
allow_broadcast=None,
|
|
340
|
+
sock=None,
|
|
341
|
+
):
|
|
342
|
+
raise NotImplementedError
|
|
343
|
+
|
|
344
|
+
async def connect_read_pipe(self, protocol_factory, pipe):
|
|
345
|
+
raise NotImplementedError
|
|
346
|
+
|
|
347
|
+
async def connect_write_pipe(self, protocol_factory, pipe):
|
|
348
|
+
raise NotImplementedError
|
|
349
|
+
|
|
350
|
+
async def subprocess_shell(
|
|
351
|
+
self,
|
|
352
|
+
protocol_factory,
|
|
353
|
+
cmd,
|
|
354
|
+
*,
|
|
355
|
+
stdin=subprocess.PIPE,
|
|
356
|
+
stdout=subprocess.PIPE,
|
|
357
|
+
stderr=subprocess.PIPE,
|
|
358
|
+
**kwargs,
|
|
359
|
+
):
|
|
360
|
+
raise NotImplementedError
|
|
361
|
+
|
|
362
|
+
async def subprocess_exec(
|
|
363
|
+
self,
|
|
364
|
+
protocol_factory,
|
|
365
|
+
*args,
|
|
366
|
+
stdin=subprocess.PIPE,
|
|
367
|
+
stdout=subprocess.PIPE,
|
|
368
|
+
stderr=subprocess.PIPE,
|
|
369
|
+
**kwargs,
|
|
370
|
+
):
|
|
371
|
+
raise NotImplementedError
|
|
372
|
+
|
|
373
|
+
def add_reader(self, fd, callback, *args):
|
|
374
|
+
raise NotImplementedError
|
|
375
|
+
|
|
376
|
+
def remove_reader(self, fd):
|
|
377
|
+
raise NotImplementedError
|
|
378
|
+
|
|
379
|
+
def add_writer(self, fd, callback, *args):
|
|
380
|
+
raise NotImplementedError
|
|
381
|
+
|
|
382
|
+
def remove_writer(self, fd):
|
|
383
|
+
raise NotImplementedError
|
|
384
|
+
|
|
385
|
+
async def sock_recv(self, sock, nbytes):
|
|
386
|
+
raise NotImplementedError
|
|
387
|
+
|
|
388
|
+
async def sock_recv_into(self, sock, buf):
|
|
389
|
+
raise NotImplementedError
|
|
390
|
+
|
|
391
|
+
async def sock_recvfrom(self, sock, bufsize):
|
|
392
|
+
raise NotImplementedError
|
|
393
|
+
|
|
394
|
+
async def sock_recvfrom_into(self, sock, buf, nbytes=0):
|
|
395
|
+
raise NotImplementedError
|
|
396
|
+
|
|
397
|
+
async def sock_sendall(self, sock, data):
|
|
398
|
+
raise NotImplementedError
|
|
399
|
+
|
|
400
|
+
async def sock_sendto(self, sock, data, address):
|
|
401
|
+
raise NotImplementedError
|
|
402
|
+
|
|
403
|
+
async def sock_connect(self, sock, address):
|
|
404
|
+
raise NotImplementedError
|
|
405
|
+
|
|
406
|
+
async def sock_accept(self, sock):
|
|
407
|
+
raise NotImplementedError
|
|
408
|
+
|
|
409
|
+
async def sock_sendfile(self, sock, file, offset=0, count=None, *, fallback=None):
|
|
410
|
+
raise NotImplementedError
|
|
411
|
+
|
|
412
|
+
def add_signal_handler(self, sig, callback, *args):
|
|
413
|
+
raise NotImplementedError
|
|
414
|
+
|
|
415
|
+
def remove_signal_handler(self, sig):
|
|
416
|
+
raise NotImplementedError
|
|
417
|
+
|
|
418
|
+
def set_task_factory(self, factory):
|
|
419
|
+
raise NotImplementedError
|
|
420
|
+
|
|
421
|
+
def get_task_factory(self):
|
|
422
|
+
raise NotImplementedError
|
|
423
|
+
|
|
424
|
+
def get_exception_handler(self):
|
|
425
|
+
raise NotImplementedError
|
|
426
|
+
|
|
427
|
+
def set_exception_handler(self, handler):
|
|
428
|
+
raise NotImplementedError
|
|
429
|
+
|
|
430
|
+
def default_exception_handler(self, context):
|
|
431
|
+
raise NotImplementedError
|
|
432
|
+
|
|
433
|
+
def set_debug(self, enabled):
|
|
434
|
+
raise NotImplementedError
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
async def register(loop: PollLoop, pollable: Pollable):
|
|
438
|
+
waker = loop.create_future()
|
|
439
|
+
loop.wakers.append((pollable, waker))
|
|
440
|
+
await waker
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/// Provides functionality to schedule tasks to be executed later on the server.
|
|
2
|
+
interface scheduler {
|
|
3
|
+
/// Schedules a task to be executed once after the specified number of ticks.
|
|
4
|
+
///
|
|
5
|
+
/// * `handler-id`: The unique ID of the handler to call when the task executes.
|
|
6
|
+
/// * `delay-ticks`: The number of game ticks to wait before execution (20 ticks = 1 second).
|
|
7
|
+
///
|
|
8
|
+
/// Returns a unique task ID that can be used to cancel the task.
|
|
9
|
+
schedule-delayed-task: func(handler-id: u32, delay-ticks: u64) -> u32;
|
|
10
|
+
|
|
11
|
+
/// Schedules a task to be executed repeatedly.
|
|
12
|
+
///
|
|
13
|
+
/// * `handler-id`: The unique ID of the handler to call when the task executes.
|
|
14
|
+
/// * `delay-ticks`: The number of game ticks to wait before the first execution.
|
|
15
|
+
/// * `period-ticks`: The number of game ticks between subsequent executions.
|
|
16
|
+
///
|
|
17
|
+
/// Returns a unique task ID that can be used to cancel the task.
|
|
18
|
+
schedule-repeating-task: func(handler-id: u32, delay-ticks: u64, period-ticks: u64) -> u32;
|
|
19
|
+
|
|
20
|
+
/// Cancels a scheduled task if it hasn't finished yet.
|
|
21
|
+
///
|
|
22
|
+
/// * `task-id`: The ID of the task to cancel.
|
|
23
|
+
cancel-task: func(task-id: u32);
|
|
24
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
interface scoreboard {
|
|
2
|
+
use text.{text-component};
|
|
3
|
+
use common.{named-color};
|
|
4
|
+
|
|
5
|
+
enum render-type {
|
|
6
|
+
integer,
|
|
7
|
+
hearts
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
enum display-slot {
|
|
11
|
+
player-list,
|
|
12
|
+
sidebar,
|
|
13
|
+
below-name,
|
|
14
|
+
sidebar-team-black,
|
|
15
|
+
sidebar-team-dark-blue,
|
|
16
|
+
sidebar-team-dark-green,
|
|
17
|
+
sidebar-team-dark-aqua,
|
|
18
|
+
sidebar-team-dark-red,
|
|
19
|
+
sidebar-team-dark-purple,
|
|
20
|
+
sidebar-team-gold,
|
|
21
|
+
sidebar-team-gray,
|
|
22
|
+
sidebar-team-dark-gray,
|
|
23
|
+
sidebar-team-blue,
|
|
24
|
+
sidebar-team-green,
|
|
25
|
+
sidebar-team-aqua,
|
|
26
|
+
sidebar-team-red,
|
|
27
|
+
sidebar-team-light-purple,
|
|
28
|
+
sidebar-team-yellow,
|
|
29
|
+
sidebar-team-white,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
enum nametag-visibility {
|
|
33
|
+
always,
|
|
34
|
+
never,
|
|
35
|
+
hide-for-other-teams,
|
|
36
|
+
hide-for-own-team
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
enum collision-rule {
|
|
40
|
+
always,
|
|
41
|
+
never,
|
|
42
|
+
push-other-teams,
|
|
43
|
+
push-own-team
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
record team-settings {
|
|
47
|
+
display-name: text-component,
|
|
48
|
+
friendly-fire: bool,
|
|
49
|
+
see-friendly-invisibles: bool,
|
|
50
|
+
nametag-visibility: nametag-visibility,
|
|
51
|
+
collision-rule: collision-rule,
|
|
52
|
+
color: named-color,
|
|
53
|
+
prefix: text-component,
|
|
54
|
+
suffix: text-component
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
resource scoreboard {
|
|
58
|
+
add-objective: func(name: string, display-name: text-component, render-type: render-type);
|
|
59
|
+
remove-objective: func(name: string);
|
|
60
|
+
set-display-slot: func(slot: display-slot, objective-name: string);
|
|
61
|
+
|
|
62
|
+
update-score: func(entity-name: string, objective-name: string, value: s32);
|
|
63
|
+
remove-score: func(entity-name: string, objective-name: string);
|
|
64
|
+
|
|
65
|
+
create-team: func(name: string, settings: team-settings);
|
|
66
|
+
remove-team: func(name: string);
|
|
67
|
+
update-team: func(name: string, settings: team-settings);
|
|
68
|
+
|
|
69
|
+
add-player-to-team: func(team-name: string, player-name: string);
|
|
70
|
+
remove-player-from-team: func(team-name: string, player-name: string);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
interface server {
|
|
2
|
+
use player.{player};
|
|
3
|
+
|
|
4
|
+
/// Represents the difficulty setting of a Minecraft server.
|
|
5
|
+
enum difficulty {
|
|
6
|
+
/// Hostile mobs do not spawn. Players regain health automatically.
|
|
7
|
+
peaceful,
|
|
8
|
+
/// Hostile mobs deal less damage.
|
|
9
|
+
easy,
|
|
10
|
+
/// Standard Minecraft difficulty.
|
|
11
|
+
normal,
|
|
12
|
+
/// Hostile mobs deal more damage.
|
|
13
|
+
hard,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/// Represents the global server instance.
|
|
17
|
+
resource server {
|
|
18
|
+
/// Returns the current difficulty level of the server.
|
|
19
|
+
get-difficulty: func() -> difficulty;
|
|
20
|
+
|
|
21
|
+
/// Returns the total number of players currently connected to the server.
|
|
22
|
+
get-player-count: func() -> u32;
|
|
23
|
+
|
|
24
|
+
/// Returns the rolling average Milliseconds Per Tick (MSPT).
|
|
25
|
+
/// A value below 50.0 is required for a stable 20 TPS.
|
|
26
|
+
get-mspt: func() -> f64;
|
|
27
|
+
|
|
28
|
+
/// Returns the effective Ticks Per Second (TPS).
|
|
29
|
+
/// Ideal value is 20.0.
|
|
30
|
+
get-tps: func() -> f64;
|
|
31
|
+
|
|
32
|
+
/// Returns a list of all online players across all worlds.
|
|
33
|
+
get-all-players: func() -> list<player>;
|
|
34
|
+
|
|
35
|
+
/// Searches for a player by their exact name.
|
|
36
|
+
get-player-by-name: func(name: string) -> option<player>;
|
|
37
|
+
|
|
38
|
+
/// Searches for a player by their UUID string.
|
|
39
|
+
get-player-by-uuid: func(id: string) -> option<player>;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
interface text {
|
|
2
|
+
use common.{named-color, rgb-color, argb-color};
|
|
3
|
+
|
|
4
|
+
resource text-component {
|
|
5
|
+
text: static func(plain: string) -> text-component;
|
|
6
|
+
translate: static func(key: string, %with: list<text-component>) -> text-component;
|
|
7
|
+
|
|
8
|
+
add-child: func(child: text-component);
|
|
9
|
+
add-text: func(text: string);
|
|
10
|
+
get-text: func() -> string;
|
|
11
|
+
encode: func() -> list<u8>;
|
|
12
|
+
|
|
13
|
+
// Style
|
|
14
|
+
|
|
15
|
+
color-named: func(color: named-color);
|
|
16
|
+
color-rgb: func(color: rgb-color);
|
|
17
|
+
bold: func(value: bool);
|
|
18
|
+
italic: func(value: bool);
|
|
19
|
+
underlined: func(value: bool);
|
|
20
|
+
strikethrough: func(value: bool);
|
|
21
|
+
obfuscated: func(value: bool);
|
|
22
|
+
/// Text inserted into chat when shift-clicked
|
|
23
|
+
insertion: func(text: string);
|
|
24
|
+
font: func(font: string);
|
|
25
|
+
shadow-color: func(color: argb-color);
|
|
26
|
+
|
|
27
|
+
// Click events
|
|
28
|
+
|
|
29
|
+
click-open-url: func(url: string);
|
|
30
|
+
click-run-command: func(command: string);
|
|
31
|
+
click-suggest-command: func(command: string);
|
|
32
|
+
click-copy-to-clipboard: func(text: string);
|
|
33
|
+
|
|
34
|
+
// Hover events
|
|
35
|
+
|
|
36
|
+
hover-show-text: func(text: text-component);
|
|
37
|
+
/// Item data as SNBT string
|
|
38
|
+
hover-show-item: func(item: string);
|
|
39
|
+
hover-show-entity: func(entity-type: string, id: string, name: option<text-component>);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# This file is automatically generated by componentize-py
|
|
2
|
+
# It is not intended for manual editing.
|
|
3
|
+
from typing import TypeVar, Generic, Union, Optional, Protocol, Tuple, List, Any, Self, Callable
|
|
4
|
+
from types import TracebackType
|
|
5
|
+
from enum import Flag, Enum, auto
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from abc import abstractmethod
|
|
8
|
+
import weakref
|
|
9
|
+
|
|
10
|
+
from componentize_py_types import Result, Ok, Err, Some
|
|
11
|
+
from .imports import event
|
|
12
|
+
from .imports import server
|
|
13
|
+
from .imports import command
|
|
14
|
+
from .imports import context
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class WitWorld(Protocol):
|
|
18
|
+
|
|
19
|
+
@abstractmethod
|
|
20
|
+
def init_plugin(self) -> None:
|
|
21
|
+
"""
|
|
22
|
+
--- Plugin-provided exports ---
|
|
23
|
+
Called by the host once to initialize the plugin.
|
|
24
|
+
Internal use only; plugins should use the `register_plugin!` macro.
|
|
25
|
+
"""
|
|
26
|
+
raise NotImplementedError
|
|
27
|
+
|
|
28
|
+
@abstractmethod
|
|
29
|
+
def on_load(self, context: context.Context) -> None:
|
|
30
|
+
"""
|
|
31
|
+
Called when the plugin is being loaded.
|
|
32
|
+
Use this to register commands, events, and perform initial setup.
|
|
33
|
+
|
|
34
|
+
Raises: `componentize_py_types.Err(wit_world.imports.str)`
|
|
35
|
+
"""
|
|
36
|
+
raise NotImplementedError
|
|
37
|
+
|
|
38
|
+
@abstractmethod
|
|
39
|
+
def on_unload(self, context: context.Context) -> None:
|
|
40
|
+
"""
|
|
41
|
+
Called when the plugin is being unloaded.
|
|
42
|
+
Use this to save data and clean up resources.
|
|
43
|
+
|
|
44
|
+
Raises: `componentize_py_types.Err(wit_world.imports.str)`
|
|
45
|
+
"""
|
|
46
|
+
raise NotImplementedError
|
|
47
|
+
|
|
48
|
+
@abstractmethod
|
|
49
|
+
def handle_event(self, event_id: int, server: server.Server, event: event.Event) -> event.Event:
|
|
50
|
+
"""
|
|
51
|
+
Dispatches an event to the plugin for handling.
|
|
52
|
+
"""
|
|
53
|
+
raise NotImplementedError
|
|
54
|
+
|
|
55
|
+
@abstractmethod
|
|
56
|
+
def handle_command(self, command_id: int, sender: command.CommandSender, server: server.Server, args: command.ConsumedArgs) -> int:
|
|
57
|
+
"""
|
|
58
|
+
Dispatches a command execution to the plugin.
|
|
59
|
+
|
|
60
|
+
Raises: `componentize_py_types.Err(wit_world.imports.command.CommandError)`
|
|
61
|
+
"""
|
|
62
|
+
raise NotImplementedError
|
|
63
|
+
|
|
64
|
+
@abstractmethod
|
|
65
|
+
def handle_task(self, handler_id: int, server: server.Server) -> None:
|
|
66
|
+
"""
|
|
67
|
+
Dispatches a scheduled task execution to the plugin.
|
|
68
|
+
"""
|
|
69
|
+
raise NotImplementedError
|
|
70
|
+
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# This file is automatically generated by componentize-py
|
|
2
|
+
# It is not intended for manual editing.
|
|
3
|
+
from typing import TypeVar, Generic, Union, Optional, Protocol, Tuple, List, Any, Self, Callable
|
|
4
|
+
from types import TracebackType
|
|
5
|
+
from enum import Flag, Enum, auto
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from abc import abstractmethod
|
|
8
|
+
import weakref
|
|
9
|
+
|
|
10
|
+
from componentize_py_types import Result, Ok, Err, Some
|
|
11
|
+
from ..exports import metadata
|
|
12
|
+
|
|
13
|
+
class Metadata(Protocol):
|
|
14
|
+
|
|
15
|
+
@abstractmethod
|
|
16
|
+
def get_metadata(self) -> metadata.PluginMetadata:
|
|
17
|
+
raise NotImplementedError
|
|
18
|
+
|
|
19
|
+
|