|
1 | 1 | # Pythonized CC Tweaked (ComputerCraft) API
|
2 | 2 |
|
3 |
| -1. Enable localhost in mod server config |
| 3 | +**Warning**: CPython can't build safe sandboxes for arbitrary untrusted code |
| 4 | +[(read more)](https://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html). |
| 5 | +Never use code in this repo if you don't trust your players! |
| 6 | + |
| 7 | +1. Download and install wheel from github releases |
| 8 | + |
| 9 | + ```sh |
| 10 | + pip install computercraft-*.whl |
| 11 | + ``` |
| 12 | + |
| 13 | +2. Enable localhost in mod server config |
4 | 14 |
|
5 | 15 | In case of singleplayer it's located inside your saves folder.
|
6 | 16 | In case of multiplayer check your server folder.
|
|
13 | 23 | action = "allow" # change here deny to allow
|
14 | 24 | ```
|
15 | 25 |
|
16 |
| -2. Create module named `examplemod.py`: |
| 26 | +3. Start python server: |
17 | 27 |
|
18 |
| - ```python |
19 |
| - async def hello(api): |
20 |
| - await api.print('Hello world!') |
21 |
| - ``` |
22 |
| - |
23 |
| -3. Start a server: |
24 |
| - |
25 |
| - ```bash |
26 |
| - python -m computercraft.server examplemod |
| 28 | + ```sh |
| 29 | + python -m computercraft.server |
27 | 30 | ```
|
28 | 31 |
|
29 | 32 | 4. In minecraft, open up any computer and type:
|
30 | 33 |
|
31 |
| - ```bash |
| 34 | + ```sh |
32 | 35 | wget http://127.0.0.1:8080/ py
|
33 |
| - py hello |
| 36 | + py |
34 | 37 | ```
|
35 | 38 |
|
| 39 | + Now you have python REPL in computercraft! |
| 40 | + To quit REPL type `exit()` and press enter. |
| 41 | +
|
36 | 42 | `py` is short Lua program that interacts with the server.
|
37 |
| -Argument is the name of coroutine inside the module. |
38 |
| -`api` object contains almost everything *as is* in ComputerCraft documentation: |
| 43 | +`cc` module contains almost everything *as is* in ComputerCraft documentation: |
39 | 44 |
|
40 | 45 | ```python
|
41 |
| -async def program(api): |
42 |
| - await api.disk.eject('right') |
43 |
| - await api.print(await api.os.getComputerLabel()) |
44 |
| - # ... |
| 46 | +from cc import disk, os |
| 47 | +
|
| 48 | +disk.eject('right') |
| 49 | +print(os.getComputerLabel()) |
45 | 50 | ```
|
46 | 51 |
|
47 |
| -Using python coroutines allows launching commands in parallel, effectively replacing `parallel` API: |
| 52 | +Opening a file: |
48 | 53 |
|
49 | 54 | ```python
|
50 |
| -async def program(api): |
51 |
| - # Since os.sleep is mostly waiting for events, it doesn't block execution of parallel threads |
52 |
| - # and this snippet takes approximately 2 seconds to complete. |
53 |
| - await asyncio.gather(api.os.sleep(2), api.os.sleep(2)) |
| 55 | +from cc import fs |
| 56 | +
|
| 57 | +with fs.open('filename', 'r') as f: |
| 58 | + for line in f: |
| 59 | + print(line) |
54 | 60 | ```
|
55 | 61 |
|
56 |
| -Opening a file: |
| 62 | +Waiting for event: |
57 | 63 |
|
58 | 64 | ```python
|
59 |
| -async def program(api): |
60 |
| - async with api.fs.open('filename', 'r') as f: |
61 |
| - async for line in f: |
62 |
| - await api.print(line) |
| 65 | +from cc import os |
| 66 | +
|
| 67 | +timer_id = os.startTimer(2) |
| 68 | +while True: |
| 69 | + e = os.pullEvent('timer') |
| 70 | + if e[1] == timer_id: |
| 71 | + print('Timer reached') |
| 72 | + break |
63 | 73 | ```
|
64 | 74 |
|
65 |
| -Capturing event: |
| 75 | +Using modems: |
66 | 76 |
|
67 | 77 | ```python
|
68 |
| -async def program(api): |
69 |
| - async with api.os.captureEvent('timer') as timer_event_queue: |
70 |
| - timer_id = await api.os.startTimer(2) |
71 |
| - async for etid, *_ in timer_event_queue: |
72 |
| - if etid == timer_id: |
73 |
| - await api.print('Timer reached') |
74 |
| - break |
| 78 | +from cc import peripheral |
| 79 | +
|
| 80 | +modem = peripheral.wrap('back') |
| 81 | +listen_channel = 5 |
| 82 | +# this automatically opens and closes modem on listen_channel |
| 83 | +for msg in modem.receive(listen_channel): |
| 84 | + print(repr(msg)) |
| 85 | + if msg.content == 'stop': |
| 86 | + break |
| 87 | + else: |
| 88 | + modem.transmit(msg.reply_channel, listen_channel, msg.content) |
75 | 89 | ```
|
76 | 90 |
|
77 |
| -Using modems: |
| 91 | +Using parallel: |
| 92 | +
|
| 93 | +```python |
| 94 | +from cc import parallel, os |
| 95 | +
|
| 96 | +def fn(): |
| 97 | + os.sleep(2) |
| 98 | + print('done') |
| 99 | +
|
| 100 | +parallel.waitForAll(fn, fn, fn) |
| 101 | +``` |
| 102 | +
|
| 103 | +Importing in-game files as modules: |
78 | 104 |
|
79 | 105 | ```python
|
80 |
| -async def program(api): |
81 |
| - modem = await api.peripheral.wrap('back') |
82 |
| - listen_channel = 5 |
83 |
| - async with modem.receive(listen_channel) as q: |
84 |
| - async for msg in q: |
85 |
| - await api.print(repr(msg)) |
86 |
| - if msg.content == 'stop': |
87 |
| - break |
88 |
| - else: |
89 |
| - await modem.transmit(msg.reply_channel, listen_channel, msg.content) |
| 106 | +from cc import import_file |
| 107 | +
|
| 108 | +p = import_file('/disk/program.py') # absolute |
| 109 | +m = import_file('lib.py', __file__) # relative to current file |
90 | 110 | ```
|
91 | 111 |
|
92 |
| -More examples can be found in `testmod.py`. |
| 112 | +More examples can be found in repository. |
0 commit comments