mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-10-18 15:37:38 +00:00
Compare commits
1034 Commits
v1.96.0
...
v1.16.5-1.
Author | SHA1 | Date | |
---|---|---|---|
![]() |
69af1de979 | ||
![]() |
1dd6c8d75c | ||
![]() |
32b856f77e | ||
![]() |
43101773bb | ||
![]() |
af863469e6 | ||
![]() |
9c00124d38 | ||
![]() |
f62811cb44 | ||
![]() |
79366bf2f5 | ||
![]() |
413fa5bcc8 | ||
![]() |
79fc8237b6 | ||
![]() |
9d50d6414c | ||
![]() |
16df86224b | ||
![]() |
a9519f68a1 | ||
![]() |
f1a08a3362 | ||
![]() |
802949d888 | ||
![]() |
330ab058d3 | ||
![]() |
654c7571c1 | ||
![]() |
7a50bf3979 | ||
![]() |
1153910dc0 | ||
![]() |
af6a240c09 | ||
![]() |
2b901f2d5e | ||
![]() |
62f2cd5cb2 | ||
![]() |
e558b31b2b | ||
![]() |
afd82fbf1f | ||
![]() |
901d8d4c3b | ||
![]() |
f794ce42ab | ||
![]() |
f470478a0f | ||
![]() |
aa009df740 | ||
![]() |
0c6c0badde | ||
![]() |
bed2e0b658 | ||
![]() |
0f9ddac83c | ||
![]() |
932b77d7ee | ||
![]() |
5eedea1bbb | ||
![]() |
114261944a | ||
![]() |
4d10639efb | ||
![]() |
cc08eced48 | ||
![]() |
aa36b49c50 | ||
![]() |
8a1067940d | ||
![]() |
57cfcd8709 | ||
![]() |
190a110296 | ||
![]() |
2562642664 | ||
![]() |
632db1cfa5 | ||
![]() |
aa0d544bba | ||
![]() |
2f6ad00764 | ||
![]() |
05da4dd362 | ||
![]() |
0477b2742c | ||
![]() |
5ee2dba7da | ||
![]() |
7f368727f4 | ||
![]() |
4850d4346d | ||
![]() |
9f337c2d1c | ||
![]() |
d9777a8d2f | ||
![]() |
ca37dbb591 | ||
![]() |
93b45bffed | ||
![]() |
482ed6f6b5 | ||
![]() |
fe3c42ce22 | ||
![]() |
cbe3cb8b3e | ||
![]() |
7b3537761b | ||
![]() |
6ad2cdaf62 | ||
![]() |
e6edee4c58 | ||
![]() |
6754c7bb69 | ||
![]() |
4914ad0040 | ||
![]() |
27102e6381 | ||
![]() |
9083e4f97b | ||
![]() |
f74a386312 | ||
![]() |
ad0080ef32 | ||
![]() |
a549400776 | ||
![]() |
d2405ee3c3 | ||
![]() |
2145d0fe14 | ||
![]() |
f6fcba7a39 | ||
![]() |
82a7edee12 | ||
![]() |
687352572d | ||
![]() |
b048b6666d | ||
![]() |
e16f66e128 | ||
![]() |
1cfad31a0d | ||
![]() |
7c373c6e06 | ||
![]() |
6196aae488 | ||
![]() |
92a0ef2b75 | ||
![]() |
57c5d19f95 | ||
![]() |
1f6e0f287d | ||
![]() |
0e4b7a5a75 | ||
![]() |
47ad7a35dc | ||
![]() |
147f396d28 | ||
![]() |
35d642b516 | ||
![]() |
dc20050547 | ||
![]() |
f5c8afa566 | ||
![]() |
6c73eb7df1 | ||
![]() |
745b732e87 | ||
![]() |
6c519aef63 | ||
![]() |
f880396286 | ||
![]() |
3eab2a9b57 | ||
![]() |
34760d3de4 | ||
![]() |
c4024a4c4c | ||
![]() |
f5fb82cd7d | ||
![]() |
23c17075be | ||
![]() |
e18ba8a2c2 | ||
![]() |
87988a705b | ||
![]() |
422bfdb60d | ||
![]() |
1851ed31cd | ||
![]() |
179da1d8cf | ||
![]() |
92fd93c0e0 | ||
![]() |
3929dba4a5 | ||
![]() |
af966179ce | ||
![]() |
5927e9bb10 | ||
![]() |
53811f8169 | ||
![]() |
298f339376 | ||
![]() |
2418cfb87b | ||
![]() |
9d44f1ca66 | ||
![]() |
306e06a79a | ||
![]() |
4f11549112 | ||
![]() |
8983ecd03a | ||
![]() |
7f3490591d | ||
![]() |
58e747506e | ||
![]() |
095101831c | ||
![]() |
70a24d371d | ||
![]() |
73e3e237ad | ||
![]() |
7b7527ec80 | ||
![]() |
8ffd45c66e | ||
![]() |
e247bd823e | ||
![]() |
276956eed8 | ||
![]() |
dbbbe96df2 | ||
![]() |
bae502e8ea | ||
![]() |
a4c5ecf8df | ||
![]() |
99de00e16e | ||
![]() |
600227e481 | ||
![]() |
18d66bd727 | ||
![]() |
d3563a3854 | ||
![]() |
c2dc8bf675 | ||
![]() |
603119e1e6 | ||
![]() |
d9b3f17b52 | ||
![]() |
993bccc51f | ||
![]() |
96d3b27064 | ||
![]() |
f33f57ea35 | ||
![]() |
070479d901 | ||
![]() |
2fe40f669d | ||
![]() |
1b39c9f470 | ||
![]() |
ed9e823f3f | ||
![]() |
814d5cbcd1 | ||
![]() |
4d8862c78e | ||
![]() |
6cc2f035db | ||
![]() |
2b8fea5b35 | ||
![]() |
b3e6b4c29a | ||
![]() |
c94ff68e7f | ||
![]() |
3fb96a3438 | ||
![]() |
cf3f1d3d48 | ||
![]() |
bca964629a | ||
![]() |
7a2b7c0701 | ||
![]() |
fa7a731ad1 | ||
![]() |
8be48ebcf0 | ||
![]() |
123f3abcaa | ||
![]() |
9f2e43f00a | ||
![]() |
9fb35b2799 | ||
![]() |
272572dbf2 | ||
![]() |
702e4fc787 | ||
![]() |
ea7a218f4a | ||
![]() |
511327effe | ||
![]() |
940e35caea | ||
![]() |
fca01693dd | ||
![]() |
8846a3f36f | ||
![]() |
8002c9e932 | ||
![]() |
544bcaa599 | ||
![]() |
6fd8331e94 | ||
![]() |
7a667b9028 | ||
![]() |
67b7cd7a14 | ||
![]() |
960d79803d | ||
![]() |
ab6b861cd6 | ||
![]() |
43ef36fa15 | ||
![]() |
f037d9539e | ||
![]() |
a3b2f7b5bd | ||
![]() |
0859145d18 | ||
![]() |
f6e4122f7f | ||
![]() |
8e4023fdbc | ||
![]() |
f10818ec6b | ||
![]() |
72e8fc03d3 | ||
![]() |
0e94355a85 | ||
![]() |
bc2358489b | ||
![]() |
6e5e682e3a | ||
![]() |
02c63ce7e8 | ||
![]() |
fd24d89f89 | ||
![]() |
685d33a2dd | ||
![]() |
ca40c9cf19 | ||
![]() |
8985ea9560 | ||
![]() |
1832028dfd | ||
![]() |
316889dab7 | ||
![]() |
96c80a6549 | ||
![]() |
482ae0d22e | ||
![]() |
fb274e2ed6 | ||
![]() |
6dd33f7099 | ||
![]() |
ebe847c04b | ||
![]() |
fdbf41b3c4 | ||
![]() |
9dcb9f9537 | ||
![]() |
1395c877af | ||
![]() |
969451f18c | ||
![]() |
259c8d57f5 | ||
![]() |
2ee07283fa | ||
![]() |
c85a80617a | ||
![]() |
5aa8611e43 | ||
![]() |
86aecd945e | ||
![]() |
045472577a | ||
![]() |
a7a9f4fa13 | ||
![]() |
22e4c0603b | ||
![]() |
f3b731460e | ||
![]() |
d787c6e6c1 | ||
![]() |
9f539dbd59 | ||
![]() |
ca367e7cc7 | ||
![]() |
f6fd0ad172 | ||
![]() |
11272b8d00 | ||
![]() |
0d35331b82 | ||
![]() |
076b454c8f | ||
![]() |
36e0dcbad0 | ||
![]() |
0b5fe990e5 | ||
![]() |
29ece2a6e3 | ||
![]() |
eba26dedab | ||
![]() |
1c254e3bb0 | ||
![]() |
13779d6ad3 | ||
![]() |
7ade380fad | ||
![]() |
2a377a37ee | ||
![]() |
861a9e199d | ||
![]() |
d4f1e34023 | ||
![]() |
d700f1f500 | ||
![]() |
06bf84f151 | ||
![]() |
6d25278a5c | ||
![]() |
abfb05f04c | ||
![]() |
9d8e76c5b4 | ||
![]() |
89662bf54a | ||
![]() |
520635dfec | ||
![]() |
ee82a8d75f | ||
![]() |
967f00cd1b | ||
![]() |
dda5236d84 | ||
![]() |
427ca2f108 | ||
![]() |
e30f2a86f0 | ||
![]() |
121ef6e976 | ||
![]() |
e4271ff6f7 | ||
![]() |
8d3b94734d | ||
![]() |
8ba20985d7 | ||
![]() |
7bb7b5e638 | ||
![]() |
297426419b | ||
![]() |
eb61c5c5d7 | ||
![]() |
cf2bc667c1 | ||
![]() |
c8449086ee | ||
![]() |
662bead8be | ||
![]() |
acaa61a720 | ||
![]() |
9e57150384 | ||
![]() |
0dc34a7dbe | ||
![]() |
5facbca2b3 | ||
![]() |
6c6b2c2ff3 | ||
![]() |
3eb601e554 | ||
![]() |
d0e79f310e | ||
![]() |
0d6528aaf0 | ||
![]() |
647902c019 | ||
![]() |
2aa70b49c1 | ||
![]() |
b17ab16e05 | ||
![]() |
b447b0e308 | ||
![]() |
94ad106272 | ||
![]() |
dc9edf26ec | ||
![]() |
048c7bda23 | ||
![]() |
c9397460a4 | ||
![]() |
b2273c9b29 | ||
![]() |
9e82209aab | ||
![]() |
340ade170f | ||
![]() |
7cac8401e8 | ||
![]() |
0f899357c2 | ||
![]() |
3396fe2871 | ||
![]() |
bbf3e48763 | ||
![]() |
92fe1d4bc2 | ||
![]() |
9fbcbae5b3 | ||
![]() |
36a779dc18 | ||
![]() |
cd8b8bbc74 | ||
![]() |
d8319bb35c | ||
![]() |
afd6adbffa | ||
![]() |
4d591c600c | ||
![]() |
0a8e427c61 | ||
![]() |
d3a5d1e314 | ||
![]() |
56010382fb | ||
![]() |
0ff6b0ca70 | ||
![]() |
4b33306940 | ||
![]() |
4dea3dff36 | ||
![]() |
3e8c741170 | ||
![]() |
62baa72457 | ||
![]() |
5eb711da87 | ||
![]() |
79c5df1d92 | ||
![]() |
991ea6e829 | ||
![]() |
1d160641a4 | ||
![]() |
c2b3d914f7 | ||
![]() |
0a537eaeee | ||
![]() |
143b2bdbcd | ||
![]() |
8cb21ed4d1 | ||
![]() |
8aa7695fdd | ||
![]() |
fa78818069 | ||
![]() |
aa857c1be3 | ||
![]() |
e4ced551eb | ||
![]() |
6eec9ba1a3 | ||
![]() |
62172c6049 | ||
![]() |
39f3cf8cbe | ||
![]() |
5082947331 | ||
![]() |
a8f675c59d | ||
![]() |
bb1ebaee4f | ||
![]() |
bb1183d274 | ||
![]() |
01ddb2b4e4 | ||
![]() |
bdd38fb061 | ||
![]() |
06f35e4997 | ||
![]() |
2d95c32892 | ||
![]() |
6f4d4540b2 | ||
![]() |
96316cddaa | ||
![]() |
e84ddef877 | ||
![]() |
11b40bb6d5 | ||
![]() |
686c6a4c44 | ||
![]() |
a1821035d3 | ||
![]() |
7b8650bbc8 | ||
![]() |
0285260e97 | ||
![]() |
10a3a223a0 | ||
![]() |
2dc970a8bb | ||
![]() |
f74c4cc83c | ||
![]() |
7012ac7163 | ||
![]() |
227b444d81 | ||
![]() |
d50db8a6f3 | ||
![]() |
3a80b51a9f | ||
![]() |
03396cf07a | ||
![]() |
5b57f7509d | ||
![]() |
0568c86628 | ||
![]() |
b31e66686d | ||
![]() |
924b8ef30f | ||
![]() |
7bcc16bb40 | ||
![]() |
31e6746bdf | ||
![]() |
c39bf3eb4d | ||
![]() |
8b952e7e1e | ||
![]() |
04e97f7b86 | ||
![]() |
74752c561c | ||
![]() |
ee96458b56 | ||
![]() |
333410e4cd | ||
![]() |
999a39a3e6 | ||
![]() |
82ca19c296 | ||
![]() |
56d8a5d585 | ||
![]() |
aa5fbb2980 | ||
![]() |
db0bb071f5 | ||
![]() |
ab702e2ba1 | ||
![]() |
d4efacd40a | ||
![]() |
347affcc5c | ||
![]() |
8ebe34b8da | ||
![]() |
fbe28dc51a | ||
![]() |
14e013d075 | ||
![]() |
9bc4e9530c | ||
![]() |
cbff505297 | ||
![]() |
7086cb8a02 | ||
![]() |
8dbc930c2f | ||
![]() |
61eb67849d | ||
![]() |
c2316ef256 | ||
![]() |
0d22270f8b | ||
![]() |
abb9c14256 | ||
![]() |
815e534dc6 | ||
![]() |
51dde077fe | ||
![]() |
31d0b7afcd | ||
![]() |
95b0d950aa | ||
![]() |
efa2be2821 | ||
![]() |
670db97fc7 | ||
![]() |
1650b72edb | ||
![]() |
a5bca3f0df | ||
![]() |
88f41314c7 | ||
![]() |
5ef8d52c13 | ||
![]() |
0b65d56ab0 | ||
![]() |
a256b70685 | ||
![]() |
f16d1499fe | ||
![]() |
79ca851e4f | ||
![]() |
d5c54d64a6 | ||
![]() |
5cfdd2339f | ||
![]() |
3ab3213290 | ||
![]() |
c4aef2d4c7 | ||
![]() |
2ed6692f76 | ||
![]() |
46c9840d00 | ||
![]() |
b3f2f14e96 | ||
![]() |
f075eabc32 | ||
![]() |
3d1c9d1667 | ||
![]() |
3ace49d27f | ||
![]() |
9bd662d8dc | ||
![]() |
df7a40354e | ||
![]() |
c489d4bc4f | ||
![]() |
2b029bd506 | ||
![]() |
2227845658 | ||
![]() |
2d3e88ef59 | ||
![]() |
0bfe960cbd | ||
![]() |
a735f23e1f | ||
![]() |
de6f27ceaf | ||
![]() |
0028ad8f54 | ||
![]() |
4c805f1c27 | ||
![]() |
505543ad94 | ||
![]() |
644471c6bf | ||
![]() |
bf87d7faa1 | ||
![]() |
be95b65488 | ||
![]() |
7e9f3bd61a | ||
![]() |
4a74aa8166 | ||
![]() |
b4ce4361ce | ||
![]() |
42a3dd24ad | ||
![]() |
9129da2e3d | ||
![]() |
668cdcdd39 | ||
![]() |
2543ebee10 | ||
![]() |
2fab1a3054 | ||
![]() |
d4745ae47e | ||
![]() |
104a317163 | ||
![]() |
dc21e2dbc9 | ||
![]() |
75dfa71275 | ||
![]() |
d71bf225cc | ||
![]() |
921802e6c9 | ||
![]() |
56cfc1a452 | ||
![]() |
a14b98be22 | ||
![]() |
76b5c05acc | ||
![]() |
8b3f1a448f | ||
![]() |
3de515c617 | ||
![]() |
ab199cd9b0 | ||
![]() |
fc4bc9aa05 | ||
![]() |
9662a106f0 | ||
![]() |
06b0538b76 | ||
![]() |
fb128152a5 | ||
![]() |
f596af059d | ||
![]() |
52bb06d250 | ||
![]() |
f3d22444d3 | ||
![]() |
8644c4ebf6 | ||
![]() |
84a1f63445 | ||
![]() |
dbe98ac270 | ||
![]() |
a00775dcbb | ||
![]() |
2279f5044d | ||
![]() |
e8d90b94ec | ||
![]() |
0bf7f3de89 | ||
![]() |
59266fe6e9 | ||
![]() |
a198a5241d | ||
![]() |
b429095f88 | ||
![]() |
a6c7236fa0 | ||
![]() |
69deb0c947 | ||
![]() |
b0d7f690eb | ||
![]() |
62f93f1b4b | ||
![]() |
7fe322a93a | ||
![]() |
de97fa35a8 | ||
![]() |
b323db30ee | ||
![]() |
53efd6b303 | ||
![]() |
25ce9b9bea | ||
![]() |
59048b3f30 | ||
![]() |
97faa1b3bc | ||
![]() |
7404133d40 | ||
![]() |
e18e24407e | ||
![]() |
026afa7f73 | ||
![]() |
a960db7ced | ||
![]() |
29cc5bb86b | ||
![]() |
aa9d3c8269 | ||
![]() |
f8074636bc | ||
![]() |
6a4f09e7b1 | ||
![]() |
db2cde4a4c | ||
![]() |
5eec7d9172 | ||
![]() |
8b9735d72e | ||
![]() |
1866916cb8 | ||
![]() |
f38a6a9d43 | ||
![]() |
0f6db63020 | ||
![]() |
51fcd83b87 | ||
![]() |
19d1cc0320 | ||
![]() |
c2190e1318 | ||
![]() |
c40a13558c | ||
![]() |
02695aea51 | ||
![]() |
d5be1aca0e | ||
![]() |
8ff8b78ed8 | ||
![]() |
7fc55aa9a0 | ||
![]() |
38335ca187 | ||
![]() |
e0e194099c | ||
![]() |
8063059764 | ||
![]() |
f96d923b2a | ||
![]() |
9142ccfc93 | ||
![]() |
9f7cc00fcb | ||
![]() |
b129ae627b | ||
![]() |
f9fb0619fa | ||
![]() |
7f9b86a78e | ||
![]() |
58ea7a275e | ||
![]() |
8487a13764 | ||
![]() |
f0ba1108d5 | ||
![]() |
5d0daf9b2d | ||
![]() |
8b8692ba53 | ||
![]() |
1f385f5b35 | ||
![]() |
34baa09b6c | ||
![]() |
b21866fbff | ||
![]() |
e0a288bcb9 | ||
![]() |
4592534a18 | ||
![]() |
28165bfcd6 | ||
![]() |
953b94fd08 | ||
![]() |
e10e30f82b | ||
![]() |
aeb1fa0e7e | ||
![]() |
349a7543b0 | ||
![]() |
3d589eda4a | ||
![]() |
de646b66b6 | ||
![]() |
4f0d311df7 | ||
![]() |
d6e3c9a7fa | ||
![]() |
a7a724f134 | ||
![]() |
b0e30fdce1 | ||
![]() |
4e15afa254 | ||
![]() |
84bac06178 | ||
![]() |
1fecb995c9 | ||
![]() |
99b719299c | ||
![]() |
fb9590467d | ||
![]() |
bc8e090873 | ||
![]() |
cf0f67265f | ||
![]() |
53dd15a213 | ||
![]() |
eb2d617ed8 | ||
![]() |
74dae4ec17 | ||
![]() |
abbc46877b | ||
![]() |
3cb25b3525 | ||
![]() |
f387730b88 | ||
![]() |
92b45b1868 | ||
![]() |
003c7ec2e8 | ||
![]() |
c45221a2d0 | ||
![]() |
8494ba8ce2 | ||
![]() |
058d63e77f | ||
![]() |
17b5bca443 | ||
![]() |
c3f5700494 | ||
![]() |
b17ff6daf0 | ||
![]() |
e8f5531a8c | ||
![]() |
51d3b091da | ||
![]() |
9708dd6786 | ||
![]() |
e48427dbbc | ||
![]() |
669b6d2d56 | ||
![]() |
32d956bbe7 | ||
![]() |
3a147c78a8 | ||
![]() |
8c56b6a7be | ||
![]() |
66e42e0817 | ||
![]() |
0ee3d10fda | ||
![]() |
ed0afc4068 | ||
![]() |
1f70ed6985 | ||
![]() |
8f3ea60c74 | ||
![]() |
eb722a74cd | ||
![]() |
1825f67eee | ||
![]() |
975a994581 | ||
![]() |
061514549d | ||
![]() |
5e52429c23 | ||
![]() |
396cf15a1f | ||
![]() |
7514cf7320 | ||
![]() |
1316d6a3c9 | ||
![]() |
e1cbbe3628 | ||
![]() |
6d367e08a3 | ||
![]() |
eaa7359c8c | ||
![]() |
657ceda3af | ||
![]() |
a934e42219 | ||
![]() |
1544749282 | ||
![]() |
763bab80fa | ||
![]() |
417fda3019 | ||
![]() |
444830cf2d | ||
![]() |
23bf33c454 | ||
![]() |
0be030c497 | ||
![]() |
ee27d8f081 | ||
![]() |
a3a9684505 | ||
![]() |
1381325813 | ||
![]() |
52b112fae6 | ||
![]() |
c83eeb16a8 | ||
![]() |
9d1ee6f61d | ||
![]() |
b90611b4b4 | ||
![]() |
e1e7ef59c6 | ||
![]() |
9ae0f4a993 | ||
![]() |
fd262a7995 | ||
![]() |
58054ad2d1 | ||
![]() |
1255bd00fd | ||
![]() |
1f84480a80 | ||
![]() |
b838efedd2 | ||
![]() |
f78e24f9a0 | ||
![]() |
88f5b20353 | ||
![]() |
331031be45 | ||
![]() |
c5694ea966 | ||
![]() |
34b5ede326 | ||
![]() |
7b476cb24b | ||
![]() |
7ca261d763 | ||
![]() |
c864576619 | ||
![]() |
247c05305d | ||
![]() |
2232f025b8 | ||
![]() |
b2e5401486 | ||
![]() |
41226371f3 | ||
![]() |
1edb7288b9 | ||
![]() |
cc5e972cfc | ||
![]() |
92be0126df | ||
![]() |
dd6f97622e | ||
![]() |
2c9f51db89 | ||
![]() |
72340defe4 | ||
![]() |
542b66c79a | ||
![]() |
e4b0a5b3ce | ||
![]() |
f7e3e72a6e | ||
![]() |
8b17ec76a8 | ||
![]() |
b8d5a89446 | ||
![]() |
4af5bcc0b0 | ||
![]() |
96c577482d | ||
![]() |
7f9a707f75 | ||
![]() |
ed3913c1f4 | ||
![]() |
16d74dd2e8 | ||
![]() |
24bb92007a | ||
![]() |
2f0cae0bc1 | ||
![]() |
e3a672099c | ||
![]() |
abf425dfb5 | ||
![]() |
663859d2e5 | ||
![]() |
f5eb6ce03e | ||
![]() |
4ae370b9db | ||
![]() |
b97e950d86 | ||
![]() |
5865e9c41a | ||
![]() |
85cf2d5ff1 | ||
![]() |
61f8e97f6b | ||
![]() |
c92f06cfd9 | ||
![]() |
05c3c8ad32 | ||
![]() |
bb8f4c624b | ||
![]() |
ea3a160367 | ||
![]() |
737b3cb576 | ||
![]() |
d83a68f3ff | ||
![]() |
24d3777722 | ||
![]() |
826797cbd5 | ||
![]() |
511eea39a1 | ||
![]() |
24af36743d | ||
![]() |
e2761bb315 | ||
![]() |
6734a0e112 | ||
![]() |
d4199064ae | ||
![]() |
04f9644ae7 | ||
![]() |
486f41f082 | ||
![]() |
fff8353451 | ||
![]() |
9a749642d2 | ||
![]() |
c35707725f | ||
![]() |
b0651082f4 | ||
![]() |
aab0cd34cd | ||
![]() |
d2a1a00dc4 | ||
![]() |
f194f4fa3a | ||
![]() |
c9f3d315c0 | ||
![]() |
7f90f2f7ca | ||
![]() |
9f57e77ed3 | ||
![]() |
ab39cb849d | ||
![]() |
a4c9e89370 | ||
![]() |
c8aeddedd4 | ||
![]() |
83df64e520 | ||
![]() |
74ac5bb3d1 | ||
![]() |
d13bd2cce8 | ||
![]() |
ab232bd689 | ||
![]() |
cc96e41d3e | ||
![]() |
741adfa7bb | ||
![]() |
666e83cf4f | ||
![]() |
e2a635b6e5 | ||
![]() |
c58441b29c | ||
![]() |
a6fcfb6af2 | ||
![]() |
17a9329207 | ||
![]() |
f6160bdc57 | ||
![]() |
6aae4e5766 | ||
![]() |
84a6bb1cf3 | ||
![]() |
c334423d42 | ||
![]() |
113b560a20 | ||
![]() |
5bf367af9f | ||
![]() |
61fb4caaad | ||
![]() |
6734af6e4a | ||
![]() |
bf6053906d | ||
![]() |
4766833cf2 | ||
![]() |
01d81cb91d | ||
![]() |
93068402a2 | ||
![]() |
34a2c835d4 | ||
![]() |
30d35883b8 | ||
![]() |
71563a52ff | ||
![]() |
0c6e7b5db5 | ||
![]() |
334ca65482 | ||
![]() |
8472112fc1 | ||
![]() |
84036d97d9 | ||
![]() |
0832974725 | ||
![]() |
6cee4efcd3 | ||
![]() |
6f868849ab | ||
![]() |
275ca58a82 | ||
![]() |
87393e8aef | ||
![]() |
86bf57e3cd | ||
![]() |
72c1d451fe | ||
![]() |
8b4a01df27 | ||
![]() |
d0a973fa46 | ||
![]() |
748ebbe66b | ||
![]() |
59de21eae2 | ||
![]() |
50473afea8 | ||
![]() |
37f925de0a | ||
![]() |
cefde3f003 | ||
![]() |
ae6124d1f4 | ||
![]() |
7e121ff72f | ||
![]() |
5155e18de2 | ||
![]() |
7365741088 | ||
![]() |
d5368d0719 | ||
![]() |
26c12ac1a9 | ||
![]() |
2c67849b35 | ||
![]() |
04509cefec | ||
![]() |
74b9f5dcb0 | ||
![]() |
7809a2eddd | ||
![]() |
183b342071 | ||
![]() |
0bb5515055 | ||
![]() |
e8e9294fdf | ||
![]() |
9acfc0316f | ||
![]() |
29fb0baa09 | ||
![]() |
d5de39ebd4 | ||
![]() |
0faf76e4bd | ||
![]() |
99581e1f40 | ||
![]() |
e8e2ed9fe5 | ||
![]() |
9f72448ecd | ||
![]() |
3da3f16deb | ||
![]() |
0e2ce3c634 | ||
![]() |
fe00e00537 | ||
![]() |
29646a7f61 | ||
![]() |
50d2712581 | ||
![]() |
3093f882d8 | ||
![]() |
e5cf0d1c61 | ||
![]() |
cd879b067f | ||
![]() |
053cb1b53c | ||
![]() |
6b102a8142 | ||
![]() |
ac7979fb46 | ||
![]() |
c8a6888a2f | ||
![]() |
9ce33f8a3f | ||
![]() |
d51851e763 | ||
![]() |
fb70a1a998 | ||
![]() |
a1dcd59d95 | ||
![]() |
2a17585702 | ||
![]() |
2f323f23d7 | ||
![]() |
087c305b0d | ||
![]() |
31764f6d65 | ||
![]() |
4efde2b294 | ||
![]() |
95554a53d1 | ||
![]() |
89c1b2771d | ||
![]() |
8f069a9b72 | ||
![]() |
2e9d6603e3 | ||
![]() |
46595e73df | ||
![]() |
a6a1b9b8e5 | ||
![]() |
3f277a7a7b | ||
![]() |
90c5d3f1e8 | ||
![]() |
a5f7cf8334 | ||
![]() |
3075f89797 | ||
![]() |
45297665c6 | ||
![]() |
ddbf3fc111 | ||
![]() |
da82b89676 | ||
![]() |
d5f1a2c817 | ||
![]() |
6020adef6b | ||
![]() |
d2a52a8b5d | ||
![]() |
9f8774960f | ||
![]() |
36bb8b67c9 | ||
![]() |
8f3a56dd32 | ||
![]() |
113d5d982f | ||
![]() |
37a447e745 | ||
![]() |
9e2232d240 | ||
![]() |
514db30fb1 | ||
![]() |
08181f72d4 | ||
![]() |
613a28a5af | ||
![]() |
e4c422d6f9 | ||
![]() |
478f992dea | ||
![]() |
b54519d0e6 | ||
![]() |
9499654757 | ||
![]() |
c5138c535c | ||
![]() |
5bd8d84d14 | ||
![]() |
ab0310e27c | ||
![]() |
607751da40 | ||
![]() |
1efabccd14 | ||
![]() |
029374e9aa | ||
![]() |
2a8efb3fd5 | ||
![]() |
48edcde4ef | ||
![]() |
58a2995bbc | ||
![]() |
a35dcb28ef | ||
![]() |
7b2d482387 | ||
![]() |
2b077554f7 | ||
![]() |
9134f243c1 | ||
![]() |
c0f3ca81fb | ||
![]() |
190ed4fd20 | ||
![]() |
b9ff9b7f90 | ||
![]() |
b9b8121be9 | ||
![]() |
014bf55cd4 | ||
![]() |
085ae2e74a | ||
![]() |
4ff33f165d | ||
![]() |
d929c02d2a | ||
![]() |
d50a08a549 | ||
![]() |
c493d668c8 | ||
![]() |
53477fd3a1 | ||
![]() |
87aa839b60 | ||
![]() |
e02ccdcb1a | ||
![]() |
f36f532c63 | ||
![]() |
5a816917d5 | ||
![]() |
7af63d052d | ||
![]() |
4f8217d1ab | ||
![]() |
5409d441b5 | ||
![]() |
d5f82fa458 | ||
![]() |
d0deab3519 | ||
![]() |
d5a8df753a | ||
![]() |
13de2c4dd0 | ||
![]() |
906280225e | ||
![]() |
161a5b4707 | ||
![]() |
c6b6b4479c | ||
![]() |
96e7b60285 | ||
![]() |
086fccd997 | ||
![]() |
5dfaf6eee9 | ||
![]() |
e251dd066c | ||
![]() |
9abcfe56ea | ||
![]() |
abbc641fd4 | ||
![]() |
c60dcb4f5a | ||
![]() |
4be0b15afa | ||
![]() |
a4ae36b6b3 | ||
![]() |
ac075d9f53 | ||
![]() |
05d7be0362 | ||
![]() |
9a71dc1a26 | ||
![]() |
156023b154 | ||
![]() |
6b3773a862 | ||
![]() |
376d628cf0 | ||
![]() |
44062ebd52 | ||
![]() |
5739285fc2 | ||
![]() |
70b457ed18 | ||
![]() |
ca2995ed38 | ||
![]() |
6816931659 | ||
![]() |
1547ecbeb3 | ||
![]() |
e918f55b58 | ||
![]() |
c28b468844 | ||
![]() |
052cf8ee7d | ||
![]() |
550ada2f9e | ||
![]() |
17b7727262 | ||
![]() |
4553e404b2 | ||
![]() |
a565a571f9 | ||
![]() |
fb64b6017b | ||
![]() |
ed4229ab70 | ||
![]() |
3fb906ef6c | ||
![]() |
e1663f3df0 | ||
![]() |
52c6584c81 | ||
![]() |
9f87eda5de | ||
![]() |
697e9449cf | ||
![]() |
76c3e4c155 | ||
![]() |
358289b5f9 | ||
![]() |
5eec24676f | ||
![]() |
f52b8fa2de | ||
![]() |
447c3ab125 | ||
![]() |
8fac68386e | ||
![]() |
a3021c4697 | ||
![]() |
b7c61f9c6d | ||
![]() |
08a0342618 | ||
![]() |
3d7a81696d | ||
![]() |
48cb032ddf | ||
![]() |
33260a7747 | ||
![]() |
a049502d12 | ||
![]() |
ae7ef66dfa | ||
![]() |
9748679484 | ||
![]() |
da419b24e7 | ||
![]() |
7f57a977a1 | ||
![]() |
2f42a4e85b | ||
![]() |
af40f5ae5c | ||
![]() |
759d02a249 | ||
![]() |
d7729337ac | ||
![]() |
ee391ae9ea | ||
![]() |
4ed4a6409b | ||
![]() |
e5cc345f49 | ||
![]() |
d847a4d9e0 | ||
![]() |
f106733d71 | ||
![]() |
f3de97d67f | ||
![]() |
544f276ff0 | ||
![]() |
463635a459 | ||
![]() |
3b7b845930 | ||
![]() |
1fc0214857 | ||
![]() |
11bf601db9 | ||
![]() |
7c1154ddfc | ||
![]() |
df557e03fa | ||
![]() |
524b6f1d8a | ||
![]() |
cea8be7efa | ||
![]() |
c5f918ad95 | ||
![]() |
b14c7842fc | ||
![]() |
eead8b5755 | ||
![]() |
10a27a7a25 | ||
![]() |
865fc239a0 | ||
![]() |
f9f94b8304 | ||
![]() |
cb8135a0d1 | ||
![]() |
ef4b0a5632 | ||
![]() |
6a6a87489c | ||
![]() |
2360a6e951 | ||
![]() |
f4f71185ae | ||
![]() |
062977336a | ||
![]() |
e52d98ad8b | ||
![]() |
ef8da8054f | ||
![]() |
1ccd687c00 | ||
![]() |
a8ce5a5b20 | ||
![]() |
68e6bc464b | ||
![]() |
68762fe84c | ||
![]() |
419f29321a | ||
![]() |
00b41d29c1 | ||
![]() |
0ffd5fcf85 | ||
![]() |
95fee95006 | ||
![]() |
239bd769df | ||
![]() |
b4e0e9984f | ||
![]() |
79f42e35ce | ||
![]() |
be89fc25f9 | ||
![]() |
8eae02c037 | ||
![]() |
930fd59298 | ||
![]() |
bf13bac152 | ||
![]() |
649acbae1c | ||
![]() |
05eada427b | ||
![]() |
03caf9d805 | ||
![]() |
d6ea3aab1c | ||
![]() |
f3a330e330 | ||
![]() |
044d2b2b06 | ||
![]() |
fb440b0d2e | ||
![]() |
0de5969ec1 | ||
![]() |
3f98b2785e | ||
![]() |
798868427e | ||
![]() |
c79f643ba7 | ||
![]() |
1db3a14c54 | ||
![]() |
bf6d017ad1 | ||
![]() |
8b1773dd60 | ||
![]() |
a706300598 | ||
![]() |
2541c3c5e6 | ||
![]() |
41a1b99f7d | ||
![]() |
1862a439e2 | ||
![]() |
018ecfbaa0 | ||
![]() |
4c8fd4fc35 | ||
![]() |
35c1b10224 | ||
![]() |
c1c01bef7c | ||
![]() |
a48c3d0ba8 | ||
![]() |
93a9ebc4f6 | ||
![]() |
7cc2bd43c6 | ||
![]() |
393e628721 | ||
![]() |
0bcd28e58c | ||
![]() |
42f5389fb8 | ||
![]() |
041cfe91b4 | ||
![]() |
0f82a4589b | ||
![]() |
4320a4f851 | ||
![]() |
037cbabb32 | ||
![]() |
0dde859582 | ||
![]() |
e59c043fb6 | ||
![]() |
ae928c4397 | ||
![]() |
da41c65128 | ||
![]() |
4d18234714 | ||
![]() |
d254c6464b | ||
![]() |
3a5d50e572 | ||
![]() |
03b6d2f1ab | ||
![]() |
b0397ed3c5 | ||
![]() |
fa70ebcac2 | ||
![]() |
86e0330100 | ||
![]() |
92567b4d7e | ||
![]() |
0ae70fed13 | ||
![]() |
3b7300543a | ||
![]() |
642351af1a | ||
![]() |
121802a683 | ||
![]() |
08cf55e55f | ||
![]() |
3c8c0d78ef | ||
![]() |
c4d18aa9ca | ||
![]() |
2d4a87adc9 | ||
![]() |
bedac71e3d | ||
![]() |
ee4e42e730 | ||
![]() |
0de75f05dd | ||
![]() |
be6dd21e54 | ||
![]() |
927ddb0bde | ||
![]() |
a8fadabaf1 | ||
![]() |
44d0f78c1b | ||
![]() |
38f9a015ca | ||
![]() |
c311cdc6f5 | ||
![]() |
a93e0f3284 | ||
![]() |
14b3065ba4 | ||
![]() |
3ea2d6a0a8 | ||
![]() |
c802290437 | ||
![]() |
f7781defe5 | ||
![]() |
418420523a | ||
![]() |
d342a1f368 | ||
![]() |
81f85361d5 | ||
![]() |
f1621b30ec | ||
![]() |
d4f6a594b6 | ||
![]() |
ff5ba5c131 | ||
![]() |
4243f30308 | ||
![]() |
813e91073d | ||
![]() |
7250f22ff6 | ||
![]() |
db31a53bba | ||
![]() |
3023f235a4 | ||
![]() |
79cd8b4da5 | ||
![]() |
8e4d311cd9 | ||
![]() |
9bd8c86a94 | ||
![]() |
cbc0c1d0b6 | ||
![]() |
49c37857d4 | ||
![]() |
b1139a4bf6 | ||
![]() |
7e8559278e | ||
![]() |
1e7f1c98fc | ||
![]() |
a802f25dd6 | ||
![]() |
f1d6d21d6d | ||
![]() |
a80302c513 | ||
![]() |
1c46949da7 | ||
![]() |
07a56454a0 | ||
![]() |
a0e72d02c8 | ||
![]() |
455a59ca85 | ||
![]() |
46d78af068 | ||
![]() |
08d22fd3df | ||
![]() |
e6c691a8f8 | ||
![]() |
4b0e5c445c | ||
![]() |
eb5cff1045 | ||
![]() |
35c7792aa2 | ||
![]() |
521688d630 | ||
![]() |
75e2845c01 | ||
![]() |
2f96283286 | ||
![]() |
cbe6e9b5f5 | ||
![]() |
2ab79cf474 | ||
![]() |
6ce34aba79 | ||
![]() |
5eeb320b60 | ||
![]() |
93310850d2 | ||
![]() |
a2880b12ca | ||
![]() |
cef2657048 | ||
![]() |
ccd85eb055 | ||
![]() |
303b57779a | ||
![]() |
6279816ecc | ||
![]() |
4ae77261fa | ||
![]() |
4b7d843b78 | ||
![]() |
1c28df65c3 | ||
![]() |
85b740f484 | ||
![]() |
f9929cb27d | ||
![]() |
bafab1ac07 | ||
![]() |
e05c262468 | ||
![]() |
acfb72246c | ||
![]() |
9d51c4c340 | ||
![]() |
18068effec | ||
![]() |
7a3f7d3bba | ||
![]() |
95aa48c456 | ||
![]() |
6ea8ca991b | ||
![]() |
f1e551b960 | ||
![]() |
772c54ec74 | ||
![]() |
13cb789c18 | ||
![]() |
42220c4268 | ||
![]() |
3052506e2e | ||
![]() |
0741daa7eb | ||
![]() |
b4aa554279 | ||
![]() |
8fe2abe0ae | ||
![]() |
5af789ae11 | ||
![]() |
904a168d5c | ||
![]() |
724441eddc | ||
![]() |
f68ab3edd1 | ||
![]() |
68542aca3a | ||
![]() |
594bc4203c | ||
![]() |
57318b022d | ||
![]() |
761159aa93 | ||
![]() |
29dce26bf6 | ||
![]() |
717ab69093 | ||
![]() |
138a2cf08f | ||
![]() |
81daf82647 | ||
![]() |
f3798bfb63 | ||
![]() |
bc07dfad2e | ||
![]() |
8dd1c2a6cc | ||
![]() |
d10b657a54 | ||
![]() |
f90da739eb | ||
![]() |
d9cadf64e8 | ||
![]() |
15d4a55cd8 | ||
![]() |
309cbdb8be | ||
![]() |
39a9ad0ce7 | ||
![]() |
0f3c44c926 | ||
![]() |
a0e7c4a74c | ||
![]() |
7d428030df | ||
![]() |
00c395f689 | ||
![]() |
d8e1c73d26 | ||
![]() |
ffa4cc241b | ||
![]() |
6f1b740c8f | ||
![]() |
3406ba3ebf |
@@ -10,6 +10,3 @@ insert_final_newline = true
|
|||||||
|
|
||||||
[*.md]
|
[*.md]
|
||||||
trim_trailing_whitespace = false
|
trim_trailing_whitespace = false
|
||||||
|
|
||||||
[*.properties]
|
|
||||||
insert_final_newline = false
|
|
||||||
|
1
.github/ISSUE_TEMPLATE/bug_report.md
vendored
1
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -12,4 +12,5 @@ labels: bug
|
|||||||
## Useful information to include:
|
## Useful information to include:
|
||||||
- Minecraft version
|
- Minecraft version
|
||||||
- CC: Restitched version
|
- CC: Restitched version
|
||||||
|
- Logs: These will be located in the `logs/` directory of your Minecraft instance. Please upload them as a gist or directly into this editor.
|
||||||
- Detailed reproduction steps: sometimes I can spot a bug pretty easily, but often it's much more obscure. The more information I have to help reproduce it, the quicker it'll get fixed.
|
- Detailed reproduction steps: sometimes I can spot a bug pretty easily, but often it's much more obscure. The more information I have to help reproduce it, the quicker it'll get fixed.
|
||||||
|
17
.github/matchers/checkstyle.json
vendored
Normal file
17
.github/matchers/checkstyle.json
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"problemMatcher": [
|
||||||
|
{
|
||||||
|
"owner": "checkstyle",
|
||||||
|
"pattern": [
|
||||||
|
{
|
||||||
|
"regexp": "^([a-z]+) ([\\w./-]+):(\\d+):(\\d+): (.*)$",
|
||||||
|
"severity": 1,
|
||||||
|
"file": 2,
|
||||||
|
"line": 3,
|
||||||
|
"column": 4,
|
||||||
|
"message": 5
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
18
.github/matchers/illuaminate.json
vendored
Normal file
18
.github/matchers/illuaminate.json
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"problemMatcher": [
|
||||||
|
{
|
||||||
|
"owner": "illuaminate",
|
||||||
|
"severity": "warning",
|
||||||
|
"pattern": [
|
||||||
|
{
|
||||||
|
"regexp": "^([\\w./-]+):\\[(\\d+):(\\d+)\\-(?:\\d+):(?:\\d+)\\]: (.*) \\[([a-z:-]+)\\]$",
|
||||||
|
"file": 1,
|
||||||
|
"line": 2,
|
||||||
|
"column": 3,
|
||||||
|
"message": 4,
|
||||||
|
"code": 5
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
15
.github/matchers/junit.json
vendored
Normal file
15
.github/matchers/junit.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"problemMatcher": [
|
||||||
|
{
|
||||||
|
"owner": "junit",
|
||||||
|
"pattern": [
|
||||||
|
{
|
||||||
|
"regexp": "^## ([\\w./-]+):(\\d+): (.*)$",
|
||||||
|
"file": 1,
|
||||||
|
"line": 2,
|
||||||
|
"message": 3
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
74
.github/workflows/main-ci.yml
vendored
74
.github/workflows/main-ci.yml
vendored
@@ -3,33 +3,57 @@ name: Build
|
|||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: Build
|
name: Build
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Checkout submodules
|
with:
|
||||||
run: git submodule update --init --recursive
|
submodules: true
|
||||||
|
|
||||||
- name: Set up Java 8
|
- name: Set up Java 16
|
||||||
uses: actions/setup-java@v1
|
uses: actions/setup-java@v1
|
||||||
with:
|
with:
|
||||||
java-version: 8
|
java-version: 16
|
||||||
|
|
||||||
- name: Cache gradle dependencies
|
- name: Cache gradle dependencies
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v2
|
||||||
with:
|
with:
|
||||||
path: ~/.gradle/caches
|
path: ~/.gradle/caches
|
||||||
key: ${{ runner.os }}-gradle-${{ hashFiles('gradle.properties') }}
|
key: ${{ runner.os }}-gradle-${{ hashFiles('gradle.properties') }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-gradle-
|
${{ runner.os }}-gradle-
|
||||||
|
|
||||||
- name: Build with Gradle
|
- name: Disable Gradle daemon
|
||||||
run: ./gradlew build --no-daemon || ./gradlew build --no-daemon
|
run: |
|
||||||
|
mkdir -p ~/.gradle
|
||||||
|
echo "org.gradle.daemon=false" >> ~/.gradle/gradle.properties
|
||||||
|
|
||||||
- name: Upload Jar
|
- name: Build with Gradle
|
||||||
uses: actions/upload-artifact@v1
|
run: |
|
||||||
with:
|
./gradlew assemble || ./gradlew assemble
|
||||||
name: cc-restiched
|
./gradlew build
|
||||||
path: build/libs
|
|
||||||
|
- name: Upload Jar
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: cc-restitched
|
||||||
|
path: build/libs
|
||||||
|
|
||||||
|
- name: Parse test reports
|
||||||
|
run: ./tools/parse-reports.py
|
||||||
|
if: ${{ failure() }}
|
||||||
|
|
||||||
|
- name: Cache pre-commit
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: ~/.cache/pre-commit
|
||||||
|
key: ${{ runner.os }}-pre-commit-${{ hashFiles('config/pre-commit/config.yml') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-pre-commit-
|
||||||
|
|
||||||
|
- name: Run linters
|
||||||
|
run: |
|
||||||
|
pip install pre-commit
|
||||||
|
pre-commit run --config config/pre-commit/config.yml --show-diff-on-failure --all --color=always
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -21,3 +21,4 @@
|
|||||||
.gradle
|
.gradle
|
||||||
*.DS_Store
|
*.DS_Store
|
||||||
.project
|
.project
|
||||||
|
*.launch
|
||||||
|
20
.gitpod.yml
Normal file
20
.gitpod.yml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
image:
|
||||||
|
file: config/gitpod/Dockerfile
|
||||||
|
|
||||||
|
ports:
|
||||||
|
- port: 25565
|
||||||
|
onOpen: notify
|
||||||
|
|
||||||
|
vscode:
|
||||||
|
extensions:
|
||||||
|
- eamodio.gitlens
|
||||||
|
- github.vscode-pull-request-github
|
||||||
|
- ms-azuretools.vscode-docker
|
||||||
|
- redhat.java
|
||||||
|
- richardwillis.vscode-gradle
|
||||||
|
- vscjava.vscode-java-debug
|
||||||
|
- vscode.github
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Setup pre-commit hool
|
||||||
|
init: pre-commit install --config config/pre-commit/config.yml --allow-missing-config
|
12
.vscode/settings.json
vendored
12
.vscode/settings.json
vendored
@@ -1,3 +1,15 @@
|
|||||||
{
|
{
|
||||||
|
"files.exclude": {
|
||||||
|
// Default Java Dev
|
||||||
|
"**/.classpath": true,
|
||||||
|
"**/.project": true,
|
||||||
|
"**/.settings": true,
|
||||||
|
"**/.factorypath": true,
|
||||||
|
|
||||||
|
// Custom Hidden Files
|
||||||
|
"**/.bin": true,
|
||||||
|
"**/.editorconfig": true,
|
||||||
|
},
|
||||||
|
|
||||||
"java.configuration.updateBuildConfiguration": "automatic"
|
"java.configuration.updateBuildConfiguration": "automatic"
|
||||||
}
|
}
|
108
README.md
108
README.md
@@ -1,68 +1,66 @@
|
|||||||
# CC:Restitched Patchwork
|
|
||||||
# CC:R Version VS CC:T Version
|
|
||||||
CC:R Strives to maintaim perfect pairity with CC:R, however in some cases this is not possible, or atleast, not yet, so just because you might be on CC:R 1.96.6, doesnt mean you are on CC:T 1.96.6.
|
|
||||||
|
|
||||||
<img src="logo.png" alt="CC: Restitched" width="100%"/>
|
<img src="logo.png" alt="CC: Restitched" width="100%"/>
|
||||||
|
|
||||||
*it works and runs-ish*
|
[](https://github.com/cc-tweaked/cc-restitched/actions "Current build status")
|
||||||
|
[](https://www.curseforge.com/minecraft/mc-mods/cc-restitched "Download CC: Restitched on CurseForge")
|
||||||
|
[](https://gitpod.io/#https://github.com/cc-tweaked/cc-restitched/tree/1.17.1)
|
||||||
|
|
||||||
[](https://github.com/Merith-TK/cc-restitched/actions "Current build status") [](https://www.curseforge.com/minecraft/mc-mods/cc-restitched-updated "Download CC: Restitched on CurseForge")
|
# What is CC: Restitched?
|
||||||
|
This is a fabric port of [SquidDev-CC/CC-Tweaked](https://github.com/SquidDev-CC/CC-Tweaked). The work is a continuation of [Zundrel/cc-tweaked-fabric](https://github.com/Zundrel/cc-tweaked-fabric).
|
||||||
|
|
||||||
## What?
|
## CC: Restitched vs. CC: Tweaked
|
||||||
This is an fork of [Zundrel/cc-tweaked-fabric](https://github.com/Zundrel/cc-tweaked-fabric) who's goal was to port [SquidDev-CC/CC-Tweaked](https://github.com/SquidDev-CC/CC-Tweaked) to the [Fabric](https://fabricmc.net/) modloader. I picked up maintaining the mod because the team working on Zundrel's fork, admitted they had gotten lethargic so I picked it up to make it equal with CC:T
|
CC: R tries to maintain parity with CC: T, but may be behind or divergent in some areas. If you notice a disparity please open an issue. CC: R major and minor version numbers indicate parity with the major features of that version of CC: T. Patch version numbers will not align.
|
||||||
|
|
||||||
## Resource Packs
|
## Resource Packs
|
||||||
This mod includes textures that are more in-line with the style of Mojang's new texture-artist, Jappa. If you prefer the original textures, enable the "Classic" resource pack provided by the mod.
|
This mod includes textures by [Jummit](https://github.com/Jummit) that are more in line with the style of Mojang's new texture-artist, Jappa. If you prefer the original textures, enable the "Classic" resource pack.
|
||||||
|
|
||||||
<img src="https://raw.githubusercontent.com/3prm3/cc-pack/main/pack.png" alt="CC: Restitched" width="16" height="16"/> [3prm3/cc-pack](https://github.com/3prm3/cc-pack/)
|
<img src="https://raw.githubusercontent.com/3prm3/cc-pack/main/pack.png" alt="CC: Restitched" width="16" height="16"/> We also have a second resourcepack made by [3prm3](https://github.com/3prm3), it features a complete overhaul and can be enabled by enabling the `overhaul` resource pack, go check out his resource pack over [here](https://github.com/3prm3/cc-pack/)!
|
||||||
We also have a second resourcepack made by [3prm3](https://github.com/3prm3), it features a complete overhaul and can be enabled by enabling the `overhaul` resource pack, go check out his resource pack over here!
|
|
||||||
|
|
||||||
## Major Tasks Planned
|
|
||||||
* Rewrite the config system
|
|
||||||
* **Planned for 1.96.0 release**
|
|
||||||
* it currently sets the values that would normally be read from `config/computercraft.json` to the default values, because it does not read the file at all
|
|
||||||
* Fixing `/computercraft` commands,
|
|
||||||
* No clue why they broken, they just are
|
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
Any contribution is welcome, be that using the mod, reporting bugs or contributing code. In order to start helping develop CC:R there are a few rules
|
Any contribution is welcome, be that using the mod, reporting bugs or contributing code. In order to start helping develop CC: R there are a few rules;
|
||||||
1) Any updates that port commits from CC:T, ***MUST*** follow the format defined in [patchwork.md](patchwork.md) otherwise they will not be accepted,
|
1) Make sure your code follows the checkstyle rules. You can test this by running `./gradle build` or `./gradle check`.
|
||||||
* Commit Message must be the same as it is in CC:T,
|
2) Do not alter the lua code unless those changes are taken directly from CC: Tweaked. If you wish to contribute changes to the in game rom please contribute upstream at [CC-Tweaked](https://github.com/SquidDev-CC/CC-Tweaked).
|
||||||
* patchwork.md must be updated in the following format
|
|
||||||
> Comments, optional but useful if you had to do something differently than in CC:T outside of [Fabric](https://fabricmc.net/)/[Forge](https://mcforge.readthedocs.io/en/1.16.x/) differences
|
# Does this work Fabric's many rendering mods?
|
||||||
>
|
* [ YES ] Sodium
|
||||||
> \`\`\`
|
* [ YES ] Optifine
|
||||||
>
|
* Works with VBO Rendering (automatically set)
|
||||||
>commitID
|
* No issues
|
||||||
>
|
* [ EHH ] Iris Shaders
|
||||||
> commit title
|
* "Works" with TBO Rendering (Default)
|
||||||
>
|
* Crashes with VBO Rendering
|
||||||
> commit desc
|
* <details>
|
||||||
>
|
<summary>Shaders are broken</summary>
|
||||||
> \`\`\`
|
|
||||||
2) Follow the [Fabric](https://fabricmc.net/) programming guidelines as close as possible. This means you have to use [`loom`](https://fabricmc.net/wiki/tutorial:mappings) mappings,
|
* Shaders will cause varrying results ranging from monitors being invisible, to straight up crashing.
|
||||||
3) You cannot intentionally implement bugs and security vulnerabilities
|
* Not using shaders will result in odd Z-Fighting of the monitor display and the transparent texture
|
||||||
4) Unless the commit is a ["patchwork"](https://github.com/Merith-TK/cc-restitched/blob/fabric/patchwork.md) compliant commit, (IE: taken from CC:T), the lua code is off limits
|
- 
|
||||||
|
- 
|
||||||
|
</details>
|
||||||
|
* [ YES ] Canvas
|
||||||
|
* Works with TBO Rendering (Default)
|
||||||
|
* Scuffed with VBO Rendering
|
||||||
|
* <details>
|
||||||
|
<summary>VBO is broken</summary>
|
||||||
|
|
||||||
|
Monitors are just... scuffed beyond belief.
|
||||||
|
- 
|
||||||
|
- 
|
||||||
|
* The content to the left is supposed to be on the monitors to the right, also the bottom one is supposed to `black/white` not colored.
|
||||||
|
* Turtle Texture for some reason?
|
||||||
|
- 
|
||||||
|
</details>
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
Any contribution is welcome, be that using the mod, reporting bugs or contributing code. In order to start helping develop CC: R there are a few rules;
|
||||||
|
1) Follow the [Fabric](https://fabricmc.net/) programming guidelines as close as possible. This means you have to use [`loom`](https://fabricmc.net/wiki/tutorial:mappings) mappings, if you use anything else, your code will be rejected.
|
||||||
|
2) You cannot intentionally implement bugs and security vulnerabilities.
|
||||||
|
3) Unless the code is taken directly from CC: Tweaked, `lua` code is offlimits from alteration.
|
||||||
|
|
||||||
## Bleeding Edge Builds
|
## Bleeding Edge Builds
|
||||||
Bleeding edge builds can be found [here](https://github.com/Merith-TK/cc-restitched/actions) at Github Actions.
|
Bleeding edge builds can be found [here](https://github.com/cc-tweaked/cc-restitched/actions) at Github Actions.
|
||||||
|
|
||||||
## Community
|
## Community
|
||||||
If you need help getting started with CC: Tweaked, want to show off your latest project, or just want to chat about ComputerCraft, here is the [Forum](https://forums.computercraft.cc/) and the [Discord](https://discord.gg/H2UyJXe)
|
If you need help getting started with CC: Restitched, want to show off your latest project, or just want to chat about ComputerCraft, here is the [Forum](https://forums.computercraft.cc/) and the [Discord](https://discord.gg/H2UyJXe).
|
||||||
|
|
||||||
## Known Issues
|
## Perpheral mods
|
||||||
Main Known issue
|
Unfortunately, CC: Restitched does not have as many peripherals mods available as CC: Tweaked. If you're an interested mod developer, please check out our `api` package. If you've already made a mod with CC: R peripheral support OR if you're a player who found a mod with ComputerCraft integration, please open an [issue here](https://github.com/cc-tweaked/cc-restitched/issues/new?assignees=&labels=peripheralShoutout&template=peripheral_shoutout.md) to let us know and we'll add it to the list!
|
||||||
* Mods that add blocks that can be used as peripherals for CC:T On forge, don't work with CC:R.
|
|
||||||
* This is because of the differences between forge and fabric, and that mod devs, to my knowledge have not agreed upon a standard method in which to implement cross compatibility between mods,
|
|
||||||
* [Fixed (d10f297c): please report if bug persists]</br> ~~Storage Peripherals throw a java "StackOverflowError" when using `pushItems()`,~~
|
|
||||||
* ~~Work around, you are probably using `pushItems(chest, 1)` or similar. please use `pushItems(chest, 1, nil, 1)`.~~
|
|
||||||
* Computers will not run built in commands, saying "File not found"
|
|
||||||
* This is a know bug, dont know what causes it, but just restart the computer (`ctrl+r` for one second) and it will work again
|
|
||||||
* Occurs when server runs `/reload` or a datapack is updated
|
|
||||||
|
|
||||||
## Perpherals
|
|
||||||
Unfortunately, unlike the original CC:Tweaked project, CC:Restitched, does not have any actual peripheral mods, currently the only one we have is an example for mod devs to get started with making/adding the peripheral API to their mods!
|
|
||||||
|
|
||||||
If your a mod dev made a mod with CC:R peripheral support, OR if your a player who found a mod with CC:R support, please open an [issue here](https://github.com/Merith-TK/cc-restitched/issues/new?assignees=&labels=peripheralShoutout&template=peripheral_shoutout.md) to let us know so we can add it to the list!
|
|
||||||
|
|
||||||
*  [CC Peripheral Test](https://github.com/Toad-Dev/cc-peripheral-test)
|
|
||||||
* This is an example mod for how to make peripherals that work as a block, or as a turtle upgrade!
|
|
||||||
|
241
build.gradle
241
build.gradle
@@ -1,114 +1,243 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'fabric-loom' version '0.6-SNAPSHOT'
|
id "checkstyle"
|
||||||
id 'maven-publish'
|
id "jacoco"
|
||||||
|
id "maven-publish"
|
||||||
|
id "com.github.hierynomus.license" version "0.16.1"
|
||||||
|
id "org.jetbrains.kotlin.jvm" version "1.5.21"
|
||||||
|
id 'fabric-loom' version '0.10-SNAPSHOT'
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
def javaVersion = JavaLanguageVersion.of(17)
|
||||||
targetCompatibility = JavaVersion.VERSION_1_8
|
java {
|
||||||
|
toolchain {
|
||||||
|
languageVersion = javaVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
withSourcesJar()
|
||||||
|
withJavadocJar()
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType(JavaExec).configureEach {
|
||||||
|
javaLauncher = javaToolchains.launcherFor {
|
||||||
|
languageVersion = javaVersion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
version = mod_version
|
version = mod_version
|
||||||
|
|
||||||
group = "dan200.computercraft"
|
group = "dan200.computercraft"
|
||||||
archivesBaseName = "cc-restiched"
|
archivesBaseName = "cc-restitched"
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
main.resources {
|
||||||
|
srcDir 'src/generated/resources'
|
||||||
|
}
|
||||||
|
|
||||||
|
testMod {}
|
||||||
|
}
|
||||||
|
|
||||||
|
loom {
|
||||||
|
accessWidenerPath = file("src/main/resources/cc.accesswidener")
|
||||||
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
jcenter()
|
|
||||||
maven {
|
maven {
|
||||||
name "SquidDev"
|
name "SquidDev"
|
||||||
url "https://squiddev.cc/maven"
|
url "https://squiddev.cc/maven"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Limit these to a set of groups.
|
||||||
|
maven { url "https://maven.shedaniel.me/" }
|
||||||
|
maven { url "https://maven.terraformersmc.com/" }
|
||||||
}
|
}
|
||||||
|
|
||||||
configurations {
|
configurations {
|
||||||
compile.extendsFrom shade
|
shade
|
||||||
|
implementation.extendsFrom shade
|
||||||
|
cctJavadoc
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
checkstyle "com.puppycrawl.tools:checkstyle:8.45"
|
||||||
|
|
||||||
minecraft "com.mojang:minecraft:${mc_version}"
|
minecraft "com.mojang:minecraft:${mc_version}"
|
||||||
mappings "net.fabricmc:yarn:${mc_version}+build.${mappings_version}:v2"
|
mappings loom.officialMojangMappings()
|
||||||
modImplementation "net.fabricmc:fabric-loader:${fabric_loader_version}"
|
modImplementation "net.fabricmc:fabric-loader:${fabric_loader_version}"
|
||||||
modImplementation "net.fabricmc.fabric-api:fabric-api:${fabric_api_version}"
|
modImplementation "net.fabricmc.fabric-api:fabric-api:${fabric_api_version}"
|
||||||
|
|
||||||
compile 'com.electronwill.night-config:json:3.6.0'
|
modApi("me.shedaniel.cloth:cloth-config-fabric:${cloth_config_version}") {
|
||||||
|
exclude(group: "net.fabricmc.fabric-api")
|
||||||
|
}
|
||||||
|
modImplementation "com.terraformersmc:modmenu:${modmenu_version}"
|
||||||
|
modImplementation "me.shedaniel.cloth.api:cloth-utils-v1:${cloth_api_version}"
|
||||||
|
|
||||||
modImplementation "me.shedaniel.cloth:config-2:${cloth_config_version}"
|
implementation 'com.electronwill.night-config:toml:3.6.3'
|
||||||
modImplementation "io.github.prospector:modmenu:${modmenu_version}"
|
|
||||||
|
|
||||||
modApi "me.shedaniel.cloth.api:cloth-utils-v1:${project.cloth_api_version}"
|
compileOnly 'com.google.code.findbugs:jsr305:3.0.2'
|
||||||
include "me.shedaniel.cloth.api:cloth-utils-v1:${project.cloth_api_version}"
|
|
||||||
|
|
||||||
implementation "blue.endless:jankson:${jankson_version}"
|
|
||||||
implementation 'com.google.code.findbugs:jsr305:3.0.2'
|
|
||||||
|
|
||||||
compileOnly 'com.google.auto.service:auto-service:1.0-rc7'
|
|
||||||
annotationProcessor 'com.google.auto.service:auto-service:1.0-rc7'
|
|
||||||
|
|
||||||
include "me.shedaniel.cloth:config-2:${cloth_config_version}"
|
|
||||||
include "blue.endless:jankson:${jankson_version}"
|
|
||||||
include 'javax.vecmath:vecmath:1.5.2'
|
|
||||||
|
|
||||||
compile 'javax.vecmath:vecmath:1.5.2'
|
|
||||||
|
|
||||||
shade 'org.squiddev:Cobalt:0.5.2-SNAPSHOT'
|
shade 'org.squiddev:Cobalt:0.5.2-SNAPSHOT'
|
||||||
|
|
||||||
modRuntime "me.shedaniel:RoughlyEnoughItems-api:5.8.9"
|
include "me.shedaniel.cloth.api:cloth-utils-v1:${cloth_api_version}"
|
||||||
modRuntime "me.shedaniel:RoughlyEnoughItems:5.8.9"
|
include 'com.electronwill.night-config:core:3.6.3'
|
||||||
}
|
include 'com.electronwill.night-config:toml:3.6.3'
|
||||||
|
include "me.shedaniel.cloth:cloth-config-fabric:${cloth_config_version}"
|
||||||
|
|
||||||
sourceSets {
|
//modRuntimeOnly "me.shedaniel:RoughlyEnoughItems-api-fabric:6.0.254-alpha"
|
||||||
main {
|
//modRuntimeOnly "me.shedaniel:RoughlyEnoughItems-fabric:6.0.254-alpha"
|
||||||
java {
|
|
||||||
exclude 'dan200/computercraft/shared/integration'
|
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
|
||||||
}
|
testImplementation 'org.junit.jupiter:junit-jupiter-params:5.7.0'
|
||||||
}
|
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
|
||||||
|
testImplementation 'org.hamcrest:hamcrest:2.2'
|
||||||
|
testImplementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.5.21'
|
||||||
|
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.1'
|
||||||
|
|
||||||
|
cctJavadoc 'cc.tweaked:cct-javadoc:1.4.2'
|
||||||
}
|
}
|
||||||
|
|
||||||
processResources {
|
processResources {
|
||||||
inputs.property "version", project.version
|
inputs.property "version", project.version
|
||||||
|
|
||||||
from(sourceSets.main.resources.srcDirs) {
|
def hash = 'none'
|
||||||
include "fabric.mod.json"
|
Set<String> contributors = []
|
||||||
expand "version": project.version
|
try {
|
||||||
}
|
hash = ["git", "-C", projectDir, "rev-parse", "HEAD"].execute().text.trim()
|
||||||
|
|
||||||
from(sourceSets.main.resources.srcDirs) {
|
def blacklist = ['GitHub', 'dan200', 'Daniel Ratcliffe']
|
||||||
exclude "fabric.mod.json"
|
["git", "-C", projectDir, "log", "--format=tformat:%an%n%cn"].execute().text.split('\n').each {
|
||||||
|
if (!blacklist.contains(it)) contributors.add(it)
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
inputs.property "commithash", hash
|
||||||
|
duplicatesStrategy = DuplicatesStrategy.INCLUDE
|
||||||
|
|
||||||
|
filesMatching(["fabric.mod.json", "data/computercraft/lua/rom/help/credits.txt"]) {
|
||||||
|
expand(
|
||||||
|
'version': mod_version,
|
||||||
|
'mcversion': mc_version,
|
||||||
|
'gitcontributors': contributors.sort(false, String.CASE_INSENSITIVE_ORDER).join('\n')
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensure that the encoding is set to UTF-8, no matter what the system default is
|
|
||||||
// this fixes some edge cases with special characters not displaying correctly
|
|
||||||
// see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html
|
|
||||||
tasks.withType(JavaCompile) {
|
tasks.withType(JavaCompile) {
|
||||||
options.encoding = "UTF-8"
|
options.encoding = "UTF-8"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
|
javadoc {
|
||||||
// if it is present.
|
include "dan200/computercraft/api/**/*.java"
|
||||||
// If you remove this task, sources will not be generated.
|
}
|
||||||
task sourcesJar(type: Jar, dependsOn: classes) {
|
|
||||||
classifier = "sources"
|
task luaJavadoc(type: Javadoc) {
|
||||||
from sourceSets.main.allSource
|
description "Generates documentation for Java-side Lua functions."
|
||||||
|
group "documentation"
|
||||||
|
|
||||||
|
source = sourceSets.main.allJava
|
||||||
|
destinationDir = file("${project.docsDir}/luaJavadoc")
|
||||||
|
classpath = sourceSets.main.compileClasspath
|
||||||
|
|
||||||
|
options.docletpath = configurations.cctJavadoc.files as List
|
||||||
|
options.doclet = "cc.tweaked.javadoc.LuaDoclet"
|
||||||
|
options.noTimestamp = false
|
||||||
|
|
||||||
|
javadocTool = javaToolchains.javadocToolFor {
|
||||||
|
languageVersion = javaVersion
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
jar {
|
jar {
|
||||||
from "LICENSE"
|
from "LICENSE"
|
||||||
|
manifest {
|
||||||
|
attributes([
|
||||||
|
"Specification-Title" : "computercraft",
|
||||||
|
"Specification-Version" : "1",
|
||||||
|
"Implementation-Title" : "CC: Restitched",
|
||||||
|
"Implementation-Version" : "${mod_version}",
|
||||||
|
"Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ")
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
from configurations.shade.collect { it.isDirectory() ? it : zipTree(it) }
|
from configurations.shade.collect { it.isDirectory() ? it : zipTree(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[compileJava, compileTestJava].forEach {
|
||||||
|
it.configure {
|
||||||
|
options.compilerArgs << "-Xlint" << "-Xlint:-processing"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sourcesJar {
|
||||||
|
duplicatesStrategy = DuplicatesStrategy.INCLUDE
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check tasks
|
||||||
|
|
||||||
|
test {
|
||||||
|
useJUnitPlatform()
|
||||||
|
testLogging {
|
||||||
|
events "skipped", "failed"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jacocoTestReport {
|
||||||
|
dependsOn('test')
|
||||||
|
reports {
|
||||||
|
xml.required = true
|
||||||
|
html.required = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
check.dependsOn jacocoTestReport
|
||||||
|
|
||||||
|
import com.hierynomus.gradle.license.tasks.LicenseCheck
|
||||||
|
import com.hierynomus.gradle.license.tasks.LicenseFormat
|
||||||
|
|
||||||
|
license {
|
||||||
|
mapping("java", "SLASHSTAR_STYLE")
|
||||||
|
strictCheck true
|
||||||
|
|
||||||
|
ext.year = Calendar.getInstance().get(Calendar.YEAR)
|
||||||
|
}
|
||||||
|
|
||||||
|
[licenseMain, licenseFormatMain].forEach {
|
||||||
|
it.configure {
|
||||||
|
include("**/*.java")
|
||||||
|
exclude("dan200/computercraft/api/**")
|
||||||
|
header file('config/license/main.txt')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[licenseTest, licenseFormatTest, licenseTestMod, licenseFormatTestMod].forEach {
|
||||||
|
it.configure {
|
||||||
|
include("**/*.java")
|
||||||
|
header file('config/license/main.txt')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gradle.projectsEvaluated {
|
||||||
|
tasks.withType(LicenseFormat) {
|
||||||
|
outputs.upToDateWhen { false }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task licenseAPI(type: LicenseCheck)
|
||||||
|
task licenseFormatAPI(type: LicenseFormat)
|
||||||
|
[licenseAPI, licenseFormatAPI].forEach {
|
||||||
|
it.configure {
|
||||||
|
source = sourceSets.main.java
|
||||||
|
include("dan200/computercraft/api/**")
|
||||||
|
header file('config/license/api.txt')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// configure the maven publication
|
// configure the maven publication
|
||||||
publishing {
|
publishing {
|
||||||
publications {
|
publications {
|
||||||
mavenJava(MavenPublication) {
|
mavenJava(MavenPublication) {
|
||||||
// add all the jars that should be included when publishing to maven
|
from components.java
|
||||||
artifact(remapJar) {
|
|
||||||
builtBy remapJar
|
|
||||||
}
|
|
||||||
artifact(sourcesJar) {
|
|
||||||
builtBy remapSourcesJar
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
176
config/checkstyle/checkstyle.xml
Normal file
176
config/checkstyle/checkstyle.xml
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE module PUBLIC
|
||||||
|
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
|
||||||
|
"https://checkstyle.org/dtds/configuration_1_3.dtd">
|
||||||
|
<module name="Checker">
|
||||||
|
<property name="tabWidth" value="4"/>
|
||||||
|
<property name="charset" value="UTF-8" />
|
||||||
|
|
||||||
|
<module name="SuppressionFilter">
|
||||||
|
<property name="file" value="${config_loc}/suppressions.xml" />
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<module name="BeforeExecutionExclusionFileFilter">
|
||||||
|
<property name="fileNamePattern" value="render_old"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<module name="TreeWalker">
|
||||||
|
<!-- Annotations -->
|
||||||
|
<module name="AnnotationLocation" />
|
||||||
|
<module name="AnnotationUseStyle" />
|
||||||
|
<module name="MissingDeprecated" />
|
||||||
|
<module name="MissingOverride" />
|
||||||
|
|
||||||
|
<!-- Blocks -->
|
||||||
|
<module name="EmptyBlock" />
|
||||||
|
<module name="EmptyCatchBlock">
|
||||||
|
<property name="exceptionVariableName" value="ignored" />
|
||||||
|
</module>
|
||||||
|
<module name="LeftCurly">
|
||||||
|
<property name="option" value="nl" />
|
||||||
|
<!-- The defaults, minus lambdas. -->
|
||||||
|
<property name="tokens" value="ANNOTATION_DEF,CLASS_DEF,CTOR_DEF,ENUM_CONSTANT_DEF,ENUM_DEF,INTERFACE_DEF,LITERAL_CASE,LITERAL_CATCH,LITERAL_DEFAULT,LITERAL_DO,LITERAL_ELSE,LITERAL_FINALLY,LITERAL_FOR,LITERAL_IF,LITERAL_SWITCH,LITERAL_SYNCHRONIZED,LITERAL_TRY,LITERAL_WHILE,METHOD_DEF,OBJBLOCK,STATIC_INIT" />
|
||||||
|
</module>
|
||||||
|
<module name="NeedBraces">
|
||||||
|
<property name="allowSingleLineStatement" value="true"/>
|
||||||
|
</module>
|
||||||
|
<module name="RightCurly">
|
||||||
|
<property name="option" value="alone" />
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<!-- Class design. As if we've ever followed good practice here. -->
|
||||||
|
<module name="FinalClass" />
|
||||||
|
<module name="InterfaceIsType" />
|
||||||
|
<module name="MutableException" />
|
||||||
|
<module name="OneTopLevelClass" />
|
||||||
|
|
||||||
|
<!-- Coding -->
|
||||||
|
<module name="ArrayTrailingComma" />
|
||||||
|
<module name="EqualsHashCode" />
|
||||||
|
<!-- FallThrough does not handle unreachable code well -->
|
||||||
|
<module name="IllegalInstantiation" />
|
||||||
|
<module name="IllegalThrows" />
|
||||||
|
<module name="ModifiedControlVariable" />
|
||||||
|
<module name="NoClone" />
|
||||||
|
<module name="NoFinalizer" />
|
||||||
|
<module name="OneStatementPerLine" />
|
||||||
|
<module name="PackageDeclaration" />
|
||||||
|
<module name="SimplifyBooleanExpression" />
|
||||||
|
<module name="SimplifyBooleanReturn" />
|
||||||
|
<module name="StringLiteralEquality" />
|
||||||
|
<module name="UnnecessaryParentheses">
|
||||||
|
<!-- Default minus LAND. -->
|
||||||
|
<property name="tokens" value="EXPR,IDENT,NUM_DOUBLE,NUM_FLOAT,NUM_INT,NUM_LONG,STRING_LITERAL,LITERAL_NULL,LITERAL_FALSE,LITERAL_TRUE,ASSIGN,BAND_ASSIGN,BOR_ASSIGN,BSR_ASSIGN,BXOR_ASSIGN,DIV_ASSIGN,MINUS_ASSIGN,MOD_ASSIGN,PLUS_ASSIGN,SL_ASSIGN,SR_ASSIGN,STAR_ASSIGN,LAMBDA,TEXT_BLOCK_LITERAL_BEGIN,LITERAL_INSTANCEOF,GT,LT,GE,LE,EQUAL,NOT_EQUAL,UNARY_MINUS,UNARY_PLUS,INC,DEC,LNOT,BNOT,POST_INC,POST_DEC" />
|
||||||
|
</module>
|
||||||
|
<module name="UnnecessarySemicolonAfterTypeMemberDeclaration" />
|
||||||
|
<module name="UnnecessarySemicolonInTryWithResources" />
|
||||||
|
<module name="UnnecessarySemicolonInEnumeration" />
|
||||||
|
|
||||||
|
<!-- Imports -->
|
||||||
|
<module name="CustomImportOrder">
|
||||||
|
<property name="customImportOrderRules"
|
||||||
|
value="THIRD_PARTY_PACKAGE###STANDARD_JAVA_PACKAGE###STATIC"
|
||||||
|
/>
|
||||||
|
</module>
|
||||||
|
<module name="IllegalImport" />
|
||||||
|
<module name="RedundantImport" />
|
||||||
|
<module name="UnusedImports" />
|
||||||
|
|
||||||
|
<!-- Javadoc -->
|
||||||
|
<!-- TODO: Missing* checks for the dan200.computercraft.api package? -->
|
||||||
|
<module name="AtclauseOrder" />
|
||||||
|
<module name="InvalidJavadocPosition" />
|
||||||
|
<module name="JavadocBlockTagLocation" />
|
||||||
|
<module name="JavadocMethod"/>
|
||||||
|
<module name="JavadocType"/>
|
||||||
|
<module name="JavadocStyle" />
|
||||||
|
<module name="NonEmptyAtclauseDescription" />
|
||||||
|
<module name="SingleLineJavadoc" />
|
||||||
|
<module name="SummaryJavadocCheck"/>
|
||||||
|
|
||||||
|
<!-- Misc -->
|
||||||
|
<module name="ArrayTypeStyle" />
|
||||||
|
<module name="CommentsIndentation" />
|
||||||
|
<module name="Indentation" />
|
||||||
|
<module name="OuterTypeFilename" />
|
||||||
|
|
||||||
|
<!-- Modifiers -->
|
||||||
|
<module name="ModifierOrder" />
|
||||||
|
<module name="RedundantModifier" />
|
||||||
|
|
||||||
|
<!-- Naming -->
|
||||||
|
<module name="ClassTypeParameterName" />
|
||||||
|
<module name="InterfaceTypeParameterName" />
|
||||||
|
<module name="LambdaParameterName" />
|
||||||
|
<module name="LocalFinalVariableName" />
|
||||||
|
<module name="LocalVariableName" />
|
||||||
|
<module name="MemberName" />
|
||||||
|
<module name="MethodName" />
|
||||||
|
<module name="MethodTypeParameterName" />
|
||||||
|
<module name="PackageName">
|
||||||
|
<property name="format" value="^dan200\.computercraft(\.[a-z][a-z0-9]*)*" />
|
||||||
|
</module>
|
||||||
|
<module name="ParameterName" />
|
||||||
|
<module name="StaticVariableName">
|
||||||
|
<property name="format" value="^[a-z][a-zA-Z0-9]*|CAPABILITY(_[A-Z_]+)?$" />
|
||||||
|
<property name="applyToPrivate" value="false" />
|
||||||
|
</module>
|
||||||
|
<module name="StaticVariableName">
|
||||||
|
<property name="format" value="^(s_)?[a-z][a-zA-Z0-9]*|CAPABILITY(_[A-Z_]+)?$" />
|
||||||
|
<property name="applyToPrivate" value="true" />
|
||||||
|
</module>
|
||||||
|
<module name="TypeName" />
|
||||||
|
|
||||||
|
<!-- Whitespace -->
|
||||||
|
<module name="EmptyForInitializerPad"/>
|
||||||
|
<module name="EmptyForIteratorPad">
|
||||||
|
<property name="option" value="space"/>
|
||||||
|
</module>
|
||||||
|
<module name="GenericWhitespace" />
|
||||||
|
<module name="MethodParamPad" />
|
||||||
|
<module name="NoLineWrap" />
|
||||||
|
<module name="NoWhitespaceAfter">
|
||||||
|
<property name="tokens" value="AT,INC,DEC,UNARY_MINUS,UNARY_PLUS,BNOT,LNOT,DOT,ARRAY_DECLARATOR,INDEX_OP" />
|
||||||
|
</module>
|
||||||
|
<module name="NoWhitespaceBefore" />
|
||||||
|
<!-- TODO: Decide on an OperatorWrap style. -->
|
||||||
|
<module name="ParenPad">
|
||||||
|
<property name="option" value="space" />
|
||||||
|
<property name="tokens" value="ANNOTATION,ANNOTATION_FIELD_DEF,CTOR_CALL,CTOR_DEF,ENUM_CONSTANT_DEF,LITERAL_CATCH,LITERAL_DO,LITERAL_FOR,LITERAL_IF,LITERAL_NEW,LITERAL_SWITCH,LITERAL_SYNCHRONIZED,LITERAL_WHILE,METHOD_CALL,METHOD_DEF,RESOURCE_SPECIFICATION,SUPER_CTOR_CALL,LAMBDA" />
|
||||||
|
</module>
|
||||||
|
<module name="ParenPad">
|
||||||
|
<property name="option" value="nospace" />
|
||||||
|
<property name="tokens" value="DOT,EXPR,QUESTION" />
|
||||||
|
</module>
|
||||||
|
<module name="SeparatorWrap">
|
||||||
|
<property name="option" value="eol" />
|
||||||
|
<property name="tokens" value="COMMA,SEMI,ELLIPSIS,ARRAY_DECLARATOR,RBRACK,METHOD_REF" />
|
||||||
|
</module>
|
||||||
|
<module name="SeparatorWrap">
|
||||||
|
<property name="option" value="nl" />
|
||||||
|
<property name="tokens" value="DOT,AT" />
|
||||||
|
</module>
|
||||||
|
<module name="SingleSpaceSeparator" />
|
||||||
|
<module name="TypecastParenPad" />
|
||||||
|
<module name="WhitespaceAfter">
|
||||||
|
<property name="tokens" value="COMMA" />
|
||||||
|
</module>
|
||||||
|
<module name="WhitespaceAround">
|
||||||
|
<property name="ignoreEnhancedForColon" value="false" />
|
||||||
|
<!-- Allow empty functions -->
|
||||||
|
<property name="allowEmptyLambdas" value="true" />
|
||||||
|
<property name="allowEmptyMethods" value="true" />
|
||||||
|
<property name="allowEmptyConstructors" value="true" />
|
||||||
|
<property name="allowEmptyTypes" value="true" />
|
||||||
|
|
||||||
|
<property name="tokens" value="ASSIGN,BAND,BAND_ASSIGN,BOR,BOR_ASSIGN,BSR,BSR_ASSIGN,BXOR,BXOR_ASSIGN,COLON,DIV,DIV_ASSIGN,EQUAL,GE,GT,LAMBDA,LAND,LCURLY,LE,LITERAL_RETURN,LOR,LT,MINUS,MINUS_ASSIGN,MOD,MOD_ASSIGN,NOT_EQUAL,PLUS,PLUS_ASSIGN,QUESTION,RCURLY,SL,SLIST,SL_ASSIGN,SR,SR_ASSIGN,STAR,STAR_ASSIGN,LITERAL_ASSERT,TYPE_EXTENSION_AND" />
|
||||||
|
</module>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<module name="FileTabCharacter" />
|
||||||
|
<module name="NewlineAtEndOfFile" />
|
||||||
|
<module name="RegexpSingleline">
|
||||||
|
<property name="format" value="\s+$"/>
|
||||||
|
<property name="message" value="Trailing whitespace"/>
|
||||||
|
</module>
|
||||||
|
</module>
|
15
config/checkstyle/suppressions.xml
Normal file
15
config/checkstyle/suppressions.xml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE suppressions PUBLIC
|
||||||
|
"-//Checkstyle//DTD SuppressionFilter Configuration 1.2//EN"
|
||||||
|
"https://checkstyle.org/dtds/suppressions_1_2.dtd">
|
||||||
|
<suppressions>
|
||||||
|
<!-- All the config options and method fields. -->
|
||||||
|
<suppress checks="StaticVariableName" files=".*[\\/]ComputerCraft.java" />
|
||||||
|
<suppress checks="StaticVariableName" files=".*[\\/]ComputerCraftAPI.java" />
|
||||||
|
|
||||||
|
<!-- Some shadowed fields in mixins can't be renamed -->
|
||||||
|
<suppress checks="StaticVariableName" files=".*[\\/]mixin[\\/].*" />
|
||||||
|
|
||||||
|
<!-- The commands API is documented in Lua. -->
|
||||||
|
<suppress checks="SummaryJavadocCheck" files=".*[\\/]CommandAPI.java" />
|
||||||
|
</suppressions>
|
19
config/gitpod/Dockerfile
Normal file
19
config/gitpod/Dockerfile
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
FROM gitpod/workspace-base
|
||||||
|
|
||||||
|
USER gitpod
|
||||||
|
|
||||||
|
# Install custom tools, runtime, etc. using apt-get
|
||||||
|
# For example, the command below would install "bastet" - a command line tetris clone:
|
||||||
|
#
|
||||||
|
# RUN sudo apt-get -q update && \
|
||||||
|
# sudo apt-get install -yq bastet && \
|
||||||
|
# sudo rm -rf /var/lib/apt/lists/*
|
||||||
|
#
|
||||||
|
# More information: https://www.gitpod.io/docs/config-docker/
|
||||||
|
|
||||||
|
# Install Java 8 and 16
|
||||||
|
RUN sudo apt-get -q update && \
|
||||||
|
sudo apt install -yq openjdk-8-jdk openjdk-16-jdk openjdk-17-jdk
|
||||||
|
|
||||||
|
# This is so that you can use java 8 until such a time as you switch to java 16
|
||||||
|
RUN sudo update-java-alternatives --set java-1.17.0-openjdk-amd64
|
2491
config/idea/codeInspectionSettings.xml
Normal file
2491
config/idea/codeInspectionSettings.xml
Normal file
File diff suppressed because it is too large
Load Diff
61
config/idea/codeStyleSettings.xml
Normal file
61
config/idea/codeStyleSettings.xml
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<code_scheme name="Project" version="173">
|
||||||
|
<JSON>
|
||||||
|
<option name="OBJECT_WRAPPING" value="1" />
|
||||||
|
<option name="ARRAY_WRAPPING" value="1" />
|
||||||
|
</JSON>
|
||||||
|
<JavaCodeStyleSettings>
|
||||||
|
<option name="PACKAGES_TO_USE_IMPORT_ON_DEMAND">
|
||||||
|
<value />
|
||||||
|
</option>
|
||||||
|
<option name="JD_P_AT_EMPTY_LINES" value="false" />
|
||||||
|
<option name="JD_PRESERVE_LINE_FEEDS" value="true" />
|
||||||
|
</JavaCodeStyleSettings>
|
||||||
|
<codeStyleSettings language="JAVA">
|
||||||
|
<option name="KEEP_FIRST_COLUMN_COMMENT" value="false" />
|
||||||
|
<option name="BRACE_STYLE" value="2" />
|
||||||
|
<option name="CLASS_BRACE_STYLE" value="2" />
|
||||||
|
<option name="METHOD_BRACE_STYLE" value="2" />
|
||||||
|
<option name="LAMBDA_BRACE_STYLE" value="5" />
|
||||||
|
<option name="ELSE_ON_NEW_LINE" value="true" />
|
||||||
|
<option name="CATCH_ON_NEW_LINE" value="true" />
|
||||||
|
<option name="FINALLY_ON_NEW_LINE" value="true" />
|
||||||
|
<option name="SPACE_WITHIN_METHOD_CALL_PARENTHESES" value="true" />
|
||||||
|
<option name="SPACE_WITHIN_METHOD_PARENTHESES" value="true" />
|
||||||
|
<option name="SPACE_WITHIN_IF_PARENTHESES" value="true" />
|
||||||
|
<option name="SPACE_WITHIN_WHILE_PARENTHESES" value="true" />
|
||||||
|
<option name="SPACE_WITHIN_FOR_PARENTHESES" value="true" />
|
||||||
|
<option name="SPACE_WITHIN_TRY_PARENTHESES" value="true" />
|
||||||
|
<option name="SPACE_WITHIN_CATCH_PARENTHESES" value="true" />
|
||||||
|
<option name="SPACE_WITHIN_SWITCH_PARENTHESES" value="true" />
|
||||||
|
<option name="SPACE_WITHIN_SYNCHRONIZED_PARENTHESES" value="true" />
|
||||||
|
<option name="SPACE_WITHIN_ARRAY_INITIALIZER_BRACES" value="true" />
|
||||||
|
<option name="SPACE_BEFORE_IF_PARENTHESES" value="false" />
|
||||||
|
<option name="SPACE_BEFORE_WHILE_PARENTHESES" value="false" />
|
||||||
|
<option name="SPACE_BEFORE_FOR_PARENTHESES" value="false" />
|
||||||
|
<option name="SPACE_BEFORE_TRY_PARENTHESES" value="false" />
|
||||||
|
<option name="SPACE_BEFORE_CATCH_PARENTHESES" value="false" />
|
||||||
|
<option name="SPACE_BEFORE_SWITCH_PARENTHESES" value="false" />
|
||||||
|
<option name="SPACE_BEFORE_SYNCHRONIZED_PARENTHESES" value="false" />
|
||||||
|
<option name="SPACE_BEFORE_ARRAY_INITIALIZER_LBRACE" value="true" />
|
||||||
|
<option name="KEEP_SIMPLE_METHODS_IN_ONE_LINE" value="true" />
|
||||||
|
<option name="KEEP_SIMPLE_LAMBDAS_IN_ONE_LINE" value="true" />
|
||||||
|
<option name="KEEP_SIMPLE_CLASSES_IN_ONE_LINE" value="true" />
|
||||||
|
<option name="IF_BRACE_FORCE" value="1" />
|
||||||
|
<option name="DOWHILE_BRACE_FORCE" value="1" />
|
||||||
|
<option name="WHILE_BRACE_FORCE" value="1" />
|
||||||
|
<option name="FOR_BRACE_FORCE" value="1" />
|
||||||
|
<option name="SPACE_WITHIN_ANNOTATION_PARENTHESES" value="true" />
|
||||||
|
<indentOptions>
|
||||||
|
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||||
|
</indentOptions>
|
||||||
|
</codeStyleSettings>
|
||||||
|
<codeStyleSettings language="JSON">
|
||||||
|
<option name="KEEP_BLANK_LINES_IN_CODE" value="1" />
|
||||||
|
<option name="SPACE_WITHIN_BRACKETS" value="true" />
|
||||||
|
<option name="SPACE_WITHIN_BRACES" value="true" />
|
||||||
|
<indentOptions>
|
||||||
|
<option name="INDENT_SIZE" value="4" />
|
||||||
|
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||||
|
</indentOptions>
|
||||||
|
</codeStyleSettings>
|
||||||
|
</code_scheme>
|
3
config/license/api.txt
Normal file
3
config/license/api.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||||
|
Copyright Daniel Ratcliffe, 2011-${year}. This API may be redistributed unmodified and in full only.
|
||||||
|
For help using the API, and posting your mods, visit the forums at computercraft.info.
|
3
config/license/main.txt
Normal file
3
config/license/main.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
This file is part of ComputerCraft - http://www.computercraft.info
|
||||||
|
Copyright Daniel Ratcliffe, 2011-${year}. Do not distribute without permission.
|
||||||
|
Send enquiries to dratcliffe@gmail.com
|
57
config/pre-commit/config.yml
Normal file
57
config/pre-commit/config.yml
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
# See https://pre-commit.com for more information
|
||||||
|
# See https://pre-commit.com/hooks.html for more hooks
|
||||||
|
repos:
|
||||||
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
|
rev: v4.0.1
|
||||||
|
hooks:
|
||||||
|
- id: trailing-whitespace
|
||||||
|
- id: end-of-file-fixer
|
||||||
|
- id: check-merge-conflict
|
||||||
|
|
||||||
|
# Quick syntax checkers
|
||||||
|
- id: check-xml
|
||||||
|
- id: check-yaml
|
||||||
|
- id: check-toml
|
||||||
|
- id: check-json
|
||||||
|
exclude: "tsconfig\\.json$"
|
||||||
|
|
||||||
|
- repo: https://github.com/editorconfig-checker/editorconfig-checker.python
|
||||||
|
rev: 2.3.54
|
||||||
|
hooks:
|
||||||
|
- id: editorconfig-checker
|
||||||
|
args: ['-disable-indentation']
|
||||||
|
exclude: "^(.*\\.(bat)|LICENSE)$"
|
||||||
|
|
||||||
|
- repo: local
|
||||||
|
hooks:
|
||||||
|
- id: checkstyle
|
||||||
|
name: Check Java codestyle
|
||||||
|
files: ".*\\.java$"
|
||||||
|
language: system
|
||||||
|
entry: ./gradlew checkstyleMain checkstyleTest
|
||||||
|
pass_filenames: false
|
||||||
|
require_serial: true
|
||||||
|
- id: license
|
||||||
|
name: Check Java license headers
|
||||||
|
files: ".*\\.java$"
|
||||||
|
language: system
|
||||||
|
entry: ./gradlew licenseFormat
|
||||||
|
pass_filenames: false
|
||||||
|
require_serial: true
|
||||||
|
- id: illuaminate
|
||||||
|
name: Check Lua code
|
||||||
|
files: ".*\\.(lua|java|md)"
|
||||||
|
language: script
|
||||||
|
entry: config/pre-commit/illuaminate-lint.sh
|
||||||
|
pass_filenames: false
|
||||||
|
require_serial: true
|
||||||
|
|
||||||
|
exclude: |
|
||||||
|
(?x)^(
|
||||||
|
src/generated|
|
||||||
|
src/test/resources/test-rom/data/json-parsing/|
|
||||||
|
src/test/server-files/|
|
||||||
|
config/idea/|
|
||||||
|
.vscode/|
|
||||||
|
.*\.dfpwm
|
||||||
|
)
|
16
config/pre-commit/illuaminate-lint.sh
Executable file
16
config/pre-commit/illuaminate-lint.sh
Executable file
@@ -0,0 +1,16 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
test -d bin || mkdir bin
|
||||||
|
test -f bin/illuaminate || curl -s -obin/illuaminate https://squiddev.cc/illuaminate/linux-x86-64/illuaminate
|
||||||
|
chmod +x bin/illuaminate
|
||||||
|
|
||||||
|
if [ -n ${GITHUB_ACTIONS+x} ]; then
|
||||||
|
# Register a problem matcher (see https://github.com/actions/toolkit/blob/master/docs/problem-matchers.md)
|
||||||
|
# for illuaminate.
|
||||||
|
echo "::add-matcher::.github/matchers/illuaminate.json"
|
||||||
|
trap 'echo "::remove-matcher owner=illuaminate::"' EXIT
|
||||||
|
fi
|
||||||
|
|
||||||
|
./gradlew luaJavadoc
|
||||||
|
bin/illuaminate lint
|
21
doc/events/alarm.md
Normal file
21
doc/events/alarm.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
module: [kind=event] alarm
|
||||||
|
see: os.setAlarm To start an alarm.
|
||||||
|
---
|
||||||
|
|
||||||
|
The @{timer} event is fired when an alarm started with @{os.setAlarm} completes.
|
||||||
|
|
||||||
|
## Return Values
|
||||||
|
1. @{string}: The event name.
|
||||||
|
2. @{number}: The ID of the alarm that finished.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
Starts a timer and then prints its ID:
|
||||||
|
```lua
|
||||||
|
local alarmID = os.setAlarm(os.time() + 0.05)
|
||||||
|
local event, id
|
||||||
|
repeat
|
||||||
|
event, id = os.pullEvent("alarm")
|
||||||
|
until id == alarmID
|
||||||
|
print("Alarm with ID " .. id .. " was fired")
|
||||||
|
```
|
24
doc/events/char.md
Normal file
24
doc/events/char.md
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
---
|
||||||
|
module: [kind=event] char
|
||||||
|
see: key To listen to any key press.
|
||||||
|
---
|
||||||
|
|
||||||
|
The @{char} event is fired when a character is _typed_ on the keyboard.
|
||||||
|
|
||||||
|
The @{char} event is different to a key press. Sometimes multiple key presses may result in one character being
|
||||||
|
typed (for instance, on some European keyboards). Similarly, some keys (e.g. <kbd>Ctrl</kbd>) do not have any
|
||||||
|
corresponding character. The @{key} should be used if you want to listen to key presses themselves.
|
||||||
|
|
||||||
|
## Return values
|
||||||
|
1. @{string}: The event name.
|
||||||
|
2. @{string}: The string representing the character that was pressed.
|
||||||
|
|
||||||
|
|
||||||
|
## Example
|
||||||
|
Prints each character the user presses:
|
||||||
|
```lua
|
||||||
|
while true do
|
||||||
|
local event, character = os.pullEvent("char")
|
||||||
|
print(character .. " was pressed.")
|
||||||
|
end
|
||||||
|
```
|
18
doc/events/computer_command.md
Normal file
18
doc/events/computer_command.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
module: [kind=event] computer_command
|
||||||
|
---
|
||||||
|
|
||||||
|
The @{computer_command} event is fired when the `/computercraft queue` command is run for the current computer.
|
||||||
|
|
||||||
|
## Return Values
|
||||||
|
1. @{string}: The event name.
|
||||||
|
... @{string}: The arguments passed to the command.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
Prints the contents of messages sent:
|
||||||
|
```lua
|
||||||
|
while true do
|
||||||
|
local event = {os.pullEvent("computer_command")}
|
||||||
|
print("Received message:", table.unpack(event, 2))
|
||||||
|
end
|
||||||
|
```
|
19
doc/events/disk.md
Normal file
19
doc/events/disk.md
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
module: [kind=event] disk
|
||||||
|
see: disk_eject For the event sent when a disk is removed.
|
||||||
|
---
|
||||||
|
|
||||||
|
The @{disk} event is fired when a disk is inserted into an adjacent or networked disk drive.
|
||||||
|
|
||||||
|
## Return Values
|
||||||
|
1. @{string}: The event name.
|
||||||
|
2. @{string}: The side of the disk drive that had a disk inserted.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
Prints a message when a disk is inserted:
|
||||||
|
```lua
|
||||||
|
while true do
|
||||||
|
local event, side = os.pullEvent("disk")
|
||||||
|
print("Inserted a disk on side " .. side)
|
||||||
|
end
|
||||||
|
```
|
19
doc/events/disk_eject.md
Normal file
19
doc/events/disk_eject.md
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
module: [kind=event] disk_eject
|
||||||
|
see: disk For the event sent when a disk is inserted.
|
||||||
|
---
|
||||||
|
|
||||||
|
The @{disk_eject} event is fired when a disk is removed from an adjacent or networked disk drive.
|
||||||
|
|
||||||
|
## Return Values
|
||||||
|
1. @{string}: The event name.
|
||||||
|
2. @{string}: The side of the disk drive that had a disk removed.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
Prints a message when a disk is removed:
|
||||||
|
```lua
|
||||||
|
while true do
|
||||||
|
local event, side = os.pullEvent("disk_eject")
|
||||||
|
print("Removed a disk on side " .. side)
|
||||||
|
end
|
||||||
|
```
|
14
doc/events/http_check.md
Normal file
14
doc/events/http_check.md
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
module: [kind=event] http_check
|
||||||
|
see: http.checkURLAsync To check a URL asynchronously.
|
||||||
|
---
|
||||||
|
|
||||||
|
The @{http_check} event is fired when a URL check finishes.
|
||||||
|
|
||||||
|
This event is normally handled inside @{http.checkURL}, but it can still be seen when using @{http.checkURLAsync}.
|
||||||
|
|
||||||
|
## Return Values
|
||||||
|
1. @{string}: The event name.
|
||||||
|
2. @{string}: The URL requested to be checked.
|
||||||
|
3. @{boolean}: Whether the check succeeded.
|
||||||
|
4. @{string|nil}: If the check failed, a reason explaining why the check failed.
|
39
doc/events/http_failure.md
Normal file
39
doc/events/http_failure.md
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
---
|
||||||
|
module: [kind=event] http_failure
|
||||||
|
see: http.request To send an HTTP request.
|
||||||
|
---
|
||||||
|
|
||||||
|
The @{http_failure} event is fired when an HTTP request fails.
|
||||||
|
|
||||||
|
This event is normally handled inside @{http.get} and @{http.post}, but it can still be seen when using @{http.request}.
|
||||||
|
|
||||||
|
## Return Values
|
||||||
|
1. @{string}: The event name.
|
||||||
|
2. @{string}: The URL of the site requested.
|
||||||
|
3. @{string}: An error describing the failure.
|
||||||
|
4. @{http.Response|nil}: A response handle if the connection succeeded, but the server's response indicated failure.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
Prints an error why the website cannot be contacted:
|
||||||
|
```lua
|
||||||
|
local myURL = "https://does.not.exist.tweaked.cc"
|
||||||
|
http.request(myURL)
|
||||||
|
local event, url, err
|
||||||
|
repeat
|
||||||
|
event, url, err = os.pullEvent("http_failure")
|
||||||
|
until url == myURL
|
||||||
|
print("The URL " .. url .. " could not be reached: " .. err)
|
||||||
|
```
|
||||||
|
|
||||||
|
Prints the contents of a webpage that does not exist:
|
||||||
|
```lua
|
||||||
|
local myURL = "https://tweaked.cc/this/does/not/exist"
|
||||||
|
http.request(myURL)
|
||||||
|
local event, url, err, handle
|
||||||
|
repeat
|
||||||
|
event, url, err, handle = os.pullEvent("http_failure")
|
||||||
|
until url == myURL
|
||||||
|
print("The URL " .. url .. " could not be reached: " .. err)
|
||||||
|
print(handle.getResponseCode())
|
||||||
|
handle.close()
|
||||||
|
```
|
27
doc/events/http_success.md
Normal file
27
doc/events/http_success.md
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
---
|
||||||
|
module: [kind=event] http_success
|
||||||
|
see: http.request To make an HTTP request.
|
||||||
|
---
|
||||||
|
|
||||||
|
The @{http_success} event is fired when an HTTP request returns successfully.
|
||||||
|
|
||||||
|
This event is normally handled inside @{http.get} and @{http.post}, but it can still be seen when using @{http.request}.
|
||||||
|
|
||||||
|
## Return Values
|
||||||
|
1. @{string}: The event name.
|
||||||
|
2. @{string}: The URL of the site requested.
|
||||||
|
3. @{http.Response}: The handle for the response text.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
Prints the content of a website (this may fail if the request fails):
|
||||||
|
```lua
|
||||||
|
local myURL = "https://tweaked.cc/"
|
||||||
|
http.request(myURL)
|
||||||
|
local event, url, handle
|
||||||
|
repeat
|
||||||
|
event, url, handle = os.pullEvent("http_success")
|
||||||
|
until url == myURL
|
||||||
|
print("Contents of " .. url .. ":")
|
||||||
|
print(handle.readAll())
|
||||||
|
handle.close()
|
||||||
|
```
|
26
doc/events/key.md
Normal file
26
doc/events/key.md
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
---
|
||||||
|
module: [kind=event] key
|
||||||
|
---
|
||||||
|
|
||||||
|
This event is fired when any key is pressed while the terminal is focused.
|
||||||
|
|
||||||
|
This event returns a numerical "key code" (for instance, <kbd>F1</kbd> is 290). This value may vary between versions and
|
||||||
|
so it is recommended to use the constants in the @{keys} API rather than hard coding numeric values.
|
||||||
|
|
||||||
|
If the button pressed represented a printable character, then the @{key} event will be followed immediately by a @{char}
|
||||||
|
event. If you are consuming text input, use a @{char} event instead!
|
||||||
|
|
||||||
|
## Return values
|
||||||
|
1. @{string}: The event name.
|
||||||
|
2. @{number}: The numerical key value of the key pressed.
|
||||||
|
3. @{boolean}: Whether the key event was generated while holding the key (@{true}), rather than pressing it the first time (@{false}).
|
||||||
|
|
||||||
|
## Example
|
||||||
|
Prints each key when the user presses it, and if the key is being held.
|
||||||
|
|
||||||
|
```lua
|
||||||
|
while true do
|
||||||
|
local event, key, is_held = os.pullEvent("key")
|
||||||
|
print(("%s held=%s"):format(keys.getName(key), is_held))
|
||||||
|
end
|
||||||
|
```
|
24
doc/events/key_up.md
Normal file
24
doc/events/key_up.md
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
---
|
||||||
|
module: [kind=event] key_up
|
||||||
|
see: keys For a lookup table of the given keys.
|
||||||
|
---
|
||||||
|
|
||||||
|
Fired whenever a key is released (or the terminal is closed while a key was being pressed).
|
||||||
|
|
||||||
|
This event returns a numerical "key code" (for instance, <kbd>F1</kbd> is 290). This value may vary between versions and
|
||||||
|
so it is recommended to use the constants in the @{keys} API rather than hard coding numeric values.
|
||||||
|
|
||||||
|
## Return values
|
||||||
|
1. @{string}: The event name.
|
||||||
|
2. @{number}: The numerical key value of the key pressed.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
Prints each key released on the keyboard whenever a @{key_up} event is fired.
|
||||||
|
|
||||||
|
```lua
|
||||||
|
while true do
|
||||||
|
local event, key = os.pullEvent("key_up")
|
||||||
|
local name = keys.getName(key) or "unknown key"
|
||||||
|
print(name .. " was released.")
|
||||||
|
end
|
||||||
|
```
|
26
doc/events/modem_message.md
Normal file
26
doc/events/modem_message.md
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
---
|
||||||
|
module: [kind=event] modem_message
|
||||||
|
---
|
||||||
|
|
||||||
|
The @{modem_message} event is fired when a message is received on an open channel on any @{modem}.
|
||||||
|
|
||||||
|
## Return Values
|
||||||
|
1. @{string}: The event name.
|
||||||
|
2. @{string}: The side of the modem that received the message.
|
||||||
|
3. @{number}: The channel that the message was sent on.
|
||||||
|
4. @{number}: The reply channel set by the sender.
|
||||||
|
5. @{any}: The message as sent by the sender.
|
||||||
|
6. @{number}: The distance between the sender and the receiver, in blocks.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
Wraps a @{modem} peripheral, opens channel 0 for listening, and prints all received messages.
|
||||||
|
|
||||||
|
```lua
|
||||||
|
local modem = peripheral.find("modem") or error("No modem attached", 0)
|
||||||
|
modem.open(0)
|
||||||
|
|
||||||
|
while true do
|
||||||
|
local event, side, channel, replyChannel, message, distance = os.pullEvent("modem_message")
|
||||||
|
print(("Message received on side %s on channel %d (reply to %d) from %f blocks away with message %s"):format(side, channel, replyChannel, distance, tostring(message)))
|
||||||
|
end
|
||||||
|
```
|
18
doc/events/monitor_resize.md
Normal file
18
doc/events/monitor_resize.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
module: [kind=event] monitor_resize
|
||||||
|
---
|
||||||
|
|
||||||
|
The @{monitor_resize} event is fired when an adjacent or networked monitor's size is changed.
|
||||||
|
|
||||||
|
## Return Values
|
||||||
|
1. @{string}: The event name.
|
||||||
|
2. @{string}: The side or network ID of the monitor that resized.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
Prints a message when a monitor is resized:
|
||||||
|
```lua
|
||||||
|
while true do
|
||||||
|
local event, side = os.pullEvent("monitor_resize")
|
||||||
|
print("The monitor on side " .. side .. " was resized.")
|
||||||
|
end
|
||||||
|
```
|
20
doc/events/monitor_touch.md
Normal file
20
doc/events/monitor_touch.md
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
module: [kind=event] monitor_touch
|
||||||
|
---
|
||||||
|
|
||||||
|
The @{monitor_touch} event is fired when an adjacent or networked Advanced Monitor is right-clicked.
|
||||||
|
|
||||||
|
## Return Values
|
||||||
|
1. @{string}: The event name.
|
||||||
|
2. @{string}: The side or network ID of the monitor that was touched.
|
||||||
|
3. @{number}: The X coordinate of the touch, in characters.
|
||||||
|
4. @{number}: The Y coordinate of the touch, in characters.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
Prints a message when a monitor is touched:
|
||||||
|
```lua
|
||||||
|
while true do
|
||||||
|
local event, side, x, y = os.pullEvent("monitor_touch")
|
||||||
|
print("The monitor on side " .. side .. " was touched at (" .. x .. ", " .. y .. ")")
|
||||||
|
end
|
||||||
|
```
|
34
doc/events/mouse_click.md
Normal file
34
doc/events/mouse_click.md
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
---
|
||||||
|
module: [kind=event] mouse_click
|
||||||
|
---
|
||||||
|
|
||||||
|
This event is fired when the terminal is clicked with a mouse. This event is only fired on advanced computers (including
|
||||||
|
advanced turtles and pocket computers).
|
||||||
|
|
||||||
|
## Return values
|
||||||
|
1. @{string}: The event name.
|
||||||
|
2. @{number}: The mouse button that was clicked.
|
||||||
|
3. @{number}: The X-coordinate of the click.
|
||||||
|
4. @{number}: The Y-coordinate of the click.
|
||||||
|
|
||||||
|
## Mouse buttons
|
||||||
|
Several mouse events (@{mouse_click}, @{mouse_up}, @{mouse_scroll}) contain a "mouse button" code. This takes a
|
||||||
|
numerical value depending on which button on your mouse was last pressed when this event occurred.
|
||||||
|
|
||||||
|
<table class="pretty-table">
|
||||||
|
<!-- Our markdown parser doesn't work on tables!? Guess I'll have to roll my own soonish :/. -->
|
||||||
|
<tr><th>Button code</th><th>Mouse button</th></tr>
|
||||||
|
<tr><td align="right">1</td><td>Left button</td></tr>
|
||||||
|
<tr><td align="right">2</td><td>Middle button</td></tr>
|
||||||
|
<tr><td align="right">3</td><td>Right button</td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
## Example
|
||||||
|
Print the button and the coordinates whenever the mouse is clicked.
|
||||||
|
|
||||||
|
```lua
|
||||||
|
while true do
|
||||||
|
local event, button, x, y = os.pullEvent("mouse_click")
|
||||||
|
print(("The mouse button %s was pressed at %d, %d"):format(button, x, y))
|
||||||
|
end
|
||||||
|
```
|
22
doc/events/mouse_drag.md
Normal file
22
doc/events/mouse_drag.md
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
module: [kind=event] mouse_drag
|
||||||
|
see: mouse_click For when a mouse button is initially pressed.
|
||||||
|
---
|
||||||
|
|
||||||
|
This event is fired every time the mouse is moved while a mouse button is being held.
|
||||||
|
|
||||||
|
## Return values
|
||||||
|
1. @{string}: The event name.
|
||||||
|
2. @{number}: The [mouse button](mouse_click.html#Mouse_buttons) that is being pressed.
|
||||||
|
3. @{number}: The X-coordinate of the mouse.
|
||||||
|
4. @{number}: The Y-coordinate of the mouse.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
Print the button and the coordinates whenever the mouse is dragged.
|
||||||
|
|
||||||
|
```lua
|
||||||
|
while true do
|
||||||
|
local event, button, x, y = os.pullEvent("mouse_drag")
|
||||||
|
print(("The mouse button %s was dragged at %d, %d"):format(button, x, y))
|
||||||
|
end
|
||||||
|
```
|
21
doc/events/mouse_scroll.md
Normal file
21
doc/events/mouse_scroll.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
module: [kind=event] mouse_scroll
|
||||||
|
---
|
||||||
|
|
||||||
|
This event is fired when a mouse wheel is scrolled in the terminal.
|
||||||
|
|
||||||
|
## Return values
|
||||||
|
1. @{string}: The event name.
|
||||||
|
2. @{number}: The direction of the scroll. (-1 = up, 1 = down)
|
||||||
|
3. @{number}: The X-coordinate of the mouse when scrolling.
|
||||||
|
4. @{number}: The Y-coordinate of the mouse when scrolling.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
Prints the direction of each scroll, and the position of the mouse at the time.
|
||||||
|
|
||||||
|
```lua
|
||||||
|
while true do
|
||||||
|
local event, dir, x, y = os.pullEvent("mouse_scroll")
|
||||||
|
print(("The mouse was scrolled in direction %s at %d, %d"):format(dir, x, y))
|
||||||
|
end
|
||||||
|
```
|
21
doc/events/mouse_up.md
Normal file
21
doc/events/mouse_up.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
module: [kind=event] mouse_up
|
||||||
|
---
|
||||||
|
|
||||||
|
This event is fired when a mouse button is released or a held mouse leaves the computer's terminal.
|
||||||
|
|
||||||
|
## Return values
|
||||||
|
1. @{string}: The event name.
|
||||||
|
2. @{number}: The [mouse button](mouse_click.html#Mouse_buttons) that was released.
|
||||||
|
3. @{number}: The X-coordinate of the mouse.
|
||||||
|
4. @{number}: The Y-coordinate of the mouse.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
Prints the coordinates and button number whenever the mouse is released.
|
||||||
|
|
||||||
|
```lua
|
||||||
|
while true do
|
||||||
|
local event, button, x, y = os.pullEvent("mouse_up")
|
||||||
|
print(("The mouse button %s was released at %d, %d"):format(button, x, y))
|
||||||
|
end
|
||||||
|
```
|
18
doc/events/paste.md
Normal file
18
doc/events/paste.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
module: [kind=event] paste
|
||||||
|
---
|
||||||
|
|
||||||
|
The @{paste} event is fired when text is pasted into the computer through Ctrl-V (or ⌘V on Mac).
|
||||||
|
|
||||||
|
## Return values
|
||||||
|
1. @{string}: The event name.
|
||||||
|
2. @{string} The text that was pasted.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
Prints pasted text:
|
||||||
|
```lua
|
||||||
|
while true do
|
||||||
|
local event, text = os.pullEvent("paste")
|
||||||
|
print('"' .. text .. '" was pasted')
|
||||||
|
end
|
||||||
|
```
|
19
doc/events/peripheral.md
Normal file
19
doc/events/peripheral.md
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
module: [kind=event] peripheral
|
||||||
|
see: peripheral_detach For the event fired when a peripheral is detached.
|
||||||
|
---
|
||||||
|
|
||||||
|
The @{peripheral} event is fired when a peripheral is attached on a side or to a modem.
|
||||||
|
|
||||||
|
## Return Values
|
||||||
|
1. @{string}: The event name.
|
||||||
|
2. @{string}: The side the peripheral was attached to.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
Prints a message when a peripheral is attached:
|
||||||
|
```lua
|
||||||
|
while true do
|
||||||
|
local event, side = os.pullEvent("peripheral")
|
||||||
|
print("A peripheral was attached on side " .. side)
|
||||||
|
end
|
||||||
|
```
|
19
doc/events/peripheral_detach.md
Normal file
19
doc/events/peripheral_detach.md
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
module: [kind=event] peripheral_detach
|
||||||
|
see: peripheral For the event fired when a peripheral is attached.
|
||||||
|
---
|
||||||
|
|
||||||
|
The @{peripheral_detach} event is fired when a peripheral is detached from a side or from a modem.
|
||||||
|
|
||||||
|
## Return Values
|
||||||
|
1. @{string}: The event name.
|
||||||
|
2. @{string}: The side the peripheral was detached from.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
Prints a message when a peripheral is detached:
|
||||||
|
```lua
|
||||||
|
while true do
|
||||||
|
local event, side = os.pullEvent("peripheral_detach")
|
||||||
|
print("A peripheral was detached on side " .. side)
|
||||||
|
end
|
||||||
|
```
|
30
doc/events/rednet_message.md
Normal file
30
doc/events/rednet_message.md
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
---
|
||||||
|
module: [kind=event] rednet_message
|
||||||
|
see: modem_message For raw modem messages sent outside of Rednet.
|
||||||
|
see: rednet.receive To wait for a Rednet message with an optional timeout and protocol filter.
|
||||||
|
---
|
||||||
|
|
||||||
|
The @{rednet_message} event is fired when a message is sent over Rednet.
|
||||||
|
|
||||||
|
This event is usually handled by @{rednet.receive}, but it can also be pulled manually.
|
||||||
|
|
||||||
|
@{rednet_message} events are sent by @{rednet.run} in the top-level coroutine in response to @{modem_message} events. A @{rednet_message} event is always preceded by a @{modem_message} event. They are generated inside CraftOS rather than being sent by the ComputerCraft machine.
|
||||||
|
|
||||||
|
## Return Values
|
||||||
|
1. @{string}: The event name.
|
||||||
|
2. @{number}: The ID of the sending computer.
|
||||||
|
3. @{any}: The message sent.
|
||||||
|
4. @{string|nil}: The protocol of the message, if provided.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
Prints a message when one is sent:
|
||||||
|
```lua
|
||||||
|
while true do
|
||||||
|
local event, sender, message, protocol = os.pullEvent("rednet_message")
|
||||||
|
if protocol ~= nil then
|
||||||
|
print("Received message from " .. sender .. " with protocol " .. protocol .. " and message " .. tostring(message))
|
||||||
|
else
|
||||||
|
print("Received message from " .. sender .. " with message " .. tostring(message))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
14
doc/events/redstone.md
Normal file
14
doc/events/redstone.md
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
module: [kind=event] redstone
|
||||||
|
---
|
||||||
|
|
||||||
|
The @{event!redstone} event is fired whenever any redstone inputs on the computer change.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
Prints a message when a redstone input changes:
|
||||||
|
```lua
|
||||||
|
while true do
|
||||||
|
os.pullEvent("redstone")
|
||||||
|
print("A redstone input has changed!")
|
||||||
|
end
|
||||||
|
```
|
27
doc/events/speaker_audio_empty.md
Normal file
27
doc/events/speaker_audio_empty.md
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
---
|
||||||
|
module: [kind=event] speaker_audio_empty
|
||||||
|
see: speaker.playAudio To play audio using the speaker
|
||||||
|
---
|
||||||
|
|
||||||
|
## Return Values
|
||||||
|
1. @{string}: The event name.
|
||||||
|
2. @{string}: The name of the speaker which is available to play more audio.
|
||||||
|
|
||||||
|
|
||||||
|
## Example
|
||||||
|
This uses @{io.lines} to read audio data in blocks of 16KiB from "example_song.dfpwm", and then attempts to play it
|
||||||
|
using @{speaker.playAudio}. If the speaker's buffer is full, it waits for an event and tries again.
|
||||||
|
|
||||||
|
```lua {data-peripheral=speaker}
|
||||||
|
local dfpwm = require("cc.audio.dfpwm")
|
||||||
|
local speaker = peripheral.find("speaker")
|
||||||
|
|
||||||
|
local decoder = dfpwm.make_decoder()
|
||||||
|
for chunk in io.lines("data/example.dfpwm", 16 * 1024) do
|
||||||
|
local buffer = decoder(chunk)
|
||||||
|
|
||||||
|
while not speaker.playAudio(buffer) do
|
||||||
|
os.pullEvent("speaker_audio_empty")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
28
doc/events/task_complete.md
Normal file
28
doc/events/task_complete.md
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
module: [kind=event] task_complete
|
||||||
|
see: commands.execAsync To run a command which fires a task_complete event.
|
||||||
|
---
|
||||||
|
|
||||||
|
The @{task_complete} event is fired when an asynchronous task completes. This is usually handled inside the function call that queued the task; however, functions such as @{commands.execAsync} return immediately so the user can wait for completion.
|
||||||
|
|
||||||
|
## Return Values
|
||||||
|
1. @{string}: The event name.
|
||||||
|
2. @{number}: The ID of the task that completed.
|
||||||
|
3. @{boolean}: Whether the command succeeded.
|
||||||
|
4. @{string}: If the command failed, an error message explaining the failure. (This is not present if the command succeeded.)
|
||||||
|
...: Any parameters returned from the command.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
Prints the results of an asynchronous command:
|
||||||
|
```lua
|
||||||
|
local taskID = commands.execAsync("say Hello")
|
||||||
|
local event
|
||||||
|
repeat
|
||||||
|
event = {os.pullEvent("task_complete")}
|
||||||
|
until event[2] == taskID
|
||||||
|
if event[3] == true then
|
||||||
|
print("Task " .. event[2] .. " succeeded:", table.unpack(event, 4))
|
||||||
|
else
|
||||||
|
print("Task " .. event[2] .. " failed: " .. event[4])
|
||||||
|
end
|
||||||
|
```
|
20
doc/events/term_resize.md
Normal file
20
doc/events/term_resize.md
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
module: [kind=event] term_resize
|
||||||
|
---
|
||||||
|
|
||||||
|
The @{term_resize} event is fired when the main terminal is resized. For instance:
|
||||||
|
- When a the tab bar is shown or hidden in @{multishell}.
|
||||||
|
- When the terminal is redirected to a monitor via the "monitor" program and the monitor is resized.
|
||||||
|
|
||||||
|
When this event fires, some parts of the terminal may have been moved or deleted. Simple terminal programs (those
|
||||||
|
not using @{term.setCursorPos}) can ignore this event, but more complex GUI programs should redraw the entire screen.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
Prints :
|
||||||
|
```lua
|
||||||
|
while true do
|
||||||
|
os.pullEvent("term_resize")
|
||||||
|
local w, h = term.getSize()
|
||||||
|
print("The term was resized to (" .. w .. ", " .. h .. ")")
|
||||||
|
end
|
||||||
|
```
|
25
doc/events/terminate.md
Normal file
25
doc/events/terminate.md
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
---
|
||||||
|
module: [kind=event] terminate
|
||||||
|
---
|
||||||
|
|
||||||
|
The @{terminate} event is fired when <kbd>Ctrl-T</kbd> is held down.
|
||||||
|
|
||||||
|
This event is normally handled by @{os.pullEvent}, and will not be returned. However, @{os.pullEventRaw} will return this event when fired.
|
||||||
|
|
||||||
|
@{terminate} will be sent even when a filter is provided to @{os.pullEventRaw}. When using @{os.pullEventRaw} with a filter, make sure to check that the event is not @{terminate}.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
Prints a message when Ctrl-T is held:
|
||||||
|
```lua
|
||||||
|
while true do
|
||||||
|
local event = os.pullEventRaw("terminate")
|
||||||
|
if event == "terminate" then print("Terminate requested!") end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
Exits when Ctrl-T is held:
|
||||||
|
```lua
|
||||||
|
while true do
|
||||||
|
os.pullEvent()
|
||||||
|
end
|
||||||
|
```
|
21
doc/events/timer.md
Normal file
21
doc/events/timer.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
module: [kind=event] timer
|
||||||
|
see: os.startTimer To start a timer.
|
||||||
|
---
|
||||||
|
|
||||||
|
The @{timer} event is fired when a timer started with @{os.startTimer} completes.
|
||||||
|
|
||||||
|
## Return Values
|
||||||
|
1. @{string}: The event name.
|
||||||
|
2. @{number}: The ID of the timer that finished.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
Starts a timer and then prints its ID:
|
||||||
|
```lua
|
||||||
|
local timerID = os.startTimer(2)
|
||||||
|
local event, id
|
||||||
|
repeat
|
||||||
|
event, id = os.pullEvent("timer")
|
||||||
|
until id == timerID
|
||||||
|
print("Timer with ID " .. id .. " was fired")
|
||||||
|
```
|
14
doc/events/turtle_inventory.md
Normal file
14
doc/events/turtle_inventory.md
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
module: [kind=event] turtle_inventory
|
||||||
|
---
|
||||||
|
|
||||||
|
The @{turtle_inventory} event is fired when a turtle's inventory is changed.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
Prints a message when the inventory is changed:
|
||||||
|
```lua
|
||||||
|
while true do
|
||||||
|
os.pullEvent("turtle_inventory")
|
||||||
|
print("The inventory was changed.")
|
||||||
|
end
|
||||||
|
```
|
21
doc/events/websocket_closed.md
Normal file
21
doc/events/websocket_closed.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
module: [kind=event] websocket_closed
|
||||||
|
---
|
||||||
|
|
||||||
|
The @{websocket_closed} event is fired when an open WebSocket connection is closed.
|
||||||
|
|
||||||
|
## Return Values
|
||||||
|
1. @{string}: The event name.
|
||||||
|
2. @{string}: The URL of the WebSocket that was closed.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
Prints a message when a WebSocket is closed (this may take a minute):
|
||||||
|
```lua
|
||||||
|
local myURL = "wss://example.tweaked.cc/echo"
|
||||||
|
local ws = http.websocket(myURL)
|
||||||
|
local event, url
|
||||||
|
repeat
|
||||||
|
event, url = os.pullEvent("websocket_closed")
|
||||||
|
until url == myURL
|
||||||
|
print("The WebSocket at " .. url .. " was closed.")
|
||||||
|
```
|
25
doc/events/websocket_failure.md
Normal file
25
doc/events/websocket_failure.md
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
---
|
||||||
|
module: [kind=event] websocket_failure
|
||||||
|
see: http.websocketAsync To send an HTTP request.
|
||||||
|
---
|
||||||
|
|
||||||
|
The @{websocket_failure} event is fired when a WebSocket connection request fails.
|
||||||
|
|
||||||
|
This event is normally handled inside @{http.websocket}, but it can still be seen when using @{http.websocketAsync}.
|
||||||
|
|
||||||
|
## Return Values
|
||||||
|
1. @{string}: The event name.
|
||||||
|
2. @{string}: The URL of the site requested.
|
||||||
|
3. @{string}: An error describing the failure.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
Prints an error why the website cannot be contacted:
|
||||||
|
```lua
|
||||||
|
local myURL = "wss://example.tweaked.cc/not-a-websocket"
|
||||||
|
http.websocketAsync(myURL)
|
||||||
|
local event, url, err
|
||||||
|
repeat
|
||||||
|
event, url, err = os.pullEvent("websocket_failure")
|
||||||
|
until url == myURL
|
||||||
|
print("The URL " .. url .. " could not be reached: " .. err)
|
||||||
|
```
|
27
doc/events/websocket_message.md
Normal file
27
doc/events/websocket_message.md
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
---
|
||||||
|
module: [kind=event] websocket_message
|
||||||
|
---
|
||||||
|
|
||||||
|
The @{websocket_message} event is fired when a message is received on an open WebSocket connection.
|
||||||
|
|
||||||
|
This event is normally handled by @{http.Websocket.receive}, but it can also be pulled manually.
|
||||||
|
|
||||||
|
## Return Values
|
||||||
|
1. @{string}: The event name.
|
||||||
|
2. @{string}: The URL of the WebSocket.
|
||||||
|
3. @{string}: The contents of the message.
|
||||||
|
4. @{boolean}: Whether this is a binary message.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
Prints a message sent by a WebSocket:
|
||||||
|
```lua
|
||||||
|
local myURL = "wss://example.tweaked.cc/echo"
|
||||||
|
local ws = http.websocket(myURL)
|
||||||
|
ws.send("Hello!")
|
||||||
|
local event, url, message
|
||||||
|
repeat
|
||||||
|
event, url, message = os.pullEvent("websocket_message")
|
||||||
|
until url == myURL
|
||||||
|
print("Received message from " .. url .. " with contents " .. message)
|
||||||
|
ws.close()
|
||||||
|
```
|
28
doc/events/websocket_success.md
Normal file
28
doc/events/websocket_success.md
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
module: [kind=event] websocket_success
|
||||||
|
see: http.websocketAsync To open a WebSocket asynchronously.
|
||||||
|
---
|
||||||
|
|
||||||
|
The @{websocket_success} event is fired when a WebSocket connection request returns successfully.
|
||||||
|
|
||||||
|
This event is normally handled inside @{http.websocket}, but it can still be seen when using @{http.websocketAsync}.
|
||||||
|
|
||||||
|
## Return Values
|
||||||
|
1. @{string}: The event name.
|
||||||
|
2. @{string}: The URL of the site.
|
||||||
|
3. @{http.Websocket}: The handle for the WebSocket.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
Prints the content of a website (this may fail if the request fails):
|
||||||
|
```lua
|
||||||
|
local myURL = "wss://example.tweaked.cc/echo"
|
||||||
|
http.websocketAsync(myURL)
|
||||||
|
local event, url, handle
|
||||||
|
repeat
|
||||||
|
event, url, handle = os.pullEvent("websocket_success")
|
||||||
|
until url == myURL
|
||||||
|
print("Connected to " .. url)
|
||||||
|
handle.send("Hello!")
|
||||||
|
print(handle.receive())
|
||||||
|
handle.close()
|
||||||
|
```
|
200
doc/guides/speaker_audio.md
Normal file
200
doc/guides/speaker_audio.md
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
---
|
||||||
|
module: [kind=guide] speaker_audio
|
||||||
|
see: speaker.playAudio Play PCM audio using a speaker.
|
||||||
|
see: cc.audio.dfpwm Provides utilities for encoding and decoding DFPWM files.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Playing audio with speakers
|
||||||
|
CC: Tweaked's speaker peripheral provides a powerful way to play any audio you like with the @{speaker.playAudio}
|
||||||
|
method. However, for people unfamiliar with digital audio, it's not the most intuitive thing to use. This guide provides
|
||||||
|
an introduction to digital audio, demonstrates how to play music with CC: Tweaked's speakers, and then briefly discusses
|
||||||
|
the more complex topic of audio processing.
|
||||||
|
|
||||||
|
## A short introduction to digital audio
|
||||||
|
When sound is recorded it is captured as an analogue signal, effectively the electrical version of a sound
|
||||||
|
wave. However, this signal is continuous, and so can't be used directly by a computer. Instead, we measure (or *sample*)
|
||||||
|
the amplitude of the wave many times a second and then *quantise* that amplitude, rounding it to the nearest
|
||||||
|
representable value.
|
||||||
|
|
||||||
|
This representation of sound - a long, uniformally sampled list of amplitudes is referred to as [Pulse-code
|
||||||
|
Modulation][PCM] (PCM). PCM can be thought of as the "standard" audio format, as it's incredibly easy to work with. For
|
||||||
|
instance, to mix two pieces of audio together, you can just samples from the two tracks together and take the average.
|
||||||
|
|
||||||
|
CC: Tweaked's speakers also work with PCM audio. It plays back 48,000 samples a second, where each sample is an integer
|
||||||
|
between -128 and 127. This is more commonly referred to as 48kHz and an 8-bit resolution.
|
||||||
|
|
||||||
|
Let's now look at a quick example. We're going to generate a [Sine Wave] at 220Hz, which sounds like a low monotonous
|
||||||
|
hum. First we wrap our speaker peripheral, and then we fill a table (also referred to as a *buffer*) with 128×1024
|
||||||
|
samples - this is the maximum number of samples a speaker can accept in one go.
|
||||||
|
|
||||||
|
In order to fill this buffer, we need to do a little maths. We want to play 220 sine waves each second, where each sine
|
||||||
|
wave completes a full oscillation in 2π "units". This means one seconds worth of audio is 2×π×220 "units" long. We then
|
||||||
|
need to split this into 48k samples, basically meaning for each sample we move 2×π×220/48k "along" the sine curve.
|
||||||
|
|
||||||
|
```lua {data-peripheral=speaker}
|
||||||
|
local speaker = peripheral.find("speaker")
|
||||||
|
|
||||||
|
local buffer = {}
|
||||||
|
local t, dt = 0, 2 * math.pi * 220 / 48000
|
||||||
|
for i = 1, 128 * 1024 do
|
||||||
|
buffer[i] = math.floor(math.sin(t) * 127)
|
||||||
|
t = (t + dt) % (math.pi * 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
speaker.playAudio(buffer)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Streaming audio
|
||||||
|
You might notice that the above snippet only generates a short bit of audio - 2.7s seconds to be precise. While we could
|
||||||
|
try increasing the number of loop iterations, we'll get an error when we try to play it through the speaker: the sound
|
||||||
|
buffer is too large for it to handle.
|
||||||
|
|
||||||
|
Our 2.7 seconds of audio is stored in a table with over 130 _thousand_ elements. If we wanted to play a full minute of
|
||||||
|
sine waves (and why wouldn't you?), you'd need a table with almost 3 _million_. Suddenly you find these numbers adding
|
||||||
|
up very quickly, and these tables take up more and more memory.
|
||||||
|
|
||||||
|
Instead of building our entire song (well, sine wave) in one go, we can produce it in small batches, each of which get
|
||||||
|
passed off to @{speaker.playAudio} when the time is right. This allows us to build a _stream_ of audio, where we read
|
||||||
|
chunks of audio one at a time (either from a file or a tone generator like above), do some optional processing to each
|
||||||
|
one, and then play them.
|
||||||
|
|
||||||
|
Let's adapt our example from above to do that instead.
|
||||||
|
|
||||||
|
```lua {data-peripheral=speaker}
|
||||||
|
local speaker = peripheral.find("speaker")
|
||||||
|
|
||||||
|
local t, dt = 0, 2 * math.pi * 220 / 48000
|
||||||
|
while true do
|
||||||
|
local buffer = {}
|
||||||
|
for i = 1, 16 * 1024 * 8 do
|
||||||
|
buffer[i] = math.floor(math.sin(t) * 127)
|
||||||
|
t = (t + dt) % (math.pi * 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
while not speaker.playAudio(buffer) do
|
||||||
|
os.pullEvent("speaker_audio_empty")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
It looks pretty similar to before, aside from we've wrapped the generation and playing code in a while loop, and added a
|
||||||
|
rather odd loop with @{speaker.playAudio} and @{os.pullEvent}.
|
||||||
|
|
||||||
|
Let's talk about this loop, why do we need to keep calling @{speaker.playAudio}? Remember that what we're trying to do
|
||||||
|
here is avoid keeping too much audio in memory at once. However, if we're generating audio quicker than the speakers can
|
||||||
|
play it, we're not helping at all - all this audio is still hanging around waiting to be played!
|
||||||
|
|
||||||
|
In order to avoid this, the speaker rejects any new chunks of audio if its backlog is too large. When this happens,
|
||||||
|
@{speaker.playAudio} returns false. Once enough audio has played, and the backlog has been reduced, a
|
||||||
|
@{speaker_audio_empty} event is queued, and we can try to play our chunk once more.
|
||||||
|
|
||||||
|
## Storing audio
|
||||||
|
PCM is a fantastic way of representing audio when we want to manipulate it, but it's not very efficient when we want to
|
||||||
|
store it to disk. Compare the size of a WAV file (which uses PCM) to an equivalent MP3, it's often 5 times the size.
|
||||||
|
Instead, we store audio in special formats (or *codecs*) and then convert them to PCM when we need to do processing on
|
||||||
|
them.
|
||||||
|
|
||||||
|
Modern audio codecs use some incredibly impressive techniques to compress the audio as much as possible while preserving
|
||||||
|
sound quality. However, due to CC: Tweaked's limited processing power, it's not really possible to use these from your
|
||||||
|
computer. Instead, we need something much simpler.
|
||||||
|
|
||||||
|
DFPWM (Dynamic Filter Pulse Width Modulation) is the de facto standard audio format of the ComputerCraft (and
|
||||||
|
OpenComputers) world. Originally popularised by the addon mod [Computronics], CC:T now has built-in support for it with
|
||||||
|
the @{cc.audio.dfpwm} module. This allows you to read DFPWM files from disk, decode them to PCM, and then play them
|
||||||
|
using the speaker.
|
||||||
|
|
||||||
|
Let's dive in with an example, and we'll explain things afterwards:
|
||||||
|
|
||||||
|
```lua {data-peripheral=speaker}
|
||||||
|
local dfpwm = require("cc.audio.dfpwm")
|
||||||
|
local speaker = peripheral.find("speaker")
|
||||||
|
|
||||||
|
local decoder = dfpwm.make_decoder()
|
||||||
|
for chunk in io.lines("data/example.dfpwm", 16 * 1024) do
|
||||||
|
local buffer = decoder(chunk)
|
||||||
|
|
||||||
|
while not speaker.playAudio(buffer) do
|
||||||
|
os.pullEvent("speaker_audio_empty")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
Once again, we see the @{speaker.playAudio}/@{speaker_audio_empty} loop. However, the rest of the program is a little
|
||||||
|
different.
|
||||||
|
|
||||||
|
First, we require the dfpwm module and call @{cc.audio.dfpwm.make_decoder} to construct a new decoder. This decoder
|
||||||
|
accepts blocks of DFPWM data and converts it to a list of 8-bit amplitudes, which we can then play with our speaker.
|
||||||
|
|
||||||
|
As mentioned to above, @{speaker.playAudio} accepts at most 128×1024 samples in one go. DFPMW uses a single bit for each
|
||||||
|
sample, which means we want to process our audio in chunks of 16×1024 bytes (16KiB). In order to do this, we use
|
||||||
|
@{io.lines}, which provides a nice way to loop over chunks of a file. You can of course just use @{fs.open} and
|
||||||
|
@{fs.BinaryReadHandle.read} if you prefer.
|
||||||
|
|
||||||
|
## Processing audio
|
||||||
|
As mentioned near the beginning of this guide, PCM audio is pretty easy to work with as it's just a list of amplitudes.
|
||||||
|
You can mix together samples from different streams by adding their amplitudes, change the rate of playback by removing
|
||||||
|
samples, etc...
|
||||||
|
|
||||||
|
Let's put together a small demonstration here. We're going to add a small delay effect to the song above, so that you
|
||||||
|
hear a faint echo about a second later.
|
||||||
|
|
||||||
|
In order to do this, we'll follow a format similar to the previous example, decoding the audio and then playing it.
|
||||||
|
However, we'll also add some new logic between those two steps, which loops over every sample in our chunk of audio, and
|
||||||
|
adds the sample from one second ago to it.
|
||||||
|
|
||||||
|
For this, we'll need to keep track of the last 48k samples - exactly one seconds worth of audio. We can do this using a
|
||||||
|
[Ring Buffer], which helps makes things a little more efficient.
|
||||||
|
|
||||||
|
```lua {data-peripheral=speaker}
|
||||||
|
local dfpwm = require("cc.audio.dfpwm")
|
||||||
|
local speaker = peripheral.find("speaker")
|
||||||
|
|
||||||
|
-- Speakers play at 48kHz, so one second is 48k samples. We first fill our buffer
|
||||||
|
-- with 0s, as there's nothing to echo at the start of the track!
|
||||||
|
local samples_i, samples_n = 1, 48000
|
||||||
|
local samples = {}
|
||||||
|
for i = 1, samples_n do samples[i] = 0 end
|
||||||
|
|
||||||
|
local decoder = dfpwm.make_decoder()
|
||||||
|
for chunk in io.lines("data/example.dfpwm", 16 * 1024) do
|
||||||
|
local buffer = decoder(chunk)
|
||||||
|
|
||||||
|
for i = 1, #buffer do
|
||||||
|
local original_value = buffer[i]
|
||||||
|
|
||||||
|
-- Replace this sample with its current amplitude plus the amplitude from one second ago.
|
||||||
|
-- We scale both to ensure the resulting value is still between -128 and 127.
|
||||||
|
buffer[i] = original_value * 0.6 + samples[samples_i] * 0.4
|
||||||
|
|
||||||
|
-- Now store the current sample, and move the "head" of our ring buffer forward one place.
|
||||||
|
samples[samples_i] = original_value
|
||||||
|
samples_i = samples_i + 1
|
||||||
|
if samples_i > samples_n then samples_i = 1 end
|
||||||
|
end
|
||||||
|
|
||||||
|
while not speaker.playAudio(buffer) do
|
||||||
|
os.pullEvent("speaker_audio_empty")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
:::note Confused?
|
||||||
|
Don't worry if you don't understand this example. It's quite advanced, and does use some ideas that this guide doesn't
|
||||||
|
cover. That said, don't be afraid to ask on [Discord] or [IRC] either!
|
||||||
|
:::
|
||||||
|
|
||||||
|
It's worth noting that the examples of audio processing we've mentioned here are about manipulating the _amplitude_ of
|
||||||
|
the wave. If you wanted to modify the _frequency_ (for instance, shifting the pitch), things get rather more complex.
|
||||||
|
For this, you'd need to use the [Fast Fourier transform][FFT] to convert the stream of amplitudes to frequencies,
|
||||||
|
process those, and then convert them back to amplitudes.
|
||||||
|
|
||||||
|
This is, I'm afraid, left as an exercise to the reader.
|
||||||
|
|
||||||
|
[Computronics]: https://github.com/Vexatos/Computronics/ "Computronics on GitHub"
|
||||||
|
[FFT]: https://en.wikipedia.org/wiki/Fast_Fourier_transform "Fast Fourier transform - Wikipedia"
|
||||||
|
[PCM]: https://en.wikipedia.org/wiki/Pulse-code_modulation "Pulse-code Modulation - Wikipedia"
|
||||||
|
[Ring Buffer]: https://en.wikipedia.org/wiki/Circular_buffer "Circular buffer - Wikipedia"
|
||||||
|
[Sine Wave]: https://en.wikipedia.org/wiki/Sine_wave "Sine wave - Wikipedia"
|
||||||
|
|
||||||
|
[Discord]: https://discord.computercraft.cc "The Minecraft Computer Mods Discord"
|
||||||
|
[IRC]: http://webchat.esper.net/?channels=computercraft "IRC webchat on EsperNet"
|
83
doc/guides/using_require.md
Normal file
83
doc/guides/using_require.md
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
---
|
||||||
|
module: [kind=guide] using_require
|
||||||
|
---
|
||||||
|
|
||||||
|
# Reusing code with require
|
||||||
|
A library is a collection of useful functions and other definitions which is stored separately to your main program. You
|
||||||
|
might want to create a library because you have some functions which are used in multiple programs, or just to split
|
||||||
|
your program into multiple more modular files.
|
||||||
|
|
||||||
|
Let's say we want to create a small library to make working with the @{term|terminal} a little easier. We'll provide two
|
||||||
|
functions: `reset`, which clears the terminal and sets the cursor to (1, 1), and `write_center`, which prints some text
|
||||||
|
in the middle of the screen.
|
||||||
|
|
||||||
|
Start off by creating a file called `more_term.lua`:
|
||||||
|
|
||||||
|
```lua {data-snippet=more_term}
|
||||||
|
local function reset()
|
||||||
|
term.clear()
|
||||||
|
term.setCursorPos(1, 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function write_center(text)
|
||||||
|
local x, y = term.getCursorPos()
|
||||||
|
local width, height = term.getSize()
|
||||||
|
term.setCursorPos(math.floor((width - #text) / 2) + 1, y)
|
||||||
|
term.write(text)
|
||||||
|
end
|
||||||
|
|
||||||
|
return { reset = reset, write_center = write_center }
|
||||||
|
```
|
||||||
|
|
||||||
|
Now, what's going on here? We define our two functions as one might expect, and then at the bottom return a table with
|
||||||
|
the two functions. When we require this library, this table is what is returned. With that, we can then call the
|
||||||
|
original functions. Now create a new file, with the following:
|
||||||
|
|
||||||
|
```lua {data-mount=more_term:more_term.lua}
|
||||||
|
local more_term = require("more_term")
|
||||||
|
more_term.reset()
|
||||||
|
more_term.write_center("Hello, world!")
|
||||||
|
```
|
||||||
|
|
||||||
|
When run, this'll clear the screen and print some text in the middle of the first line.
|
||||||
|
|
||||||
|
## require in depth
|
||||||
|
While the previous section is a good introduction to how @{require} operates, there are a couple of remaining points
|
||||||
|
which are worth mentioning for more advanced usage.
|
||||||
|
|
||||||
|
### Libraries can return anything
|
||||||
|
In our above example, we return a table containing the functions we want to expose. However, it's worth pointing out
|
||||||
|
that you can return ''anything'' from your library - a table, a function or even just a string! @{require} treats them
|
||||||
|
all the same, and just returns whatever your library provides.
|
||||||
|
|
||||||
|
### Module resolution and the package path
|
||||||
|
In the above examples, we defined our library in a file, and @{require} read from it. While this is what you'll do most
|
||||||
|
of the time, it is possible to make @{require} look elsewhere for your library, such as downloading from a website or
|
||||||
|
loading from an in-memory library store.
|
||||||
|
|
||||||
|
As a result, the *module name* you pass to @{require} doesn't correspond to a file path. One common mistake is to load
|
||||||
|
code from a sub-directory using `require("folder/library")` or even `require("folder/library.lua")`, neither of which
|
||||||
|
will do quite what you expect.
|
||||||
|
|
||||||
|
When loading libraries (also referred to as *modules*) from files, @{require} searches along the *@{package.path|module
|
||||||
|
path}*. By default, this looks something like:
|
||||||
|
|
||||||
|
* `?.lua`
|
||||||
|
* `?/init.lua`
|
||||||
|
* `/rom/modules/main/?.lua`
|
||||||
|
* etc...
|
||||||
|
|
||||||
|
When you call `require("my_library")`, @{require} replaces the `?` in each element of the path with your module name, and
|
||||||
|
checks if the file exists. In this case, we'd look for `my_library.lua`, `my_library/init.lua`,
|
||||||
|
`/rom/modules/main/my_library.lua` and so on. Note that this works *relative to the current program*, so if your
|
||||||
|
program is actually called `folder/program`, then we'll look for `folder/my_library.lua`, etc...
|
||||||
|
|
||||||
|
One other caveat is loading libraries from sub-directories. For instance, say we have a file
|
||||||
|
`my/fancy/library.lua`. This can be loaded by using `require("my.fancy.library")` - the '.'s are replaced with '/'
|
||||||
|
before we start looking for the library.
|
||||||
|
|
||||||
|
## External links
|
||||||
|
There are several external resources which go into require in a little more detail:
|
||||||
|
|
||||||
|
- The [Lua Module tutorial](http://lua-users.org/wiki/ModulesTutorial) on the Lua wiki.
|
||||||
|
- [Lua's manual section on @{require}](https://www.lua.org/manual/5.1/manual.html#pdf-require).
|
1
doc/head.html
Normal file
1
doc/head.html
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<meta name="theme-color" content="#c8d87c">
|
BIN
doc/images/basic-terminal.png
Normal file
BIN
doc/images/basic-terminal.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 53 KiB |
BIN
doc/images/peripherals.png
Normal file
BIN
doc/images/peripherals.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 194 KiB |
BIN
doc/images/turtle.png
Normal file
BIN
doc/images/turtle.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 163 KiB |
55
doc/index.md
Normal file
55
doc/index.md
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
# 
|
||||||
|
CC: Tweaked is a mod for Minecraft which adds programmable computers, turtles and more to the game. A fork of the
|
||||||
|
much-beloved [ComputerCraft], it continues its legacy with better performance, stability, and a wealth of new features.
|
||||||
|
|
||||||
|
CC: Tweaked can be installed from [CurseForge] or [Modrinth]. It requires the [Minecraft Forge][forge] mod loader, but
|
||||||
|
[versions are available for Fabric][ccrestitched].
|
||||||
|
|
||||||
|
## Features
|
||||||
|
Controlled using the [Lua programming language][lua], CC: Tweaked's computers provides all the tools you need to start
|
||||||
|
writing code and automating your Minecraft world.
|
||||||
|
|
||||||
|
{.big-image}
|
||||||
|
|
||||||
|
While computers are incredibly powerful, they're rather limited by their inability to move about. *Turtles* are the
|
||||||
|
solution here. They can move about the world, placing and breaking blocks, swinging a sword to protect you from zombies,
|
||||||
|
or whatever else you program them to!
|
||||||
|
|
||||||
|
{.big-image}
|
||||||
|
|
||||||
|
Not all problems can be solved with a pickaxe though, and so CC: Tweaked also provides a bunch of additional peripherals
|
||||||
|
for your computers. You can play a tune with speakers, display text or images on a monitor, connect all your
|
||||||
|
computers together with modems, and much more.
|
||||||
|
|
||||||
|
Computers can now also interact with inventories such as chests, allowing you to build complex inventory and item
|
||||||
|
management systems.
|
||||||
|
|
||||||
|
{.big-image}
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
While ComputerCraft is lovely for both experienced programmers and for people who have never coded before, it can be a
|
||||||
|
little daunting getting started. Thankfully, there's several fantastic tutorials out there:
|
||||||
|
|
||||||
|
- [Direwolf20's ComputerCraft tutorials](https://www.youtube.com/watch?v=wrUHUhfCY5A "ComputerCraft Tutorial Episode 1 - HELP! and Hello World")
|
||||||
|
- [Sethbling's ComputerCraft series](https://www.youtube.com/watch?v=DSsx4VSe-Uk "Programming Tutorial with Minecraft Turtles -- Ep. 1: Intro to Turtles and If-Then-Else_End")
|
||||||
|
- [Lyqyd's Computer Basics 1](http://www.computercraft.info/forums2/index.php?/topic/15033-computer-basics-i/ "Computer Basics I")
|
||||||
|
|
||||||
|
Once you're a little more familiar with the mod, the sidebar and links below provide more detailed documentation on the
|
||||||
|
various APIs and peripherals provided by the mod.
|
||||||
|
|
||||||
|
If you get stuck, do pop in to the [Minecraft Computer Mod Discord guild][discord] or ComputerCraft's
|
||||||
|
[IRC channel][irc].
|
||||||
|
|
||||||
|
## Get Involved
|
||||||
|
CC: Tweaked lives on [GitHub]. If you've got any ideas, feedback or bugs please do [create an issue][bug].
|
||||||
|
|
||||||
|
[github]: https://github.com/cc-tweaked/CC-Tweaked/ "CC: Tweaked on GitHub"
|
||||||
|
[bug]: https://github.com/cc-tweaked/CC-Tweaked/issues/new/choose
|
||||||
|
[computercraft]: https://github.com/dan200/ComputerCraft "ComputerCraft on GitHub"
|
||||||
|
[curseforge]: https://minecraft.curseforge.com/projects/cc-tweaked "Download CC: Tweaked from CurseForge"
|
||||||
|
[modrinth]: https://modrinth.com/mod/gu7yAYhd "Download CC: Tweaked from Modrinth"
|
||||||
|
[forge]: https://files.minecraftforge.net/ "Download Minecraft Forge."
|
||||||
|
[ccrestitched]: https://www.curseforge.com/minecraft/mc-mods/cc-restitched "Download CC: Restitched from CurseForge"
|
||||||
|
[lua]: https://www.lua.org/ "Lua's main website"
|
||||||
|
[discord]: https://discord.computercraft.cc "The Minecraft Computer Mods Discord"
|
||||||
|
[irc]: http://webchat.esper.net/?channels=computercraft "IRC webchat on EsperNet"
|
BIN
doc/logo.png
Normal file
BIN
doc/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
36
doc/stub/fs.lua
Normal file
36
doc/stub/fs.lua
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
--- The FS API allows you to manipulate files and the filesystem.
|
||||||
|
--
|
||||||
|
-- @module fs
|
||||||
|
|
||||||
|
--- Returns true if a path is mounted to the parent filesystem.
|
||||||
|
--
|
||||||
|
-- The root filesystem "/" is considered a mount, along with disk folders and
|
||||||
|
-- the rom folder. Other programs (such as network shares) can exstend this to
|
||||||
|
-- make other mount types by correctly assigning their return value for getDrive.
|
||||||
|
--
|
||||||
|
-- @tparam string path The path to check.
|
||||||
|
-- @treturn boolean If the path is mounted, rather than a normal file/folder.
|
||||||
|
-- @throws If the path does not exist.
|
||||||
|
-- @see getDrive
|
||||||
|
-- @since 1.87.0
|
||||||
|
function isDriveRoot(path) end
|
||||||
|
|
||||||
|
--[[- Provides completion for a file or directory name, suitable for use with
|
||||||
|
@{_G.read}.
|
||||||
|
|
||||||
|
When a directory is a possible candidate for completion, two entries are
|
||||||
|
included - one with a trailing slash (indicating that entries within this
|
||||||
|
directory exist) and one without it (meaning this entry is an immediate
|
||||||
|
completion candidate). `include_dirs` can be set to @{false} to only include
|
||||||
|
those with a trailing slash.
|
||||||
|
|
||||||
|
@tparam string path The path to complete.
|
||||||
|
@tparam string location The location where paths are resolved from.
|
||||||
|
@tparam[opt] boolean include_files When @{false}, only directories will be
|
||||||
|
included in the returned list.
|
||||||
|
@tparam[opt] boolean include_dirs When @{false}, "raw" directories will not be
|
||||||
|
included in the returned list.
|
||||||
|
@treturn { string... } A list of possible completion candidates.
|
||||||
|
@since 1.74
|
||||||
|
]]
|
||||||
|
function complete(path, location, include_files, include_dirs) end
|
133
doc/stub/global.lua
Normal file
133
doc/stub/global.lua
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
--[[-
|
||||||
|
Functions in the global environment, defined in `bios.lua`. This does not
|
||||||
|
include standard Lua functions.
|
||||||
|
|
||||||
|
@module _G
|
||||||
|
]]
|
||||||
|
|
||||||
|
--[[- Pauses execution for the specified number of seconds.
|
||||||
|
|
||||||
|
As it waits for a fixed amount of world ticks, `time` will automatically be
|
||||||
|
rounded up to the nearest multiple of 0.05 seconds. If you are using coroutines
|
||||||
|
or the @{parallel|parallel API}, it will only pause execution of the current
|
||||||
|
thread, not the whole program.
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
Because sleep internally uses timers, it is a function that yields. This means
|
||||||
|
that you can use it to prevent "Too long without yielding" errors, however, as
|
||||||
|
the minimum sleep time is 0.05 seconds, it will slow your program down.
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::caution
|
||||||
|
Internally, this function queues and waits for a timer event (using
|
||||||
|
@{os.startTimer}), however it does not listen for any other events. This means
|
||||||
|
that any event that occurs while sleeping will be entirely discarded. If you
|
||||||
|
need to receive events while sleeping, consider using @{os.startTimer|timers},
|
||||||
|
or the @{parallel|parallel API}.
|
||||||
|
:::
|
||||||
|
|
||||||
|
@tparam number time The number of seconds to sleep for, rounded up to the
|
||||||
|
nearest multiple of 0.05.
|
||||||
|
|
||||||
|
@see os.startTimer
|
||||||
|
@usage Sleep for three seconds.
|
||||||
|
|
||||||
|
print("Sleeping for three seconds")
|
||||||
|
sleep(3)
|
||||||
|
print("Done!")
|
||||||
|
]]
|
||||||
|
function sleep(time) end
|
||||||
|
|
||||||
|
--- Writes a line of text to the screen without a newline at the end, wrapping
|
||||||
|
-- text if necessary.
|
||||||
|
--
|
||||||
|
-- @tparam string text The text to write to the string
|
||||||
|
-- @treturn number The number of lines written
|
||||||
|
-- @see print A wrapper around write that adds a newline and accepts multiple arguments
|
||||||
|
-- @usage write("Hello, world")
|
||||||
|
function write(text) end
|
||||||
|
|
||||||
|
--- Prints the specified values to the screen separated by spaces, wrapping if
|
||||||
|
-- necessary. After printing, the cursor is moved to the next line.
|
||||||
|
--
|
||||||
|
-- @param ... The values to print on the screen
|
||||||
|
-- @treturn number The number of lines written
|
||||||
|
-- @usage print("Hello, world!")
|
||||||
|
function print(...) end
|
||||||
|
|
||||||
|
--- Prints the specified values to the screen in red, separated by spaces,
|
||||||
|
-- wrapping if necessary. After printing, the cursor is moved to the next line.
|
||||||
|
--
|
||||||
|
-- @param ... The values to print on the screen
|
||||||
|
-- @usage printError("Something went wrong!")
|
||||||
|
function printError(...) end
|
||||||
|
|
||||||
|
--[[- Reads user input from the terminal, automatically handling arrow keys,
|
||||||
|
pasting, character replacement, history scrollback, auto-completion, and
|
||||||
|
default values.
|
||||||
|
|
||||||
|
@tparam[opt] string replaceChar A character to replace each typed character with.
|
||||||
|
This can be used for hiding passwords, for example.
|
||||||
|
@tparam[opt] table history A table holding history items that can be scrolled
|
||||||
|
back to with the up/down arrow keys. The oldest item is at index 1, while the
|
||||||
|
newest item is at the highest index.
|
||||||
|
@tparam[opt] function(partial: string):({ string... }|nil) completeFn A function
|
||||||
|
to be used for completion. This function should take the partial text typed so
|
||||||
|
far, and returns a list of possible completion options.
|
||||||
|
@tparam[opt] string default Default text which should already be entered into
|
||||||
|
the prompt.
|
||||||
|
|
||||||
|
@treturn string The text typed in.
|
||||||
|
|
||||||
|
@see cc.completion For functions to help with completion.
|
||||||
|
@usage Read a string and echo it back to the user
|
||||||
|
|
||||||
|
write("> ")
|
||||||
|
local msg = read()
|
||||||
|
print(msg)
|
||||||
|
|
||||||
|
@usage Prompt a user for a password.
|
||||||
|
|
||||||
|
while true do
|
||||||
|
write("Password> ")
|
||||||
|
local pwd = read("*")
|
||||||
|
if pwd == "let me in" then break end
|
||||||
|
print("Incorrect password, try again.")
|
||||||
|
end
|
||||||
|
print("Logged in!")
|
||||||
|
|
||||||
|
@usage A complete example with completion, history and a default value.
|
||||||
|
|
||||||
|
local completion = require "cc.completion"
|
||||||
|
local history = { "potato", "orange", "apple" }
|
||||||
|
local choices = { "apple", "orange", "banana", "strawberry" }
|
||||||
|
write("> ")
|
||||||
|
local msg = read(nil, history, function(text) return completion.choice(text, choices) end, "app")
|
||||||
|
print(msg)
|
||||||
|
|
||||||
|
@changed 1.74 Added `completeFn` parameter.
|
||||||
|
@changed 1.80pr1 Added `default` parameter.
|
||||||
|
]]
|
||||||
|
function read(replaceChar, history, completeFn, default) end
|
||||||
|
|
||||||
|
--- The ComputerCraft and Minecraft version of the current computer environment.
|
||||||
|
--
|
||||||
|
-- For example, `ComputerCraft 1.93.0 (Minecraft 1.15.2)`.
|
||||||
|
-- @usage _HOST
|
||||||
|
-- @since 1.76
|
||||||
|
_HOST = _HOST
|
||||||
|
|
||||||
|
--[[- The default computer settings as defined in the ComputerCraft
|
||||||
|
configuration.
|
||||||
|
|
||||||
|
This is a comma-separated list of settings pairs defined by the mod
|
||||||
|
configuration or server owner. By default, it is empty.
|
||||||
|
|
||||||
|
An example value to disable autocompletion:
|
||||||
|
|
||||||
|
shell.autocomplete=false,lua.autocomplete=false,edit.autocomplete=false
|
||||||
|
|
||||||
|
@usage _CC_DEFAULT_SETTINGS
|
||||||
|
@since 1.77
|
||||||
|
]]
|
||||||
|
_CC_DEFAULT_SETTINGS = _CC_DEFAULT_SETTINGS
|
181
doc/stub/http.lua
Normal file
181
doc/stub/http.lua
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
--- The http library allows communicating with web servers, sending and
|
||||||
|
-- receiving data from them.
|
||||||
|
--
|
||||||
|
-- @module http
|
||||||
|
-- @since 1.1
|
||||||
|
|
||||||
|
--- Asynchronously make a HTTP request to the given url.
|
||||||
|
--
|
||||||
|
-- This returns immediately, a [`http_success`](#http-success-event) or
|
||||||
|
-- [`http_failure`](#http-failure-event) will be queued once the request has
|
||||||
|
-- completed.
|
||||||
|
--
|
||||||
|
-- @tparam string url The url to request
|
||||||
|
-- @tparam[opt] string body An optional string containing the body of the
|
||||||
|
-- request. If specified, a `POST` request will be made instead.
|
||||||
|
-- @tparam[opt] { [string] = string } headers Additional headers to send as part
|
||||||
|
-- of this request.
|
||||||
|
-- @tparam[opt] boolean binary Whether to make a binary HTTP request. If true,
|
||||||
|
-- the body will not be UTF-8 encoded, and the received response will not be
|
||||||
|
-- decoded.
|
||||||
|
--
|
||||||
|
-- @tparam[2] {
|
||||||
|
-- url = string, body? = string, headers? = { [string] = string },
|
||||||
|
-- binary? = boolean, method? = string, redirect? = boolean,
|
||||||
|
-- } request Options for the request.
|
||||||
|
--
|
||||||
|
-- This table form is an expanded version of the previous syntax. All arguments
|
||||||
|
-- from above are passed in as fields instead (for instance,
|
||||||
|
-- `http.request("https://example.com")` becomes `http.request { url =
|
||||||
|
-- "https://example.com" }`).
|
||||||
|
--
|
||||||
|
-- This table also accepts several additional options:
|
||||||
|
--
|
||||||
|
-- - `method`: Which HTTP method to use, for instance `"PATCH"` or `"DELETE"`.
|
||||||
|
-- - `redirect`: Whether to follow HTTP redirects. Defaults to true.
|
||||||
|
--
|
||||||
|
-- @see http.get For a synchronous way to make GET requests.
|
||||||
|
-- @see http.post For a synchronous way to make POST requests.
|
||||||
|
--
|
||||||
|
-- @changed 1.63 Added argument for headers.
|
||||||
|
-- @changed 1.80pr1 Added argument for binary handles.
|
||||||
|
-- @changed 1.80pr1.6 Added support for table argument.
|
||||||
|
-- @changed 1.86.0 Added PATCH and TRACE methods.
|
||||||
|
function request(...) end
|
||||||
|
|
||||||
|
--- Make a HTTP GET request to the given url.
|
||||||
|
--
|
||||||
|
-- @tparam string url The url to request
|
||||||
|
-- @tparam[opt] { [string] = string } headers Additional headers to send as part
|
||||||
|
-- of this request.
|
||||||
|
-- @tparam[opt] boolean binary Whether to make a binary HTTP request. If true,
|
||||||
|
-- the body will not be UTF-8 encoded, and the received response will not be
|
||||||
|
-- decoded.
|
||||||
|
--
|
||||||
|
-- @tparam[2] {
|
||||||
|
-- url = string, headers? = { [string] = string },
|
||||||
|
-- binary? = boolean, method? = string, redirect? = boolean,
|
||||||
|
-- } request Options for the request. See @{http.request} for details on how
|
||||||
|
-- these options behave.
|
||||||
|
--
|
||||||
|
-- @treturn Response The resulting http response, which can be read from.
|
||||||
|
-- @treturn[2] nil When the http request failed, such as in the event of a 404
|
||||||
|
-- error or connection timeout.
|
||||||
|
-- @treturn string A message detailing why the request failed.
|
||||||
|
-- @treturn Response|nil The failing http response, if available.
|
||||||
|
--
|
||||||
|
-- @changed 1.63 Added argument for headers.
|
||||||
|
-- @changed 1.80pr1 Response handles are now returned on error if available.
|
||||||
|
-- @changed 1.80pr1 Added argument for binary handles.
|
||||||
|
-- @changed 1.80pr1.6 Added support for table argument.
|
||||||
|
-- @changed 1.86.0 Added PATCH and TRACE methods.
|
||||||
|
--
|
||||||
|
-- @usage Make a request to [example.tweaked.cc](https://example.tweaked.cc),
|
||||||
|
-- and print the returned page.
|
||||||
|
-- ```lua
|
||||||
|
-- local request = http.get("https://example.tweaked.cc")
|
||||||
|
-- print(request.readAll())
|
||||||
|
-- -- => HTTP is working!
|
||||||
|
-- request.close()
|
||||||
|
-- ```
|
||||||
|
function get(...) end
|
||||||
|
|
||||||
|
--- Make a HTTP POST request to the given url.
|
||||||
|
--
|
||||||
|
-- @tparam string url The url to request
|
||||||
|
-- @tparam string body The body of the POST request.
|
||||||
|
-- @tparam[opt] { [string] = string } headers Additional headers to send as part
|
||||||
|
-- of this request.
|
||||||
|
-- @tparam[opt] boolean binary Whether to make a binary HTTP request. If true,
|
||||||
|
-- the body will not be UTF-8 encoded, and the received response will not be
|
||||||
|
-- decoded.
|
||||||
|
--
|
||||||
|
-- @tparam[2] {
|
||||||
|
-- url = string, body? = string, headers? = { [string] = string },
|
||||||
|
-- binary? = boolean, method? = string, redirect? = boolean,
|
||||||
|
-- } request Options for the request. See @{http.request} for details on how
|
||||||
|
-- these options behave.
|
||||||
|
--
|
||||||
|
-- @treturn Response The resulting http response, which can be read from.
|
||||||
|
-- @treturn[2] nil When the http request failed, such as in the event of a 404
|
||||||
|
-- error or connection timeout.
|
||||||
|
-- @treturn string A message detailing why the request failed.
|
||||||
|
-- @treturn Response|nil The failing http response, if available.
|
||||||
|
--
|
||||||
|
-- @since 1.31
|
||||||
|
-- @changed 1.63 Added argument for headers.
|
||||||
|
-- @changed 1.80pr1 Response handles are now returned on error if available.
|
||||||
|
-- @changed 1.80pr1 Added argument for binary handles.
|
||||||
|
-- @changed 1.80pr1.6 Added support for table argument.
|
||||||
|
-- @changed 1.86.0 Added PATCH and TRACE methods.
|
||||||
|
function post(...) end
|
||||||
|
|
||||||
|
--- Asynchronously determine whether a URL can be requested.
|
||||||
|
--
|
||||||
|
-- If this returns `true`, one should also listen for [`http_check`
|
||||||
|
-- events](#http-check-event) which will container further information about
|
||||||
|
-- whether the URL is allowed or not.
|
||||||
|
--
|
||||||
|
-- @tparam string url The URL to check.
|
||||||
|
-- @treturn true When this url is not invalid. This does not imply that it is
|
||||||
|
-- allowed - see the comment above.
|
||||||
|
-- @treturn[2] false When this url is invalid.
|
||||||
|
-- @treturn string A reason why this URL is not valid (for instance, if it is
|
||||||
|
-- malformed, or blocked).
|
||||||
|
--
|
||||||
|
-- @see http.checkURL For a synchronous version.
|
||||||
|
function checkURLAsync(url) end
|
||||||
|
|
||||||
|
--- Determine whether a URL can be requested.
|
||||||
|
--
|
||||||
|
-- If this returns `true`, one should also listen for [`http_check`
|
||||||
|
-- events](#http-check-event) which will container further information about
|
||||||
|
-- whether the URL is allowed or not.
|
||||||
|
--
|
||||||
|
-- @tparam string url The URL to check.
|
||||||
|
-- @treturn true When this url is valid and can be requested via @{http.request}.
|
||||||
|
-- @treturn[2] false When this url is invalid.
|
||||||
|
-- @treturn string A reason why this URL is not valid (for instance, if it is
|
||||||
|
-- malformed, or blocked).
|
||||||
|
--
|
||||||
|
-- @see http.checkURLAsync For an asynchronous version.
|
||||||
|
--
|
||||||
|
-- @usage
|
||||||
|
-- ```lua
|
||||||
|
-- print(http.checkURL("https://example.tweaked.cc/"))
|
||||||
|
-- -- => true
|
||||||
|
-- print(http.checkURL("http://localhost/"))
|
||||||
|
-- -- => false Domain not permitted
|
||||||
|
-- print(http.checkURL("not a url"))
|
||||||
|
-- -- => false URL malformed
|
||||||
|
-- ```
|
||||||
|
function checkURL(url) end
|
||||||
|
|
||||||
|
--- Open a websocket.
|
||||||
|
--
|
||||||
|
-- @tparam string url The websocket url to connect to. This should have the
|
||||||
|
-- `ws://` or `wss://` protocol.
|
||||||
|
-- @tparam[opt] { [string] = string } headers Additional headers to send as part
|
||||||
|
-- of the initial websocket connection.
|
||||||
|
--
|
||||||
|
-- @treturn Websocket The websocket connection.
|
||||||
|
-- @treturn[2] false If the websocket connection failed.
|
||||||
|
-- @treturn string An error message describing why the connection failed.
|
||||||
|
-- @since 1.80pr1.1
|
||||||
|
-- @changed 1.80pr1.3 No longer asynchronous.
|
||||||
|
-- @changed 1.95.3 Added User-Agent to default headers.
|
||||||
|
function websocket(url, headers) end
|
||||||
|
|
||||||
|
--- Asynchronously open a websocket.
|
||||||
|
--
|
||||||
|
-- This returns immediately, a [`websocket_success`](#websocket-success-event)
|
||||||
|
-- or [`websocket_failure`](#websocket-failure-event) will be queued once the
|
||||||
|
-- request has completed.
|
||||||
|
--
|
||||||
|
-- @tparam string url The websocket url to connect to. This should have the
|
||||||
|
-- `ws://` or `wss://` protocol.
|
||||||
|
-- @tparam[opt] { [string] = string } headers Additional headers to send as part
|
||||||
|
-- of the initial websocket connection.
|
||||||
|
-- @since 1.80pr1.3
|
||||||
|
-- @changed 1.95.3 Added User-Agent to default headers.
|
||||||
|
function websocketAsync(url, headers) end
|
128
doc/stub/os.lua
Normal file
128
doc/stub/os.lua
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
-- Defined in bios.lua
|
||||||
|
|
||||||
|
--[[- Loads the given API into the global environment.
|
||||||
|
|
||||||
|
This function loads and executes the file at the given path, and all global
|
||||||
|
variables and functions exported by it will by available through the use of
|
||||||
|
`myAPI.<function name>`, where `myAPI` is the base name of the API file.
|
||||||
|
|
||||||
|
@tparam string path The path of the API to load.
|
||||||
|
@treturn boolean Whether or not the API was successfully loaded.
|
||||||
|
@since 1.2
|
||||||
|
|
||||||
|
@deprecated When possible it's best to avoid using this function. It pollutes
|
||||||
|
the global table and can mask errors.
|
||||||
|
|
||||||
|
@{require} should be used to load libraries instead.
|
||||||
|
]]
|
||||||
|
function loadAPI(path) end
|
||||||
|
|
||||||
|
--- Unloads an API which was loaded by @{os.loadAPI}.
|
||||||
|
--
|
||||||
|
-- This effectively removes the specified table from `_G`.
|
||||||
|
--
|
||||||
|
-- @tparam string name The name of the API to unload.
|
||||||
|
-- @since 1.2
|
||||||
|
-- @deprecated See @{os.loadAPI} for why.
|
||||||
|
function unloadAPI(name) end
|
||||||
|
|
||||||
|
--[[- Pause execution of the current thread and waits for any events matching
|
||||||
|
`filter`.
|
||||||
|
|
||||||
|
This function @{coroutine.yield|yields} the current process and waits for it
|
||||||
|
to be resumed with a vararg list where the first element matches `filter`.
|
||||||
|
If no `filter` is supplied, this will match all events.
|
||||||
|
|
||||||
|
Unlike @{os.pullEventRaw}, it will stop the application upon a "terminate"
|
||||||
|
event, printing the error "Terminated".
|
||||||
|
|
||||||
|
@tparam[opt] string filter Event to filter for.
|
||||||
|
@treturn string event The name of the event that fired.
|
||||||
|
@treturn any param... Optional additional parameters of the event.
|
||||||
|
@usage Listen for `mouse_click` events.
|
||||||
|
|
||||||
|
while true do
|
||||||
|
local event, button, x, y = os.pullEvent("mouse_click")
|
||||||
|
print("Button", button, "was clicked at", x, ",", y)
|
||||||
|
end
|
||||||
|
|
||||||
|
@usage Listen for multiple events.
|
||||||
|
|
||||||
|
while true do
|
||||||
|
local eventData = {os.pullEvent()}
|
||||||
|
local event = eventData[1]
|
||||||
|
|
||||||
|
if event == "mouse_click" then
|
||||||
|
print("Button", eventData[2], "was clicked at", eventData[3], ",", eventData[4])
|
||||||
|
elseif event == "key" then
|
||||||
|
print("Key code", eventData[2], "was pressed")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@see os.pullEventRaw To pull the terminate event.
|
||||||
|
@changed 1.3 Added filter argument.
|
||||||
|
]]
|
||||||
|
function pullEvent(filter) end
|
||||||
|
|
||||||
|
--[[- Pause execution of the current thread and waits for events, including the
|
||||||
|
`terminate` event.
|
||||||
|
|
||||||
|
This behaves almost the same as @{os.pullEvent}, except it allows you to handle
|
||||||
|
the `terminate` event yourself - the program will not stop execution when
|
||||||
|
<kbd>Ctrl+T</kbd> is pressed.
|
||||||
|
|
||||||
|
@tparam[opt] string filter Event to filter for.
|
||||||
|
@treturn string event The name of the event that fired.
|
||||||
|
@treturn any param... Optional additional parameters of the event.
|
||||||
|
@usage Listen for `terminate` events.
|
||||||
|
|
||||||
|
while true do
|
||||||
|
local event = os.pullEventRaw()
|
||||||
|
if event == "terminate" then
|
||||||
|
print("Caught terminate event!")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@see os.pullEvent To pull events normally.
|
||||||
|
]]
|
||||||
|
function pullEventRaw(filter) end
|
||||||
|
|
||||||
|
--- Pauses execution for the specified number of seconds, alias of @{_G.sleep}.
|
||||||
|
--
|
||||||
|
-- @tparam number time The number of seconds to sleep for, rounded up to the
|
||||||
|
-- nearest multiple of 0.05.
|
||||||
|
function sleep(time) end
|
||||||
|
|
||||||
|
--- Get the current CraftOS version (for example, `CraftOS 1.8`).
|
||||||
|
--
|
||||||
|
-- This is defined by `bios.lua`. For the current version of CC:Tweaked, this
|
||||||
|
-- should return `CraftOS 1.8`.
|
||||||
|
--
|
||||||
|
-- @treturn string The current CraftOS version.
|
||||||
|
-- @usage os.version()
|
||||||
|
function version() end
|
||||||
|
|
||||||
|
--[[- Run the program at the given path with the specified environment and
|
||||||
|
arguments.
|
||||||
|
|
||||||
|
This function does not resolve program names like the shell does. This means
|
||||||
|
that, for example, `os.run("edit")` will not work. As well as this, it does not
|
||||||
|
provide access to the @{shell} API in the environment. For this behaviour, use
|
||||||
|
@{shell.run} instead.
|
||||||
|
|
||||||
|
If the program cannot be found, or failed to run, it will print the error and
|
||||||
|
return `false`. If you want to handle this more gracefully, use an alternative
|
||||||
|
such as @{loadfile}.
|
||||||
|
|
||||||
|
@tparam table env The environment to run the program with.
|
||||||
|
@tparam string path The exact path of the program to run.
|
||||||
|
@param ... The arguments to pass to the program.
|
||||||
|
@treturn boolean Whether or not the program ran successfully.
|
||||||
|
@usage Run the default shell from within your program:
|
||||||
|
|
||||||
|
os.run({}, "/rom/programs/shell.lua")
|
||||||
|
|
||||||
|
@see shell.run
|
||||||
|
@see loadfile
|
||||||
|
]]
|
||||||
|
function run(env, path, ...) end
|
14
doc/stub/turtle.lua
Normal file
14
doc/stub/turtle.lua
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
--[[- Craft a recipe based on the turtle's inventory.
|
||||||
|
|
||||||
|
The turtle's inventory should set up like a crafting grid. For instance, to
|
||||||
|
craft sticks, slots 1 and 5 should contain planks. _All_ other slots should be
|
||||||
|
empty, including those outside the crafting "grid".
|
||||||
|
|
||||||
|
@tparam[opt=64] number limit The maximum number of crafting steps to run.
|
||||||
|
@throws When limit is less than 1 or greater than 64.
|
||||||
|
@treturn[1] true If crafting succeeds.
|
||||||
|
@treturn[2] false If crafting fails.
|
||||||
|
@treturn string A string describing why crafting failed.
|
||||||
|
@since 1.4
|
||||||
|
]]
|
||||||
|
function craft(limit) end
|
@@ -1,17 +1,14 @@
|
|||||||
# Done to increase the memory available to gradle.
|
# Done to increase the memory available to gradle.
|
||||||
org.gradle.jvmargs=-Xmx1G
|
org.gradle.jvmargs=-Xmx3G
|
||||||
|
|
||||||
# Mod properties
|
# Mod properties
|
||||||
mod_version=1.96.0
|
mod_version=1.100.0-rc.1
|
||||||
|
|
||||||
# Minecraft properties
|
# Minecraft properties
|
||||||
mc_version=1.16.5
|
mc_version=1.18.1
|
||||||
mappings_version=9
|
fabric_api_version=0.44.0+1.18
|
||||||
|
fabric_loader_version=0.12.11
|
||||||
|
|
||||||
# Dependencies
|
cloth_api_version=2.0.54
|
||||||
cloth_config_version=4.8.1
|
cloth_config_version=6.0.42
|
||||||
fabric_loader_version=0.11.3
|
modmenu_version=3.0.0
|
||||||
fabric_api_version=0.32.0+1.16
|
|
||||||
jankson_version=1.2.0
|
|
||||||
modmenu_version=1.14.6+
|
|
||||||
cloth_api_version=1.4.5
|
|
||||||
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
5
gradle/wrapper/gradle-wrapper.properties
vendored
5
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,5 @@
|
|||||||
#Tue Jul 07 13:15:43 EDT 2020
|
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-all.zip
|
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStorePath=wrapper/dists
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
||||||
|
53
gradlew
vendored
53
gradlew
vendored
@@ -1,5 +1,21 @@
|
|||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright 2015 the original author or authors.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
##
|
##
|
||||||
## Gradle start up script for UN*X
|
## Gradle start up script for UN*X
|
||||||
@@ -28,7 +44,7 @@ APP_NAME="Gradle"
|
|||||||
APP_BASE_NAME=`basename "$0"`
|
APP_BASE_NAME=`basename "$0"`
|
||||||
|
|
||||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
DEFAULT_JVM_OPTS=""
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD="maximum"
|
MAX_FD="maximum"
|
||||||
@@ -66,6 +82,7 @@ esac
|
|||||||
|
|
||||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
|
||||||
# Determine the Java command to use to start the JVM.
|
# Determine the Java command to use to start the JVM.
|
||||||
if [ -n "$JAVA_HOME" ] ; then
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
@@ -109,10 +126,11 @@ if $darwin; then
|
|||||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# For Cygwin, switch paths to Windows format before running java
|
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||||
if $cygwin ; then
|
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||||
|
|
||||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||||
|
|
||||||
# We build the pattern for arguments to be converted via cygpath
|
# We build the pattern for arguments to be converted via cygpath
|
||||||
@@ -138,19 +156,19 @@ if $cygwin ; then
|
|||||||
else
|
else
|
||||||
eval `echo args$i`="\"$arg\""
|
eval `echo args$i`="\"$arg\""
|
||||||
fi
|
fi
|
||||||
i=$((i+1))
|
i=`expr $i + 1`
|
||||||
done
|
done
|
||||||
case $i in
|
case $i in
|
||||||
(0) set -- ;;
|
0) set -- ;;
|
||||||
(1) set -- "$args0" ;;
|
1) set -- "$args0" ;;
|
||||||
(2) set -- "$args0" "$args1" ;;
|
2) set -- "$args0" "$args1" ;;
|
||||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
3) set -- "$args0" "$args1" "$args2" ;;
|
||||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -159,14 +177,9 @@ save () {
|
|||||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||||
echo " "
|
echo " "
|
||||||
}
|
}
|
||||||
APP_ARGS=$(save "$@")
|
APP_ARGS=`save "$@"`
|
||||||
|
|
||||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||||
|
|
||||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
|
||||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
|
||||||
cd "$(dirname "$0")"
|
|
||||||
fi
|
|
||||||
|
|
||||||
exec "$JAVACMD" "$@"
|
exec "$JAVACMD" "$@"
|
||||||
|
43
gradlew.bat
vendored
43
gradlew.bat
vendored
@@ -1,3 +1,19 @@
|
|||||||
|
@rem
|
||||||
|
@rem Copyright 2015 the original author or authors.
|
||||||
|
@rem
|
||||||
|
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
@rem you may not use this file except in compliance with the License.
|
||||||
|
@rem You may obtain a copy of the License at
|
||||||
|
@rem
|
||||||
|
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
@rem
|
||||||
|
@rem Unless required by applicable law or agreed to in writing, software
|
||||||
|
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@rem See the License for the specific language governing permissions and
|
||||||
|
@rem limitations under the License.
|
||||||
|
@rem
|
||||||
|
|
||||||
@if "%DEBUG%" == "" @echo off
|
@if "%DEBUG%" == "" @echo off
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
@rem
|
@rem
|
||||||
@@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=.
|
|||||||
set APP_BASE_NAME=%~n0
|
set APP_BASE_NAME=%~n0
|
||||||
set APP_HOME=%DIRNAME%
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||||
|
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||||
|
|
||||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
set DEFAULT_JVM_OPTS=
|
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||||
|
|
||||||
@rem Find java.exe
|
@rem Find java.exe
|
||||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
set JAVA_EXE=java.exe
|
set JAVA_EXE=java.exe
|
||||||
%JAVA_EXE% -version >NUL 2>&1
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
if "%ERRORLEVEL%" == "0" goto init
|
if "%ERRORLEVEL%" == "0" goto execute
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
@@ -35,7 +54,7 @@ goto fail
|
|||||||
set JAVA_HOME=%JAVA_HOME:"=%
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
if exist "%JAVA_EXE%" goto init
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
@@ -45,28 +64,14 @@ echo location of your Java installation.
|
|||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
:init
|
|
||||||
@rem Get command-line arguments, handling Windows variants
|
|
||||||
|
|
||||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
|
||||||
|
|
||||||
:win9xME_args
|
|
||||||
@rem Slurp the command line arguments.
|
|
||||||
set CMD_LINE_ARGS=
|
|
||||||
set _SKIP=2
|
|
||||||
|
|
||||||
:win9xME_args_slurp
|
|
||||||
if "x%~1" == "x" goto execute
|
|
||||||
|
|
||||||
set CMD_LINE_ARGS=%*
|
|
||||||
|
|
||||||
:execute
|
:execute
|
||||||
@rem Setup the command line
|
@rem Setup the command line
|
||||||
|
|
||||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
|
|
||||||
@rem Execute Gradle
|
@rem Execute Gradle
|
||||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||||
|
|
||||||
:end
|
:end
|
||||||
@rem End local scope for the variables with windows NT shell
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
117
illuaminate.sexp
Normal file
117
illuaminate.sexp
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
; -*- mode: Lisp;-*-
|
||||||
|
|
||||||
|
(sources
|
||||||
|
/doc/events/
|
||||||
|
/doc/guides/
|
||||||
|
/doc/stub/
|
||||||
|
/build/docs/luaJavadoc/
|
||||||
|
/src/main/resources/*/computercraft/lua/bios.lua
|
||||||
|
/src/main/resources/*/computercraft/lua/rom/
|
||||||
|
/src/test/resources/test-rom
|
||||||
|
/src/web/mount)
|
||||||
|
|
||||||
|
|
||||||
|
(doc
|
||||||
|
(destination build/docs/lua)
|
||||||
|
(index doc/index.md)
|
||||||
|
|
||||||
|
(site
|
||||||
|
(title "CC: Tweaked")
|
||||||
|
(logo src/main/resources/pack.png)
|
||||||
|
(url https://tweaked.cc/)
|
||||||
|
(source-link https://github.com/cc-tweaked/CC-Tweaked/blob/${commit}/${path}#L${line})
|
||||||
|
|
||||||
|
(styles src/web/styles.css)
|
||||||
|
(scripts build/rollup/index.js)
|
||||||
|
(head doc/head.html))
|
||||||
|
|
||||||
|
(module-kinds
|
||||||
|
(peripheral Peripherals)
|
||||||
|
(generic_peripheral "Generic Peripherals")
|
||||||
|
(event Events)
|
||||||
|
(guide Guides))
|
||||||
|
|
||||||
|
(library-path
|
||||||
|
/doc/stub/
|
||||||
|
/build/docs/luaJavadoc/
|
||||||
|
|
||||||
|
/src/main/resources/*/computercraft/lua/rom/apis/
|
||||||
|
/src/main/resources/*/computercraft/lua/rom/apis/command/
|
||||||
|
/src/main/resources/*/computercraft/lua/rom/apis/turtle/
|
||||||
|
|
||||||
|
/src/main/resources/*/computercraft/lua/rom/modules/main/
|
||||||
|
/src/main/resources/*/computercraft/lua/rom/modules/command/
|
||||||
|
/src/main/resources/*/computercraft/lua/rom/modules/turtle/))
|
||||||
|
|
||||||
|
(at /
|
||||||
|
(linters
|
||||||
|
syntax:string-index
|
||||||
|
|
||||||
|
;; It'd be nice to avoid this, but right now there's a lot of instances of
|
||||||
|
;; it.
|
||||||
|
-var:set-loop
|
||||||
|
|
||||||
|
;; It's useful to name arguments for documentation, so we allow this. It'd
|
||||||
|
;; be good to find a compromise in the future, but this works for now.
|
||||||
|
-var:unused-arg)
|
||||||
|
|
||||||
|
(lint
|
||||||
|
(bracket-spaces
|
||||||
|
(call no-space)
|
||||||
|
(function-args no-space)
|
||||||
|
(parens no-space)
|
||||||
|
(table space)
|
||||||
|
(index no-space))
|
||||||
|
|
||||||
|
(allow-clarifying-parens true)
|
||||||
|
|
||||||
|
;; colours imports from colors, and we don't handle that right now.
|
||||||
|
;; keys is entirely dynamic, so we skip it.
|
||||||
|
(dynamic-modules colours keys _G)
|
||||||
|
|
||||||
|
(globals
|
||||||
|
:max
|
||||||
|
_CC_DEFAULT_SETTINGS
|
||||||
|
_CC_DISABLE_LUA51_FEATURES
|
||||||
|
_HOST
|
||||||
|
;; Ideally we'd pick these up from bios.lua, but illuaminate currently
|
||||||
|
;; isn't smart enough.
|
||||||
|
sleep write printError read rs)))
|
||||||
|
|
||||||
|
;; We disable the unused global linter in bios.lua and the APIs. In the future
|
||||||
|
;; hopefully we'll get illuaminate to handle this.
|
||||||
|
(at
|
||||||
|
(/src/main/resources/*/computercraft/lua/bios.lua
|
||||||
|
/src/main/resources/*/computercraft/lua/rom/apis/)
|
||||||
|
(linters -var:unused-global)
|
||||||
|
(lint (allow-toplevel-global true)))
|
||||||
|
|
||||||
|
;; Silence some variable warnings in documentation stubs.
|
||||||
|
(at (/doc/stub/ /build/docs/luaJavadoc/)
|
||||||
|
(linters -var:unused-global)
|
||||||
|
(lint (allow-toplevel-global true)))
|
||||||
|
|
||||||
|
;; Suppress warnings for currently undocumented modules.
|
||||||
|
(at
|
||||||
|
(; Lua APIs
|
||||||
|
/src/main/resources/*/computercraft/lua/rom/apis/io.lua
|
||||||
|
/src/main/resources/*/computercraft/lua/rom/apis/window.lua)
|
||||||
|
|
||||||
|
(linters -doc:undocumented -doc:undocumented-arg -doc:undocumented-return))
|
||||||
|
|
||||||
|
;; Suppress warnings for various APIs using its own deprecated members.
|
||||||
|
(at
|
||||||
|
(/src/main/resources/*/computercraft/lua/bios.lua
|
||||||
|
/src/main/resources/*/computercraft/lua/rom/apis/turtle/turtle.lua)
|
||||||
|
(linters -var:deprecated))
|
||||||
|
|
||||||
|
(at /src/test/resources/test-rom
|
||||||
|
; We should still be able to test deprecated members.
|
||||||
|
(linters -var:deprecated)
|
||||||
|
|
||||||
|
(lint
|
||||||
|
(globals
|
||||||
|
:max sleep write
|
||||||
|
cct_test describe expect howlci fail it pending stub)))
|
||||||
|
|
||||||
|
(at /src/web/mount/expr_template.lua (lint (globals :max __expr__)))
|
5
jitpack.yml
Normal file
5
jitpack.yml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
before_install:
|
||||||
|
- wget https://github.com/sormuras/bach/raw/master/install-jdk.sh
|
||||||
|
- source ./install-jdk.sh --feature 16 --license GPL
|
||||||
|
jdk:
|
||||||
|
- openjdk16
|
BIN
logo.png
BIN
logo.png
Binary file not shown.
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 8.1 KiB |
@@ -1,6 +1,5 @@
|
|||||||
pluginManagement {
|
pluginManagement {
|
||||||
repositories {
|
repositories {
|
||||||
jcenter()
|
|
||||||
maven {
|
maven {
|
||||||
name = 'Fabric'
|
name = 'Fabric'
|
||||||
url = 'https://maven.fabricmc.net/'
|
url = 'https://maven.fabricmc.net/'
|
||||||
@@ -9,4 +8,4 @@ pluginManagement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rootProject.name = "cc-restiched"
|
rootProject.name = "cc-restitched"
|
||||||
|
@@ -1,26 +1,13 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft;
|
package dan200.computercraft;
|
||||||
|
|
||||||
import static dan200.computercraft.shared.ComputerCraftRegistry.ModBlocks;
|
|
||||||
import static dan200.computercraft.shared.ComputerCraftRegistry.init;
|
|
||||||
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.EnumSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
|
|
||||||
import dan200.computercraft.api.turtle.event.TurtleAction;
|
|
||||||
import dan200.computercraft.core.apis.http.options.Action;
|
import dan200.computercraft.core.apis.http.options.Action;
|
||||||
import dan200.computercraft.core.apis.http.options.AddressRule;
|
import dan200.computercraft.core.apis.http.options.AddressRule;
|
||||||
import dan200.computercraft.core.apis.http.websocket.Websocket;
|
import dan200.computercraft.shared.Registry.ModBlocks;
|
||||||
import dan200.computercraft.shared.common.ColourableRecipe;
|
import dan200.computercraft.shared.common.ColourableRecipe;
|
||||||
import dan200.computercraft.shared.computer.core.ClientComputerRegistry;
|
import dan200.computercraft.shared.computer.core.ClientComputerRegistry;
|
||||||
import dan200.computercraft.shared.computer.core.ServerComputerRegistry;
|
import dan200.computercraft.shared.computer.core.ServerComputerRegistry;
|
||||||
@@ -35,105 +22,112 @@ import dan200.computercraft.shared.pocket.recipes.PocketComputerUpgradeRecipe;
|
|||||||
import dan200.computercraft.shared.proxy.ComputerCraftProxyCommon;
|
import dan200.computercraft.shared.proxy.ComputerCraftProxyCommon;
|
||||||
import dan200.computercraft.shared.turtle.recipes.TurtleRecipe;
|
import dan200.computercraft.shared.turtle.recipes.TurtleRecipe;
|
||||||
import dan200.computercraft.shared.turtle.recipes.TurtleUpgradeRecipe;
|
import dan200.computercraft.shared.turtle.recipes.TurtleUpgradeRecipe;
|
||||||
import dan200.computercraft.shared.util.Config;
|
|
||||||
import dan200.computercraft.shared.util.ImpostorRecipe;
|
import dan200.computercraft.shared.util.ImpostorRecipe;
|
||||||
import dan200.computercraft.shared.util.ImpostorShapelessRecipe;
|
import dan200.computercraft.shared.util.ImpostorShapelessRecipe;
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
|
|
||||||
import net.minecraft.item.ItemGroup;
|
|
||||||
import net.minecraft.item.ItemStack;
|
|
||||||
import net.minecraft.util.Identifier;
|
|
||||||
import net.minecraft.util.registry.Registry;
|
|
||||||
|
|
||||||
import net.fabricmc.api.ModInitializer;
|
import net.fabricmc.api.ModInitializer;
|
||||||
import net.fabricmc.fabric.api.client.itemgroup.FabricItemGroupBuilder;
|
import net.fabricmc.fabric.api.client.itemgroup.FabricItemGroupBuilder;
|
||||||
import net.fabricmc.fabric.api.resource.ResourceManagerHelper;
|
import net.fabricmc.fabric.api.resource.ResourceManagerHelper;
|
||||||
import net.fabricmc.fabric.api.resource.ResourcePackActivationType;
|
import net.fabricmc.fabric.api.resource.ResourcePackActivationType;
|
||||||
import net.fabricmc.loader.api.FabricLoader;
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.world.item.CreativeModeTab;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
public final class ComputerCraft implements ModInitializer {
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import static dan200.computercraft.shared.Registry.init;
|
||||||
|
|
||||||
|
public final class ComputerCraft implements ModInitializer
|
||||||
|
{
|
||||||
public static final String MOD_ID = "computercraft";
|
public static final String MOD_ID = "computercraft";
|
||||||
// Configuration options
|
|
||||||
public static final int terminalWidth_computer = 51;
|
|
||||||
public static final int terminalHeight_computer = 19;
|
|
||||||
public static final int terminalWidth_turtle = 39;
|
|
||||||
public static final int terminalHeight_turtle = 13;
|
|
||||||
public static final int terminalWidth_pocketComputer = 26;
|
|
||||||
public static final int terminalHeight_pocketComputer = 20;
|
|
||||||
// Registries
|
|
||||||
public static final ClientComputerRegistry clientComputerRegistry = new ClientComputerRegistry();
|
|
||||||
public static final ServerComputerRegistry serverComputerRegistry = new ServerComputerRegistry();
|
|
||||||
// Logging
|
|
||||||
public static final Logger log = LogManager.getLogger(MOD_ID);
|
|
||||||
public static ItemGroup MAIN_GROUP = FabricItemGroupBuilder.build(new Identifier(MOD_ID, "main"), () -> new ItemStack(ModBlocks.COMPUTER_NORMAL));
|
|
||||||
public static boolean commandRequireCreative = false;
|
|
||||||
public static MonitorRenderer monitorRenderer = MonitorRenderer.BEST;
|
|
||||||
public static int computerSpaceLimit = 1000 * 1000;
|
public static int computerSpaceLimit = 1000 * 1000;
|
||||||
public static int floppySpaceLimit = 125 * 1000;
|
public static int floppySpaceLimit = 125 * 1000;
|
||||||
public static int maximumFilesOpen = 128;
|
public static int maximumFilesOpen = 128;
|
||||||
public static boolean disable_lua51_features = false;
|
public static boolean disableLua51Features = false;
|
||||||
public static String default_computer_settings = "";
|
public static String defaultComputerSettings = "";
|
||||||
public static boolean debug_enable = true;
|
public static boolean logComputerErrors = true;
|
||||||
public static boolean logPeripheralErrors = false;
|
public static boolean commandRequireCreative = true;
|
||||||
public static int computer_threads = 1;
|
|
||||||
public static long maxMainGlobalTime = TimeUnit.MILLISECONDS.toNanos(10);
|
public static int computerThreads = 1;
|
||||||
public static long maxMainComputerTime = TimeUnit.MILLISECONDS.toNanos(5);
|
public static long maxMainGlobalTime = TimeUnit.MILLISECONDS.toNanos( 10 );
|
||||||
public static boolean http_enable = true;
|
public static long maxMainComputerTime = TimeUnit.MILLISECONDS.toNanos( 5 );
|
||||||
public static boolean http_websocket_enable = true;
|
|
||||||
public static int httpTimeout = 30000;
|
public static boolean httpEnabled = true;
|
||||||
|
public static boolean httpWebsocketEnabled = true;
|
||||||
|
public static List<AddressRule> httpRules = List.of(
|
||||||
|
AddressRule.parse( "$private", null, Action.DENY.toPartial() ),
|
||||||
|
AddressRule.parse( "*", null, Action.ALLOW.toPartial() )
|
||||||
|
);
|
||||||
|
|
||||||
public static int httpMaxRequests = 16;
|
public static int httpMaxRequests = 16;
|
||||||
public static long httpMaxDownload = 16 * 1024 * 1024;
|
|
||||||
public static long httpMaxUpload = 4 * 1024 * 1024;
|
|
||||||
public static int httpMaxWebsockets = 4;
|
public static int httpMaxWebsockets = 4;
|
||||||
public static int httpMaxWebsocketMessage = Websocket.MAX_MESSAGE_SIZE;
|
public static int httpDownloadBandwidth = 32 * 1024 * 1024;
|
||||||
|
public static int httpUploadBandwidth = 32 * 1024 * 1024;
|
||||||
|
|
||||||
public static boolean enableCommandBlock = false;
|
public static boolean enableCommandBlock = false;
|
||||||
public static int modem_range = 64;
|
public static int modemRange = 64;
|
||||||
public static int modem_highAltitudeRange = 384;
|
public static int modemHighAltitudeRange = 384;
|
||||||
public static int modem_rangeDuringStorm = 64;
|
public static int modemRangeDuringStorm = 64;
|
||||||
public static int modem_highAltitudeRangeDuringStorm = 384;
|
public static int modemHighAltitudeRangeDuringStorm = 384;
|
||||||
public static int maxNotesPerTick = 8;
|
public static int maxNotesPerTick = 8;
|
||||||
|
public static MonitorRenderer monitorRenderer = MonitorRenderer.BEST;
|
||||||
|
public static int monitorDistance = 65;
|
||||||
|
public static long monitorBandwidth = 1_000_000;
|
||||||
|
|
||||||
public static boolean turtlesNeedFuel = true;
|
public static boolean turtlesNeedFuel = true;
|
||||||
public static int turtleFuelLimit = 20000;
|
public static int turtleFuelLimit = 20000;
|
||||||
public static int advancedTurtleFuelLimit = 100000;
|
public static int advancedTurtleFuelLimit = 100000;
|
||||||
public static boolean turtlesObeyBlockProtection = true;
|
public static boolean turtlesObeyBlockProtection = true;
|
||||||
public static boolean turtlesCanPush = true;
|
public static boolean turtlesCanPush = true;
|
||||||
public static EnumSet<TurtleAction> turtleDisabledActions = EnumSet.noneOf(TurtleAction.class);
|
|
||||||
|
public static int computerTermWidth = 51;
|
||||||
|
public static int computerTermHeight = 19;
|
||||||
|
|
||||||
|
public static final int turtleTermWidth = 39;
|
||||||
|
public static final int turtleTermHeight = 13;
|
||||||
|
|
||||||
|
public static int pocketTermWidth = 26;
|
||||||
|
public static int pocketTermHeight = 20;
|
||||||
|
|
||||||
public static int monitorWidth = 8;
|
public static int monitorWidth = 8;
|
||||||
public static int monitorHeight = 6;
|
public static int monitorHeight = 6;
|
||||||
public static double monitorDistanceSq = 4096;
|
|
||||||
|
|
||||||
public static List<AddressRule> httpRules = Collections.unmodifiableList( Arrays.asList(
|
// Registries
|
||||||
AddressRule.parse( "$private", null, Action.DENY.toPartial() ),
|
public static final ClientComputerRegistry clientComputerRegistry = new ClientComputerRegistry();
|
||||||
AddressRule.parse( "*", null, Action.ALLOW.toPartial() )
|
public static final ServerComputerRegistry serverComputerRegistry = new ServerComputerRegistry();
|
||||||
) );
|
|
||||||
|
// Logging
|
||||||
|
public static final Logger log = LogManager.getLogger( MOD_ID );
|
||||||
|
|
||||||
|
public static CreativeModeTab MAIN_GROUP = FabricItemGroupBuilder.build( new ResourceLocation( MOD_ID, "main" ), () -> new ItemStack( ModBlocks.COMPUTER_NORMAL ) );
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInitialize() {
|
public void onInitialize()
|
||||||
Config.load(Paths.get(FabricLoader.getInstance()
|
{
|
||||||
.getConfigDir()
|
|
||||||
.toFile()
|
|
||||||
.getPath(), MOD_ID + ".json5"));
|
|
||||||
ComputerCraftProxyCommon.init();
|
ComputerCraftProxyCommon.init();
|
||||||
Registry.register(Registry.RECIPE_SERIALIZER, new Identifier(ComputerCraft.MOD_ID, "colour"), ColourableRecipe.SERIALIZER);
|
Registry.register( Registry.RECIPE_SERIALIZER, new ResourceLocation( ComputerCraft.MOD_ID, "colour" ), ColourableRecipe.SERIALIZER );
|
||||||
Registry.register(Registry.RECIPE_SERIALIZER, new Identifier(ComputerCraft.MOD_ID, "computer_upgrade"), ComputerUpgradeRecipe.SERIALIZER);
|
Registry.register( Registry.RECIPE_SERIALIZER, new ResourceLocation( ComputerCraft.MOD_ID, "computer_upgrade" ), ComputerUpgradeRecipe.SERIALIZER );
|
||||||
Registry.register(Registry.RECIPE_SERIALIZER,
|
Registry.register( Registry.RECIPE_SERIALIZER,
|
||||||
new Identifier(ComputerCraft.MOD_ID, "pocket_computer_upgrade"),
|
new ResourceLocation( ComputerCraft.MOD_ID, "pocket_computer_upgrade" ),
|
||||||
PocketComputerUpgradeRecipe.SERIALIZER);
|
PocketComputerUpgradeRecipe.SERIALIZER );
|
||||||
Registry.register(Registry.RECIPE_SERIALIZER, new Identifier(ComputerCraft.MOD_ID, "disk"), DiskRecipe.SERIALIZER);
|
Registry.register( Registry.RECIPE_SERIALIZER, new ResourceLocation( ComputerCraft.MOD_ID, "disk" ), DiskRecipe.SERIALIZER );
|
||||||
Registry.register(Registry.RECIPE_SERIALIZER, new Identifier(ComputerCraft.MOD_ID, "printout"), PrintoutRecipe.SERIALIZER);
|
Registry.register( Registry.RECIPE_SERIALIZER, new ResourceLocation( ComputerCraft.MOD_ID, "printout" ), PrintoutRecipe.SERIALIZER );
|
||||||
Registry.register(Registry.RECIPE_SERIALIZER, new Identifier(ComputerCraft.MOD_ID, "turtle"), TurtleRecipe.SERIALIZER);
|
Registry.register( Registry.RECIPE_SERIALIZER, new ResourceLocation( ComputerCraft.MOD_ID, "turtle" ), TurtleRecipe.SERIALIZER );
|
||||||
Registry.register(Registry.RECIPE_SERIALIZER, new Identifier(ComputerCraft.MOD_ID, "turtle_upgrade"), TurtleUpgradeRecipe.SERIALIZER);
|
Registry.register( Registry.RECIPE_SERIALIZER, new ResourceLocation( ComputerCraft.MOD_ID, "turtle_upgrade" ), TurtleUpgradeRecipe.SERIALIZER );
|
||||||
Registry.register(Registry.RECIPE_SERIALIZER, new Identifier(ComputerCraft.MOD_ID, "impostor_shaped"), ImpostorRecipe.SERIALIZER);
|
Registry.register( Registry.RECIPE_SERIALIZER, new ResourceLocation( ComputerCraft.MOD_ID, "impostor_shaped" ), ImpostorRecipe.SERIALIZER );
|
||||||
Registry.register(Registry.RECIPE_SERIALIZER, new Identifier(ComputerCraft.MOD_ID, "impostor_shapeless"), ImpostorShapelessRecipe.SERIALIZER);
|
Registry.register( Registry.RECIPE_SERIALIZER, new ResourceLocation( ComputerCraft.MOD_ID, "impostor_shapeless" ), ImpostorShapelessRecipe.SERIALIZER );
|
||||||
Registry.register(Registry.LOOT_CONDITION_TYPE, new Identifier(ComputerCraft.MOD_ID, "block_named"), BlockNamedEntityLootCondition.TYPE);
|
Registry.register( Registry.LOOT_CONDITION_TYPE, new ResourceLocation( ComputerCraft.MOD_ID, "block_named" ), BlockNamedEntityLootCondition.TYPE );
|
||||||
Registry.register(Registry.LOOT_CONDITION_TYPE, new Identifier(ComputerCraft.MOD_ID, "player_creative"), PlayerCreativeLootCondition.TYPE);
|
Registry.register( Registry.LOOT_CONDITION_TYPE, new ResourceLocation( ComputerCraft.MOD_ID, "player_creative" ), PlayerCreativeLootCondition.TYPE );
|
||||||
Registry.register(Registry.LOOT_CONDITION_TYPE, new Identifier(ComputerCraft.MOD_ID, "has_id"), HasComputerIdLootCondition.TYPE);
|
Registry.register( Registry.LOOT_CONDITION_TYPE, new ResourceLocation( ComputerCraft.MOD_ID, "has_id" ), HasComputerIdLootCondition.TYPE );
|
||||||
init();
|
init();
|
||||||
FabricLoader.getInstance().getModContainer(MOD_ID).ifPresent(modContainer -> {
|
FabricLoader.getInstance().getModContainer( MOD_ID ).ifPresent( modContainer -> {
|
||||||
ResourceManagerHelper.registerBuiltinResourcePack(new Identifier(MOD_ID, "classic"), modContainer, ResourcePackActivationType.NORMAL);
|
ResourceManagerHelper.registerBuiltinResourcePack( new ResourceLocation( MOD_ID, "classic" ), modContainer, ResourcePackActivationType.NORMAL );
|
||||||
ResourceManagerHelper.registerBuiltinResourcePack(new Identifier(MOD_ID, "overhaul"), modContainer, ResourcePackActivationType.NORMAL);
|
ResourceManagerHelper.registerBuiltinResourcePack( new ResourceLocation( MOD_ID, "overhaul" ), modContainer, ResourcePackActivationType.NORMAL );
|
||||||
});
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,18 +1,10 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft;
|
package dan200.computercraft;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import dan200.computercraft.api.ComputerCraftAPI.IComputerCraftAPI;
|
import dan200.computercraft.api.ComputerCraftAPI.IComputerCraftAPI;
|
||||||
import dan200.computercraft.api.filesystem.IMount;
|
import dan200.computercraft.api.filesystem.IMount;
|
||||||
import dan200.computercraft.api.filesystem.IWritableMount;
|
import dan200.computercraft.api.filesystem.IWritableMount;
|
||||||
@@ -31,118 +23,92 @@ import dan200.computercraft.core.asm.GenericMethod;
|
|||||||
import dan200.computercraft.core.filesystem.FileMount;
|
import dan200.computercraft.core.filesystem.FileMount;
|
||||||
import dan200.computercraft.core.filesystem.ResourceMount;
|
import dan200.computercraft.core.filesystem.ResourceMount;
|
||||||
import dan200.computercraft.fabric.mixin.MinecraftServerAccess;
|
import dan200.computercraft.fabric.mixin.MinecraftServerAccess;
|
||||||
import dan200.computercraft.shared.BundledRedstone;
|
import dan200.computercraft.shared.*;
|
||||||
import dan200.computercraft.shared.MediaProviders;
|
|
||||||
import dan200.computercraft.shared.Peripherals;
|
|
||||||
import dan200.computercraft.shared.PocketUpgrades;
|
|
||||||
import dan200.computercraft.shared.TurtleUpgrades;
|
|
||||||
import dan200.computercraft.shared.peripheral.modem.wired.TileCable;
|
import dan200.computercraft.shared.peripheral.modem.wired.TileCable;
|
||||||
import dan200.computercraft.shared.peripheral.modem.wired.TileWiredModemFull;
|
import dan200.computercraft.shared.peripheral.modem.wired.TileWiredModemFull;
|
||||||
import dan200.computercraft.shared.peripheral.modem.wireless.WirelessNetwork;
|
import dan200.computercraft.shared.peripheral.modem.wireless.WirelessNetwork;
|
||||||
import dan200.computercraft.shared.util.IDAssigner;
|
import dan200.computercraft.shared.util.IDAssigner;
|
||||||
import dan200.computercraft.shared.wired.WiredNode;
|
import dan200.computercraft.shared.wired.WiredNode;
|
||||||
import me.shedaniel.cloth.api.utils.v1.GameInstanceUtils;
|
import me.shedaniel.cloth.api.utils.v1.GameInstanceUtils;
|
||||||
|
|
||||||
import net.minecraft.block.entity.BlockEntity;
|
|
||||||
import net.minecraft.resource.ReloadableResourceManager;
|
|
||||||
import net.minecraft.server.MinecraftServer;
|
|
||||||
import net.minecraft.util.Identifier;
|
|
||||||
import net.minecraft.util.math.BlockPos;
|
|
||||||
import net.minecraft.util.math.Direction;
|
|
||||||
import net.minecraft.world.BlockView;
|
|
||||||
import net.minecraft.world.World;
|
|
||||||
|
|
||||||
import net.fabricmc.loader.api.FabricLoader;
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.server.packs.resources.ReloadableResourceManager;
|
||||||
|
import net.minecraft.world.level.BlockGetter;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
|
||||||
public final class ComputerCraftAPIImpl implements IComputerCraftAPI {
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
public final class ComputerCraftAPIImpl implements IComputerCraftAPI
|
||||||
|
{
|
||||||
public static final ComputerCraftAPIImpl INSTANCE = new ComputerCraftAPIImpl();
|
public static final ComputerCraftAPIImpl INSTANCE = new ComputerCraftAPIImpl();
|
||||||
|
|
||||||
private String version;
|
private String version;
|
||||||
|
|
||||||
private ComputerCraftAPIImpl() {
|
private ComputerCraftAPIImpl()
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static InputStream getResourceFile(String domain, String subPath) {
|
public static InputStream getResourceFile( String domain, String subPath )
|
||||||
MinecraftServer server = GameInstanceUtils.getServer();
|
{
|
||||||
if (server != null) {
|
ReloadableResourceManager manager = (ReloadableResourceManager) ((MinecraftServerAccess) GameInstanceUtils.getServer()).callGetResourceManager();
|
||||||
ReloadableResourceManager manager = (ReloadableResourceManager) ((MinecraftServerAccess)server).getServerResourceManager().getResourceManager();
|
try
|
||||||
try {
|
{
|
||||||
return manager.getResource(new Identifier(domain, subPath))
|
return manager.getResource( new ResourceLocation( domain, subPath ) ).getInputStream();
|
||||||
.getInputStream();
|
}
|
||||||
} catch (IOException ignored) {
|
catch( IOException ignored )
|
||||||
return null;
|
{
|
||||||
}
|
return null;
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public String getInstalledVersion() {
|
public String getInstalledVersion()
|
||||||
if (this.version != null) {
|
{
|
||||||
return this.version;
|
if( version != null ) return version;
|
||||||
|
return version = FabricLoader.getInstance().getModContainer( ComputerCraft.MOD_ID )
|
||||||
|
.map( x -> x.getMetadata().getVersion().toString() )
|
||||||
|
.orElse( "unknown" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int createUniqueNumberedSaveDir( @Nonnull Level world, @Nonnull String parentSubPath )
|
||||||
|
{
|
||||||
|
return IDAssigner.getNextId( parentSubPath );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IWritableMount createSaveDirMount( @Nonnull Level world, @Nonnull String subPath, long capacity )
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return new FileMount( new File( IDAssigner.getDir(), subPath ), capacity );
|
||||||
}
|
}
|
||||||
return this.version = FabricLoader.getInstance()
|
catch( Exception e )
|
||||||
.getModContainer(ComputerCraft.MOD_ID)
|
{
|
||||||
.map(x -> x.getMetadata()
|
|
||||||
.getVersion()
|
|
||||||
.toString())
|
|
||||||
.orElse("unknown");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int createUniqueNumberedSaveDir(@Nonnull World world, @Nonnull String parentSubPath) {
|
|
||||||
return IDAssigner.getNextId(parentSubPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IWritableMount createSaveDirMount(@Nonnull World world, @Nonnull String subPath, long capacity) {
|
|
||||||
try {
|
|
||||||
return new FileMount(new File(IDAssigner.getDir(), subPath), capacity);
|
|
||||||
} catch (Exception e) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IMount createResourceMount(@Nonnull String domain, @Nonnull String subPath) {
|
public IMount createResourceMount( @Nonnull String domain, @Nonnull String subPath )
|
||||||
MinecraftServer server = GameInstanceUtils.getServer();
|
{
|
||||||
if (server != null) {
|
ReloadableResourceManager manager = (ReloadableResourceManager) ((MinecraftServerAccess) GameInstanceUtils.getServer()).callGetResourceManager();
|
||||||
ReloadableResourceManager manager = (ReloadableResourceManager) ((MinecraftServerAccess)server).getServerResourceManager().getResourceManager();
|
ResourceMount mount = ResourceMount.get( domain, subPath, manager );
|
||||||
ResourceMount mount = ResourceMount.get(domain, subPath, manager);
|
return mount.exists( "" ) ? mount : null;
|
||||||
return mount.exists("") ? mount : null;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerPeripheralProvider(@Nonnull IPeripheralProvider provider) {
|
public void registerPeripheralProvider( @Nonnull IPeripheralProvider provider )
|
||||||
Peripherals.register(provider);
|
{
|
||||||
}
|
Peripherals.register( provider );
|
||||||
|
|
||||||
@Override
|
|
||||||
public void registerTurtleUpgrade(@Nonnull ITurtleUpgrade upgrade) {
|
|
||||||
TurtleUpgrades.register(upgrade);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void registerBundledRedstoneProvider(@Nonnull IBundledRedstoneProvider provider) {
|
|
||||||
BundledRedstone.register(provider);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getBundledRedstoneOutput(@Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side) {
|
|
||||||
return BundledRedstone.getDefaultOutput(world, pos, side);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void registerMediaProvider(@Nonnull IMediaProvider provider) {
|
|
||||||
MediaProviders.register(provider);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void registerPocketUpgrade(@Nonnull IPocketUpgrade upgrade) {
|
|
||||||
PocketUpgrades.register(upgrade);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -151,30 +117,67 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI {
|
|||||||
GenericMethod.register( source );
|
GenericMethod.register( source );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerTurtleUpgrade( @Nonnull ITurtleUpgrade upgrade )
|
||||||
|
{
|
||||||
|
TurtleUpgrades.register( upgrade );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerPocketUpgrade( @Nonnull IPocketUpgrade upgrade )
|
||||||
|
{
|
||||||
|
PocketUpgrades.register( upgrade );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerBundledRedstoneProvider( @Nonnull IBundledRedstoneProvider provider )
|
||||||
|
{
|
||||||
|
BundledRedstone.register( provider );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getBundledRedstoneOutput( @Nonnull Level world, @Nonnull BlockPos pos, @Nonnull Direction side )
|
||||||
|
{
|
||||||
|
return BundledRedstone.getDefaultOutput( world, pos, side );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerMediaProvider( @Nonnull IMediaProvider provider )
|
||||||
|
{
|
||||||
|
MediaProviders.register( provider );
|
||||||
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public IPacketNetwork getWirelessNetwork() {
|
public IPacketNetwork getWirelessNetwork()
|
||||||
|
{
|
||||||
return WirelessNetwork.getUniversal();
|
return WirelessNetwork.getUniversal();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerAPIFactory(@Nonnull ILuaAPIFactory factory) {
|
public void registerAPIFactory( @Nonnull ILuaAPIFactory factory )
|
||||||
ApiFactories.register(factory);
|
{
|
||||||
|
ApiFactories.register( factory );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public IWiredNode createWiredNodeForElement(@Nonnull IWiredElement element) {
|
public IWiredNode createWiredNodeForElement( @Nonnull IWiredElement element )
|
||||||
return new WiredNode(element);
|
{
|
||||||
|
return new WiredNode( element );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public IWiredElement getWiredElementAt(@Nonnull BlockView world, @Nonnull BlockPos pos, @Nonnull Direction side) {
|
public IWiredElement getWiredElementAt( @Nonnull BlockGetter world, @Nonnull BlockPos pos, @Nonnull Direction side )
|
||||||
BlockEntity tile = world.getBlockEntity(pos);
|
{
|
||||||
if (tile instanceof TileCable) {
|
BlockEntity tile = world.getBlockEntity( pos );
|
||||||
return ((TileCable) tile).getElement(side);
|
if( tile instanceof TileCable )
|
||||||
} else if (tile instanceof TileWiredModemFull) {
|
{
|
||||||
|
return ((TileCable) tile).getElement( side );
|
||||||
|
}
|
||||||
|
else if( tile instanceof TileWiredModemFull )
|
||||||
|
{
|
||||||
return ((TileWiredModemFull) tile).getElement();
|
return ((TileWiredModemFull) tile).getElement();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@@ -1,14 +1,10 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||||
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
|
||||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.api;
|
package dan200.computercraft.api;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import dan200.computercraft.api.filesystem.IMount;
|
import dan200.computercraft.api.filesystem.IMount;
|
||||||
import dan200.computercraft.api.filesystem.IWritableMount;
|
import dan200.computercraft.api.filesystem.IWritableMount;
|
||||||
import dan200.computercraft.api.lua.GenericSource;
|
import dan200.computercraft.api.lua.GenericSource;
|
||||||
@@ -24,97 +20,84 @@ import dan200.computercraft.api.peripheral.IPeripheralProvider;
|
|||||||
import dan200.computercraft.api.pocket.IPocketUpgrade;
|
import dan200.computercraft.api.pocket.IPocketUpgrade;
|
||||||
import dan200.computercraft.api.redstone.IBundledRedstoneProvider;
|
import dan200.computercraft.api.redstone.IBundledRedstoneProvider;
|
||||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.world.level.BlockGetter;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
|
||||||
import net.minecraft.util.math.BlockPos;
|
import javax.annotation.Nonnull;
|
||||||
import net.minecraft.util.math.Direction;
|
import javax.annotation.Nullable;
|
||||||
import net.minecraft.world.BlockView;
|
|
||||||
import net.minecraft.world.World;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The static entry point to the ComputerCraft API.
|
* The static entry point to the ComputerCraft API.
|
||||||
*
|
*
|
||||||
* Members in this class must be called after mod_ComputerCraft has been initialised, but may be called before it is fully loaded.
|
* Members in this class must be called after mod_ComputerCraft has been initialised, but may be called before it is
|
||||||
|
* fully loaded.
|
||||||
*/
|
*/
|
||||||
public final class ComputerCraftAPI {
|
public final class ComputerCraftAPI
|
||||||
private static IComputerCraftAPI instance;
|
{
|
||||||
|
public static final String MOD_ID = "computercraft";
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Deprecated
|
public static String getInstalledVersion()
|
||||||
public static String getAPIVersion() {
|
{
|
||||||
return getInstalledVersion();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
public static String getInstalledVersion() {
|
|
||||||
return getInstance().getInstalledVersion();
|
return getInstance().getInstalledVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
private static IComputerCraftAPI getInstance() {
|
|
||||||
if (instance != null) {
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
return instance = (IComputerCraftAPI) Class.forName("dan200.computercraft.ComputerCraftAPIImpl")
|
|
||||||
.getField("INSTANCE")
|
|
||||||
.get(null);
|
|
||||||
} catch (ReflectiveOperationException e) {
|
|
||||||
throw new IllegalStateException("Cannot find ComputerCraft API", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a numbered directory in a subfolder of the save directory for a given world, and returns that number.
|
* Creates a numbered directory in a subfolder of the save directory for a given world, and returns that number.
|
||||||
*
|
*
|
||||||
* Use in conjunction with createSaveDirMount() to create a unique place for your peripherals or media items to store files.
|
* Use in conjunction with createSaveDirMount() to create a unique place for your peripherals or media items to store files.
|
||||||
*
|
*
|
||||||
* @param world The world for which the save dir should be created. This should be the server side world object.
|
* @param world The world for which the save dir should be created. This should be the server side world object.
|
||||||
* @param parentSubPath The folder path within the save directory where the new directory should be created. eg: "computercraft/disk"
|
* @param parentSubPath The folder path within the save directory where the new directory should be created. eg: "computercraft/disk"
|
||||||
* @return The numerical value of the name of the new folder, or -1 if the folder could not be created for some reason.
|
* @return The numerical value of the name of the new folder, or -1 if the folder could not be created for some reason.
|
||||||
*
|
*
|
||||||
* eg: if createUniqueNumberedSaveDir( world, "computer/disk" ) was called returns 42, then "computer/disk/42" is now available for writing.
|
* eg: if createUniqueNumberedSaveDir( world, "computer/disk" ) was called returns 42, then "computer/disk/42" is now
|
||||||
* @see #createSaveDirMount(World, String, long)
|
* available for writing.
|
||||||
|
* @see #createSaveDirMount(Level, String, long)
|
||||||
*/
|
*/
|
||||||
public static int createUniqueNumberedSaveDir(@Nonnull World world, @Nonnull String parentSubPath) {
|
public static int createUniqueNumberedSaveDir( @Nonnull Level world, @Nonnull String parentSubPath )
|
||||||
return getInstance().createUniqueNumberedSaveDir(world, parentSubPath);
|
{
|
||||||
|
return getInstance().createUniqueNumberedSaveDir( world, parentSubPath );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a file system mount that maps to a subfolder of the save directory for a given world, and returns it.
|
* Creates a file system mount that maps to a subfolder of the save directory for a given world, and returns it.
|
||||||
*
|
*
|
||||||
* Use in conjunction with IComputerAccess.mount() or IComputerAccess.mountWritable() to mount a folder from the users save directory onto a computers
|
* Use in conjunction with IComputerAccess.mount() or IComputerAccess.mountWritable() to mount a folder from the
|
||||||
* file system.
|
* users save directory onto a computers file system.
|
||||||
*
|
*
|
||||||
* @param world The world for which the save dir can be found. This should be the server side world object.
|
* @param world The world for which the save dir can be found. This should be the server side world object.
|
||||||
* @param subPath The folder path within the save directory that the mount should map to. eg: "computer/disk/42". Use createUniqueNumberedSaveDir()
|
* @param subPath The folder path within the save directory that the mount should map to. eg: "computer/disk/42".
|
||||||
* to create a new numbered folder to use.
|
* Use createUniqueNumberedSaveDir() to create a new numbered folder to use.
|
||||||
* @param capacity The amount of data that can be stored in the directory before it fills up, in bytes.
|
* @param capacity The amount of data that can be stored in the directory before it fills up, in bytes.
|
||||||
* @return The mount, or null if it could be created for some reason. Use IComputerAccess.mount() or IComputerAccess.mountWritable() to mount this on a
|
* @return The mount, or null if it could be created for some reason. Use IComputerAccess.mount() or IComputerAccess.mountWritable()
|
||||||
* Computers' file system.
|
* to mount this on a Computers' file system.
|
||||||
* @see #createUniqueNumberedSaveDir(World, String)
|
* @see #createUniqueNumberedSaveDir(Level, String)
|
||||||
* @see IComputerAccess#mount(String, IMount)
|
* @see IComputerAccess#mount(String, IMount)
|
||||||
* @see IComputerAccess#mountWritable(String, IWritableMount)
|
* @see IComputerAccess#mountWritable(String, IWritableMount)
|
||||||
* @see IMount
|
* @see IMount
|
||||||
* @see IWritableMount
|
* @see IWritableMount
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public static IWritableMount createSaveDirMount(@Nonnull World world, @Nonnull String subPath, long capacity) {
|
public static IWritableMount createSaveDirMount( @Nonnull Level world, @Nonnull String subPath, long capacity )
|
||||||
return getInstance().createSaveDirMount(world, subPath, capacity);
|
{
|
||||||
|
return getInstance().createSaveDirMount( world, subPath, capacity );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a file system mount to a resource folder, and returns it.
|
* Creates a file system mount to a resource folder, and returns it.
|
||||||
*
|
*
|
||||||
* Use in conjunction with {@link IComputerAccess#mount} or {@link IComputerAccess#mountWritable} to mount a resource folder onto a computer's file
|
* Use in conjunction with {@link IComputerAccess#mount} or {@link IComputerAccess#mountWritable} to mount a
|
||||||
* system.
|
* resource folder onto a computer's file system.
|
||||||
*
|
*
|
||||||
* The files in this mount will be a combination of files in all mod jar, and data packs that contain
|
* The files in this mount will be a combination of files in all mod jar, and data packs that contain
|
||||||
* resources with the same domain and path. For instance, ComputerCraft's resources are stored in
|
* resources with the same domain and path. For instance, ComputerCraft's resources are stored in
|
||||||
* "/data/computercraft/lua/rom". We construct a mount for that with
|
* "/data/computercraft/lua/rom". We construct a mount for that with
|
||||||
* {@code createResourceMount("computercraft", "lua/rom")}.
|
* {@code createResourceMount("computercraft", "lua/rom")}.
|
||||||
*
|
*
|
||||||
* @param domain The domain under which to look for resources. eg: "mymod".
|
* @param domain The domain under which to look for resources. eg: "mymod".
|
||||||
* @param subPath The subPath under which to look for resources. eg: "lua/myfiles".
|
* @param subPath The subPath under which to look for resources. eg: "lua/myfiles".
|
||||||
* @return The mount, or {@code null} if it could be created for some reason.
|
* @return The mount, or {@code null} if it could be created for some reason.
|
||||||
* @see IComputerAccess#mount(String, IMount)
|
* @see IComputerAccess#mount(String, IMount)
|
||||||
@@ -122,19 +105,21 @@ public final class ComputerCraftAPI {
|
|||||||
* @see IMount
|
* @see IMount
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public static IMount createResourceMount(@Nonnull String domain, @Nonnull String subPath) {
|
public static IMount createResourceMount( @Nonnull String domain, @Nonnull String subPath )
|
||||||
return getInstance().createResourceMount(domain, subPath);
|
{
|
||||||
|
return getInstance().createResourceMount( domain, subPath );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a peripheral provider to convert blocks into {@link IPeripheral} implementations.
|
* rers a peripheral provider to convert blocks into {@link IPeripheral} implementations.
|
||||||
*
|
*
|
||||||
* @param provider The peripheral provider to register.
|
* @param provider The peripheral provider to register.
|
||||||
* @see IPeripheral
|
* @see IPeripheral
|
||||||
* @see IPeripheralProvider
|
* @see IPeripheralProvider
|
||||||
*/
|
*/
|
||||||
public static void registerPeripheralProvider(@Nonnull IPeripheralProvider provider) {
|
public static void registerPeripheralProvider( @Nonnull IPeripheralProvider provider )
|
||||||
getInstance().registerPeripheralProvider(provider);
|
{
|
||||||
|
getInstance().registerPeripheralProvider( provider );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -149,14 +134,29 @@ public final class ComputerCraftAPI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a new turtle turtle for use in ComputerCraft. After calling this, users should be able to craft Turtles with your new turtle. It is
|
* Registers a new turtle upgrade for use in ComputerCraft. After calling this,
|
||||||
|
* users should be able to craft Turtles with your upgrade's ItemStack. It is
|
||||||
* recommended to call this during the load() method of your mod.
|
* recommended to call this during the load() method of your mod.
|
||||||
*
|
*
|
||||||
* @param upgrade The turtle upgrade to register.
|
* @param upgrade The turtle upgrade to register.
|
||||||
* @see ITurtleUpgrade
|
* @see ITurtleUpgrade
|
||||||
*/
|
*/
|
||||||
public static void registerTurtleUpgrade(@Nonnull ITurtleUpgrade upgrade) {
|
public static void registerTurtleUpgrade( @Nonnull ITurtleUpgrade upgrade )
|
||||||
getInstance().registerTurtleUpgrade(upgrade);
|
{
|
||||||
|
getInstance().registerTurtleUpgrade( upgrade );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a new pocket upgrade for use in ComputerCraft. After calling this,
|
||||||
|
* users should be able to craft pocket computers with your upgrade's ItemStack. It is
|
||||||
|
* recommended to call this during the load() method of your mod.
|
||||||
|
*
|
||||||
|
* @param upgrade The pocket upgrade to register.
|
||||||
|
* @see IPocketUpgrade
|
||||||
|
*/
|
||||||
|
public static void registerPocketUpgrade( @Nonnull IPocketUpgrade upgrade )
|
||||||
|
{
|
||||||
|
getInstance().registerPocketUpgrade( upgrade );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -165,22 +165,24 @@ public final class ComputerCraftAPI {
|
|||||||
* @param provider The bundled redstone provider to register.
|
* @param provider The bundled redstone provider to register.
|
||||||
* @see IBundledRedstoneProvider
|
* @see IBundledRedstoneProvider
|
||||||
*/
|
*/
|
||||||
public static void registerBundledRedstoneProvider(@Nonnull IBundledRedstoneProvider provider) {
|
public static void registerBundledRedstoneProvider( @Nonnull IBundledRedstoneProvider provider )
|
||||||
getInstance().registerBundledRedstoneProvider(provider);
|
{
|
||||||
|
getInstance().registerBundledRedstoneProvider( provider );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If there is a Computer or Turtle at a certain position in the world, get it's bundled redstone output.
|
* If there is a Computer or Turtle at a certain position in the world, get it's bundled redstone output.
|
||||||
*
|
*
|
||||||
* @param world The world this block is in.
|
* @param world The world this block is in.
|
||||||
* @param pos The position this block is at.
|
* @param pos The position this block is at.
|
||||||
* @param side The side to extract the bundled redstone output from.
|
* @param side The side to extract the bundled redstone output from.
|
||||||
* @return If there is a block capable of emitting bundled redstone at the location, it's signal (0-65535) will be returned. If there is no block
|
* @return If there is a block capable of emitting bundled redstone at the location, it's signal (0-65535) will be returned.
|
||||||
* capable of emitting bundled redstone at the location, -1 will be returned.
|
* If there is no block capable of emitting bundled redstone at the location, -1 will be returned.
|
||||||
* @see IBundledRedstoneProvider
|
* @see IBundledRedstoneProvider
|
||||||
*/
|
*/
|
||||||
public static int getBundledRedstoneOutput(@Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side) {
|
public static int getBundledRedstoneOutput( @Nonnull Level world, @Nonnull BlockPos pos, @Nonnull Direction side )
|
||||||
return getInstance().getBundledRedstoneOutput(world, pos, side);
|
{
|
||||||
|
return getInstance().getBundledRedstoneOutput( world, pos, side );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -189,12 +191,9 @@ public final class ComputerCraftAPI {
|
|||||||
* @param provider The media provider to register.
|
* @param provider The media provider to register.
|
||||||
* @see IMediaProvider
|
* @see IMediaProvider
|
||||||
*/
|
*/
|
||||||
public static void registerMediaProvider(@Nonnull IMediaProvider provider) {
|
public static void registerMediaProvider( @Nonnull IMediaProvider provider )
|
||||||
getInstance().registerMediaProvider(provider);
|
{
|
||||||
}
|
getInstance().registerMediaProvider( provider );
|
||||||
|
|
||||||
public static void registerPocketUpgrade(@Nonnull IPocketUpgrade upgrade) {
|
|
||||||
getInstance().registerPocketUpgrade(upgrade);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -202,12 +201,14 @@ public final class ComputerCraftAPI {
|
|||||||
*
|
*
|
||||||
* @return The global wireless network, or {@code null} if it could not be fetched.
|
* @return The global wireless network, or {@code null} if it could not be fetched.
|
||||||
*/
|
*/
|
||||||
public static IPacketNetwork getWirelessNetwork() {
|
public static IPacketNetwork getWirelessNetwork()
|
||||||
|
{
|
||||||
return getInstance().getWirelessNetwork();
|
return getInstance().getWirelessNetwork();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void registerAPIFactory(@Nonnull ILuaAPIFactory factory) {
|
public static void registerAPIFactory( @Nonnull ILuaAPIFactory factory )
|
||||||
getInstance().registerAPIFactory(factory);
|
{
|
||||||
|
getInstance().registerAPIFactory( factory );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -218,59 +219,79 @@ public final class ComputerCraftAPI {
|
|||||||
* @see IWiredElement#getNode()
|
* @see IWiredElement#getNode()
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public static IWiredNode createWiredNodeForElement(@Nonnull IWiredElement element) {
|
public static IWiredNode createWiredNodeForElement( @Nonnull IWiredElement element )
|
||||||
return getInstance().createWiredNodeForElement(element);
|
{
|
||||||
|
return getInstance().createWiredNodeForElement( element );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the wired network element for a block in world.
|
* Get the wired network element for a block in world.
|
||||||
*
|
*
|
||||||
* @param world The world the block exists in
|
* @param world The world the block exists in
|
||||||
* @param pos The position the block exists in
|
* @param pos The position the block exists in
|
||||||
* @param side The side to extract the network element from
|
* @param side The side to extract the network element from
|
||||||
* @return The element's node
|
* @return The element's node
|
||||||
* @see IWiredElement#getNode()
|
* @see IWiredElement#getNode()
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public static IWiredElement getWiredElementAt(@Nonnull BlockView world, @Nonnull BlockPos pos, @Nonnull Direction side) {
|
public static IWiredElement getWiredElementAt( @Nonnull BlockGetter world, @Nonnull BlockPos pos, @Nonnull Direction side )
|
||||||
return getInstance().getWiredElementAt(world, pos, side);
|
{
|
||||||
|
return getInstance().getWiredElementAt( world, pos, side );
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IComputerCraftAPI {
|
private static IComputerCraftAPI instance;
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
private static IComputerCraftAPI getInstance()
|
||||||
|
{
|
||||||
|
if( instance != null ) return instance;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return instance = (IComputerCraftAPI) Class.forName( "dan200.computercraft.ComputerCraftAPIImpl" )
|
||||||
|
.getField( "INSTANCE" ).get( null );
|
||||||
|
}
|
||||||
|
catch( ReflectiveOperationException e )
|
||||||
|
{
|
||||||
|
throw new IllegalStateException( "Cannot find ComputerCraft API", e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IComputerCraftAPI
|
||||||
|
{
|
||||||
@Nonnull
|
@Nonnull
|
||||||
String getInstalledVersion();
|
String getInstalledVersion();
|
||||||
|
|
||||||
int createUniqueNumberedSaveDir(@Nonnull World world, @Nonnull String parentSubPath);
|
int createUniqueNumberedSaveDir( @Nonnull Level world, @Nonnull String parentSubPath );
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
IWritableMount createSaveDirMount(@Nonnull World world, @Nonnull String subPath, long capacity);
|
IWritableMount createSaveDirMount( @Nonnull Level world, @Nonnull String subPath, long capacity );
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
IMount createResourceMount(@Nonnull String domain, @Nonnull String subPath);
|
IMount createResourceMount( @Nonnull String domain, @Nonnull String subPath );
|
||||||
|
|
||||||
void registerPeripheralProvider(@Nonnull IPeripheralProvider provider);
|
void registerPeripheralProvider( @Nonnull IPeripheralProvider provider );
|
||||||
|
|
||||||
void registerGenericSource( @Nonnull GenericSource source );
|
void registerGenericSource( @Nonnull GenericSource source );
|
||||||
|
|
||||||
void registerTurtleUpgrade(@Nonnull ITurtleUpgrade upgrade);
|
void registerTurtleUpgrade( @Nonnull ITurtleUpgrade upgrade );
|
||||||
|
|
||||||
void registerBundledRedstoneProvider(@Nonnull IBundledRedstoneProvider provider);
|
void registerPocketUpgrade( @Nonnull IPocketUpgrade upgrade );
|
||||||
|
|
||||||
int getBundledRedstoneOutput(@Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side);
|
void registerBundledRedstoneProvider( @Nonnull IBundledRedstoneProvider provider );
|
||||||
|
|
||||||
void registerMediaProvider(@Nonnull IMediaProvider provider);
|
int getBundledRedstoneOutput( @Nonnull Level world, @Nonnull BlockPos pos, @Nonnull Direction side );
|
||||||
|
|
||||||
void registerPocketUpgrade(@Nonnull IPocketUpgrade upgrade);
|
|
||||||
|
|
||||||
|
void registerMediaProvider( @Nonnull IMediaProvider provider );
|
||||||
@Nonnull
|
@Nonnull
|
||||||
IPacketNetwork getWirelessNetwork();
|
IPacketNetwork getWirelessNetwork();
|
||||||
|
|
||||||
void registerAPIFactory(@Nonnull ILuaAPIFactory factory);
|
void registerAPIFactory( @Nonnull ILuaAPIFactory factory );
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
IWiredNode createWiredNodeForElement(@Nonnull IWiredElement element);
|
IWiredNode createWiredNodeForElement( @Nonnull IWiredElement element );
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
IWiredElement getWiredElementAt(@Nonnull BlockView world, @Nonnull BlockPos pos, @Nonnull Direction side);
|
IWiredElement getWiredElementAt( @Nonnull BlockGetter world, @Nonnull BlockPos pos, @Nonnull Direction side );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||||
|
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
|
||||||
|
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||||
|
*/
|
||||||
|
package dan200.computercraft.api;
|
||||||
|
|
||||||
|
import dan200.computercraft.ComputerCraft;
|
||||||
|
import net.fabricmc.fabric.api.tag.TagFactory;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.tags.Tag;
|
||||||
|
import net.minecraft.world.item.Item;
|
||||||
|
import net.minecraft.world.level.block.Block;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tags provided by ComputerCraft.
|
||||||
|
*/
|
||||||
|
public class ComputerCraftTags
|
||||||
|
{
|
||||||
|
public static class Items
|
||||||
|
{
|
||||||
|
public static final Tag.Named<Item> COMPUTER = make( "computer" );
|
||||||
|
public static final Tag.Named<Item> TURTLE = make( "turtle" );
|
||||||
|
public static final Tag.Named<Item> WIRED_MODEM = make( "wired_modem" );
|
||||||
|
public static final Tag.Named<Item> MONITOR = make( "monitor" );
|
||||||
|
|
||||||
|
private static Tag.Named<Item> make( String name )
|
||||||
|
{
|
||||||
|
return TagFactory.ITEM.create( new ResourceLocation( ComputerCraft.MOD_ID, name ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Blocks
|
||||||
|
{
|
||||||
|
public static final Tag.Named<Block> COMPUTER = make( "computer" );
|
||||||
|
public static final Tag.Named<Block> TURTLE = make( "turtle" );
|
||||||
|
public static final Tag.Named<Block> WIRED_MODEM = make( "wired_modem" );
|
||||||
|
public static final Tag.Named<Block> MONITOR = make( "monitor" );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blocks which can be broken by any turtle tool.
|
||||||
|
*/
|
||||||
|
public static final Tag.Named<Block> TURTLE_ALWAYS_BREAKABLE = make( "turtle_always_breakable" );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blocks which can be broken by the default shovel tool.
|
||||||
|
*/
|
||||||
|
public static final Tag.Named<Block> TURTLE_SHOVEL_BREAKABLE = make( "turtle_shovel_harvestable" );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blocks which can be broken with the default sword tool.
|
||||||
|
*/
|
||||||
|
public static final Tag.Named<Block> TURTLE_SWORD_BREAKABLE = make( "turtle_sword_harvestable" );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blocks which can be broken with the default hoe tool.
|
||||||
|
*/
|
||||||
|
public static final Tag.Named<Block> TURTLE_HOE_BREAKABLE = make( "turtle_hoe_harvestable" );
|
||||||
|
|
||||||
|
private static Tag.Named<Block> make( String name )
|
||||||
|
{
|
||||||
|
return TagFactory.BLOCK.create( new ResourceLocation( ComputerCraft.MOD_ID, name ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,83 +1,81 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||||
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
|
||||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.api.client;
|
package dan200.computercraft.api.client;
|
||||||
|
|
||||||
import java.util.Objects;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import com.mojang.math.Transformation;
|
||||||
import javax.annotation.Nonnull;
|
import com.mojang.math.Vector3f;
|
||||||
|
|
||||||
import dan200.computercraft.fabric.mixin.AffineTransformationAccess;
|
|
||||||
|
|
||||||
import net.minecraft.client.MinecraftClient;
|
|
||||||
import net.minecraft.client.render.model.BakedModel;
|
|
||||||
import net.minecraft.client.render.model.BakedModelManager;
|
|
||||||
import net.minecraft.client.util.ModelIdentifier;
|
|
||||||
import net.minecraft.client.util.math.AffineTransformation;
|
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
|
||||||
import net.minecraft.item.ItemStack;
|
|
||||||
|
|
||||||
import net.fabricmc.api.EnvType;
|
import net.fabricmc.api.EnvType;
|
||||||
import net.fabricmc.api.Environment;
|
import net.fabricmc.api.Environment;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.resources.model.BakedModel;
|
||||||
|
import net.minecraft.client.resources.model.ModelManager;
|
||||||
|
import net.minecraft.client.resources.model.ModelResourceLocation;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A model to render, combined with a transformation matrix to apply.
|
* A model to render, combined with a transformation matrix to apply.
|
||||||
*/
|
*/
|
||||||
@Environment (EnvType.CLIENT)
|
@Environment( EnvType.CLIENT )
|
||||||
public final class TransformedModel {
|
public final class TransformedModel
|
||||||
|
{
|
||||||
private final BakedModel model;
|
private final BakedModel model;
|
||||||
private final AffineTransformation matrix;
|
private final Transformation matrix;
|
||||||
|
|
||||||
public TransformedModel(@Nonnull BakedModel model, @Nonnull AffineTransformation matrix) {
|
public TransformedModel( @Nonnull BakedModel model, @Nonnull Transformation matrix )
|
||||||
this.model = Objects.requireNonNull(model);
|
{
|
||||||
this.matrix = Objects.requireNonNull(matrix);
|
this.model = Objects.requireNonNull( model );
|
||||||
|
this.matrix = Objects.requireNonNull( matrix );
|
||||||
}
|
}
|
||||||
|
|
||||||
public TransformedModel(@Nonnull BakedModel model) {
|
public TransformedModel( @Nonnull BakedModel model )
|
||||||
this.model = Objects.requireNonNull(model);
|
{
|
||||||
this.matrix = AffineTransformation.identity();
|
this.model = Objects.requireNonNull( model );
|
||||||
|
matrix = Transformation.identity();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TransformedModel of(@Nonnull ModelIdentifier location) {
|
public static TransformedModel of( @Nonnull ModelResourceLocation location )
|
||||||
BakedModelManager modelManager = MinecraftClient.getInstance()
|
{
|
||||||
.getBakedModelManager();
|
ModelManager modelManager = Minecraft.getInstance().getModelManager();
|
||||||
return new TransformedModel(modelManager.getModel(location));
|
return new TransformedModel( modelManager.getModel( location ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TransformedModel of(@Nonnull ItemStack item, @Nonnull AffineTransformation transform) {
|
public static TransformedModel of( @Nonnull ItemStack item, @Nonnull Transformation transform )
|
||||||
BakedModel model = MinecraftClient.getInstance()
|
{
|
||||||
.getItemRenderer()
|
BakedModel model = Minecraft.getInstance().getItemRenderer().getItemModelShaper().getItemModel( item );
|
||||||
.getModels()
|
return new TransformedModel( model, transform );
|
||||||
.getModel(item);
|
|
||||||
return new TransformedModel(model, transform);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public BakedModel getModel() {
|
public BakedModel getModel()
|
||||||
return this.model;
|
{
|
||||||
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public AffineTransformation getMatrix() {
|
public Transformation getMatrix()
|
||||||
return this.matrix;
|
{
|
||||||
|
return matrix;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void push(MatrixStack matrixStack) {
|
public void push( PoseStack matrixStack )
|
||||||
matrixStack.push();
|
{
|
||||||
|
matrixStack.pushPose();
|
||||||
|
|
||||||
AffineTransformationAccess access = (AffineTransformationAccess) (Object) this.matrix;
|
Vector3f translation = matrix.getTranslation();
|
||||||
if (access.getTranslation() != null)
|
matrixStack.translate( translation.x(), translation.y(), translation.z() );
|
||||||
matrixStack.translate(access.getTranslation().getX(), access.getTranslation().getY(), access.getTranslation().getZ());
|
|
||||||
|
|
||||||
matrixStack.multiply(this.matrix.getRotation2());
|
matrixStack.mulPose( matrix.getLeftRotation() );
|
||||||
|
|
||||||
if (access.getScale() != null)
|
Vector3f scale = matrix.getScale();
|
||||||
matrixStack.scale(access.getScale().getX(), access.getScale().getY(), access.getScale().getZ());
|
matrixStack.scale( scale.x(), scale.y(), scale.z() );
|
||||||
|
|
||||||
if (access.getRotation1() != null)
|
matrixStack.mulPose( matrix.getRightRotation() );
|
||||||
matrixStack.multiply(access.getRotation1());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,9 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||||
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
|
||||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.api.filesystem;
|
package dan200.computercraft.api.filesystem;
|
||||||
|
|
||||||
import java.nio.file.attribute.BasicFileAttributes;
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
@@ -13,59 +12,70 @@ import java.time.Instant;
|
|||||||
/**
|
/**
|
||||||
* A simple version of {@link BasicFileAttributes}, which provides what information a {@link IMount} already exposes.
|
* A simple version of {@link BasicFileAttributes}, which provides what information a {@link IMount} already exposes.
|
||||||
*/
|
*/
|
||||||
final class FileAttributes implements BasicFileAttributes {
|
final class FileAttributes implements BasicFileAttributes
|
||||||
private static final FileTime EPOCH = FileTime.from(Instant.EPOCH);
|
{
|
||||||
|
private static final FileTime EPOCH = FileTime.from( Instant.EPOCH );
|
||||||
|
|
||||||
private final boolean isDirectory;
|
private final boolean isDirectory;
|
||||||
private final long size;
|
private final long size;
|
||||||
|
|
||||||
FileAttributes(boolean isDirectory, long size) {
|
FileAttributes( boolean isDirectory, long size )
|
||||||
|
{
|
||||||
this.isDirectory = isDirectory;
|
this.isDirectory = isDirectory;
|
||||||
this.size = size;
|
this.size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FileTime lastModifiedTime() {
|
public FileTime lastModifiedTime()
|
||||||
|
{
|
||||||
return EPOCH;
|
return EPOCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FileTime lastAccessTime() {
|
public FileTime lastAccessTime()
|
||||||
|
{
|
||||||
return EPOCH;
|
return EPOCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FileTime creationTime() {
|
public FileTime creationTime()
|
||||||
|
{
|
||||||
return EPOCH;
|
return EPOCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isRegularFile() {
|
public boolean isRegularFile()
|
||||||
return !this.isDirectory;
|
{
|
||||||
|
return !isDirectory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isDirectory() {
|
public boolean isDirectory()
|
||||||
return this.isDirectory;
|
{
|
||||||
|
return isDirectory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSymbolicLink() {
|
public boolean isSymbolicLink()
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isOther() {
|
public boolean isOther()
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long size() {
|
public long size()
|
||||||
return this.size;
|
{
|
||||||
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object fileKey() {
|
public Object fileKey()
|
||||||
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,39 +1,41 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||||
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
|
||||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.api.filesystem;
|
package dan200.computercraft.api.filesystem;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An {@link IOException} which occurred on a specific file.
|
* An {@link IOException} which occurred on a specific file.
|
||||||
*
|
*
|
||||||
* This may be thrown from a {@link IMount} or {@link IWritableMount} to give more information about a failure.
|
* This may be thrown from a {@link IMount} or {@link IWritableMount} to give more information about a failure.
|
||||||
*/
|
*/
|
||||||
public class FileOperationException extends IOException {
|
public class FileOperationException extends IOException
|
||||||
|
{
|
||||||
private static final long serialVersionUID = -8809108200853029849L;
|
private static final long serialVersionUID = -8809108200853029849L;
|
||||||
|
|
||||||
private final String filename;
|
private final String filename;
|
||||||
|
|
||||||
public FileOperationException(@Nullable String filename, @Nonnull String message) {
|
public FileOperationException( @Nullable String filename, @Nonnull String message )
|
||||||
super(Objects.requireNonNull(message, "message cannot be null"));
|
{
|
||||||
|
super( Objects.requireNonNull( message, "message cannot be null" ) );
|
||||||
this.filename = filename;
|
this.filename = filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
public FileOperationException(@Nonnull String message) {
|
public FileOperationException( @Nonnull String message )
|
||||||
super(Objects.requireNonNull(message, "message cannot be null"));
|
{
|
||||||
this.filename = null;
|
super( Objects.requireNonNull( message, "message cannot be null" ) );
|
||||||
|
filename = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public String getFilename() {
|
public String getFilename()
|
||||||
return this.filename;
|
{
|
||||||
|
return filename;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,9 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||||
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
|
||||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.api.filesystem;
|
package dan200.computercraft.api.filesystem;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -13,31 +12,32 @@ import java.io.IOException;
|
|||||||
*
|
*
|
||||||
* This exists for use by various APIs - one should not attempt to mount it.
|
* This exists for use by various APIs - one should not attempt to mount it.
|
||||||
*/
|
*/
|
||||||
public interface IFileSystem extends IWritableMount {
|
public interface IFileSystem extends IWritableMount
|
||||||
|
{
|
||||||
/**
|
/**
|
||||||
* Combine two paths together, reducing them into a normalised form.
|
* Combine two paths together, reducing them into a normalised form.
|
||||||
*
|
*
|
||||||
* @param path The main path.
|
* @param path The main path.
|
||||||
* @param child The path to append.
|
* @param child The path to append.
|
||||||
* @return The combined, normalised path.
|
* @return The combined, normalised path.
|
||||||
*/
|
*/
|
||||||
String combine(String path, String child);
|
String combine( String path, String child );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copy files from one location to another.
|
* Copy files from one location to another.
|
||||||
*
|
*
|
||||||
* @param from The location to copy from.
|
* @param from The location to copy from.
|
||||||
* @param to The location to copy to. This should not exist.
|
* @param to The location to copy to. This should not exist.
|
||||||
* @throws IOException If the copy failed.
|
* @throws IOException If the copy failed.
|
||||||
*/
|
*/
|
||||||
void copy(String from, String to) throws IOException;
|
void copy( String from, String to ) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move files from one location to another.
|
* Move files from one location to another.
|
||||||
*
|
*
|
||||||
* @param from The location to move from.
|
* @param from The location to move from.
|
||||||
* @param to The location to move to. This should not exist.
|
* @param to The location to move to. This should not exist.
|
||||||
* @throws IOException If the move failed.
|
* @throws IOException If the move failed.
|
||||||
*/
|
*/
|
||||||
void move(String from, String to) throws IOException;
|
void move( String from, String to ) throws IOException;
|
||||||
}
|
}
|
||||||
|
@@ -1,54 +1,82 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||||
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
|
||||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.api.filesystem;
|
package dan200.computercraft.api.filesystem;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.ComputerCraftAPI;
|
||||||
|
import dan200.computercraft.api.peripheral.IComputerAccess;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.channels.ReadableByteChannel;
|
import java.nio.channels.ReadableByteChannel;
|
||||||
import java.nio.file.attribute.BasicFileAttributes;
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
|
|
||||||
import dan200.computercraft.api.ComputerCraftAPI;
|
|
||||||
import dan200.computercraft.api.peripheral.IComputerAccess;
|
|
||||||
|
|
||||||
import net.minecraft.world.World;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a read only part of a virtual filesystem that can be mounted onto a computer using {@link IComputerAccess#mount(String, IMount)}.
|
* Represents a read only part of a virtual filesystem that can be mounted onto a computer using
|
||||||
|
* {@link IComputerAccess#mount(String, IMount)}.
|
||||||
*
|
*
|
||||||
* Ready made implementations of this interface can be created using {@link ComputerCraftAPI#createSaveDirMount(World, String, long)} or {@link
|
* Ready made implementations of this interface can be created using
|
||||||
* ComputerCraftAPI#createResourceMount(String, String)}, or you're free to implement it yourselves!
|
* {@link ComputerCraftAPI#createSaveDirMount(Level, String, long)} or
|
||||||
|
* {@link ComputerCraftAPI#createResourceMount(String, String)}, or you're free to implement it yourselves!
|
||||||
*
|
*
|
||||||
* @see ComputerCraftAPI#createSaveDirMount(World, String, long)
|
* @see ComputerCraftAPI#createSaveDirMount(Level, String, long)
|
||||||
* @see ComputerCraftAPI#createResourceMount(String, String)
|
* @see ComputerCraftAPI#createResourceMount(String, String)
|
||||||
* @see IComputerAccess#mount(String, IMount)
|
* @see IComputerAccess#mount(String, IMount)
|
||||||
* @see IWritableMount
|
* @see IWritableMount
|
||||||
*/
|
*/
|
||||||
public interface IMount {
|
public interface IMount
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns whether a file with a given path exists or not.
|
||||||
|
*
|
||||||
|
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram"
|
||||||
|
* @return If the file exists.
|
||||||
|
* @throws IOException If an error occurs when checking the existence of the file.
|
||||||
|
*/
|
||||||
|
boolean exists( @Nonnull String path ) throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether a file with a given path is a directory or not.
|
||||||
|
*
|
||||||
|
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myprograms".
|
||||||
|
* @return If the file exists and is a directory
|
||||||
|
* @throws IOException If an error occurs when checking whether the file is a directory.
|
||||||
|
*/
|
||||||
|
boolean isDirectory( @Nonnull String path ) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the file names of all the files in a directory.
|
* Returns the file names of all the files in a directory.
|
||||||
*
|
*
|
||||||
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myprograms".
|
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myprograms".
|
||||||
* @param contents A list of strings. Add all the file names to this list.
|
* @param contents A list of strings. Add all the file names to this list.
|
||||||
* @throws IOException If the file was not a directory, or could not be listed.
|
* @throws IOException If the file was not a directory, or could not be listed.
|
||||||
*/
|
*/
|
||||||
void list(@Nonnull String path, @Nonnull List<String> contents) throws IOException;
|
void list( @Nonnull String path, @Nonnull List<String> contents ) throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the size of a file with a given path, in bytes.
|
||||||
|
*
|
||||||
|
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram".
|
||||||
|
* @return The size of the file, in bytes.
|
||||||
|
* @throws IOException If the file does not exist, or its size could not be determined.
|
||||||
|
*/
|
||||||
|
long getSize( @Nonnull String path ) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens a file with a given path, and returns an {@link ReadableByteChannel} representing its contents.
|
* Opens a file with a given path, and returns an {@link ReadableByteChannel} representing its contents.
|
||||||
*
|
*
|
||||||
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram".
|
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram".
|
||||||
* @return A channel representing the contents of the file. If the channel implements {@link java.nio.channels.SeekableByteChannel}, one will be able to
|
* @return A channel representing the contents of the file. If the channel implements
|
||||||
* seek to arbitrary positions when using binary mode.
|
* {@link java.nio.channels.SeekableByteChannel}, one will be able to seek to arbitrary positions when using binary
|
||||||
|
* mode.
|
||||||
* @throws IOException If the file does not exist, or could not be opened.
|
* @throws IOException If the file does not exist, or could not be opened.
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
ReadableByteChannel openForRead(@Nonnull String path) throws IOException;
|
ReadableByteChannel openForRead( @Nonnull String path ) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get attributes about the given file.
|
* Get attributes about the given file.
|
||||||
@@ -58,37 +86,9 @@ public interface IMount {
|
|||||||
* @throws IOException If the file does not exist, or attributes could not be fetched.
|
* @throws IOException If the file does not exist, or attributes could not be fetched.
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
default BasicFileAttributes getAttributes(@Nonnull String path) throws IOException {
|
default BasicFileAttributes getAttributes( @Nonnull String path ) throws IOException
|
||||||
if (!this.exists(path)) {
|
{
|
||||||
throw new FileOperationException(path, "No such file");
|
if( !exists( path ) ) throw new FileOperationException( path, "No such file" );
|
||||||
}
|
return new FileAttributes( isDirectory( path ), getSize( path ) );
|
||||||
return new FileAttributes(this.isDirectory(path), this.getSize(path));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether a file with a given path exists or not.
|
|
||||||
*
|
|
||||||
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram"
|
|
||||||
* @return If the file exists.
|
|
||||||
* @throws IOException If an error occurs when checking the existence of the file.
|
|
||||||
*/
|
|
||||||
boolean exists(@Nonnull String path) throws IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether a file with a given path is a directory or not.
|
|
||||||
*
|
|
||||||
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myprograms".
|
|
||||||
* @return If the file exists and is a directory
|
|
||||||
* @throws IOException If an error occurs when checking whether the file is a directory.
|
|
||||||
*/
|
|
||||||
boolean isDirectory(@Nonnull String path) throws IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the size of a file with a given path, in bytes.
|
|
||||||
*
|
|
||||||
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram".
|
|
||||||
* @return The size of the file, in bytes.
|
|
||||||
* @throws IOException If the file does not exist, or its size could not be determined.
|
|
||||||
*/
|
|
||||||
long getSize(@Nonnull String path) throws IOException;
|
|
||||||
}
|
}
|
||||||
|
@@ -1,43 +1,41 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||||
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
|
||||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.api.filesystem;
|
package dan200.computercraft.api.filesystem;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.ComputerCraftAPI;
|
||||||
|
import dan200.computercraft.api.peripheral.IComputerAccess;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.nio.channels.WritableByteChannel;
|
import java.nio.channels.WritableByteChannel;
|
||||||
import java.util.OptionalLong;
|
import java.util.OptionalLong;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
|
|
||||||
import dan200.computercraft.api.ComputerCraftAPI;
|
|
||||||
import dan200.computercraft.api.peripheral.IComputerAccess;
|
|
||||||
|
|
||||||
import net.minecraft.world.World;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a part of a virtual filesystem that can be mounted onto a computer using {@link IComputerAccess#mount(String, IMount)} or {@link
|
* Represents a part of a virtual filesystem that can be mounted onto a computer using {@link IComputerAccess#mount(String, IMount)}
|
||||||
* IComputerAccess#mountWritable(String, IWritableMount)}, that can also be written to.
|
* or {@link IComputerAccess#mountWritable(String, IWritableMount)}, that can also be written to.
|
||||||
*
|
*
|
||||||
* Ready made implementations of this interface can be created using {@link ComputerCraftAPI#createSaveDirMount(World, String, long)}, or you're free to
|
* Ready made implementations of this interface can be created using
|
||||||
* implement it yourselves!
|
* {@link ComputerCraftAPI#createSaveDirMount(Level, String, long)}, or you're free to implement it yourselves!
|
||||||
*
|
*
|
||||||
* @see ComputerCraftAPI#createSaveDirMount(World, String, long)
|
* @see ComputerCraftAPI#createSaveDirMount(Level, String, long)
|
||||||
* @see IComputerAccess#mount(String, IMount)
|
* @see IComputerAccess#mount(String, IMount)
|
||||||
* @see IComputerAccess#mountWritable(String, IWritableMount)
|
* @see IComputerAccess#mountWritable(String, IWritableMount)
|
||||||
* @see IMount
|
* @see IMount
|
||||||
*/
|
*/
|
||||||
public interface IWritableMount extends IMount {
|
public interface IWritableMount extends IMount
|
||||||
|
{
|
||||||
/**
|
/**
|
||||||
* Creates a directory at a given path inside the virtual file system.
|
* Creates a directory at a given path inside the virtual file system.
|
||||||
*
|
*
|
||||||
* @param path A file path in normalised format, relative to the mount location. ie: "programs/mynewprograms".
|
* @param path A file path in normalised format, relative to the mount location. ie: "programs/mynewprograms".
|
||||||
* @throws IOException If the directory already exists or could not be created.
|
* @throws IOException If the directory already exists or could not be created.
|
||||||
*/
|
*/
|
||||||
void makeDirectory(@Nonnull String path) throws IOException;
|
void makeDirectory( @Nonnull String path ) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes a directory at a given path inside the virtual file system.
|
* Deletes a directory at a given path inside the virtual file system.
|
||||||
@@ -45,33 +43,33 @@ public interface IWritableMount extends IMount {
|
|||||||
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myoldprograms".
|
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myoldprograms".
|
||||||
* @throws IOException If the file does not exist or could not be deleted.
|
* @throws IOException If the file does not exist or could not be deleted.
|
||||||
*/
|
*/
|
||||||
void delete(@Nonnull String path) throws IOException;
|
void delete( @Nonnull String path ) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens a file with a given path, and returns an {@link OutputStream} for writing to it.
|
* Opens a file with a given path, and returns an {@link OutputStream} for writing to it.
|
||||||
*
|
*
|
||||||
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram".
|
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram".
|
||||||
* @return A stream for writing to. If the channel implements {@link java.nio.channels.SeekableByteChannel}, one will be able to seek to arbitrary
|
* @return A stream for writing to. If the channel implements {@link java.nio.channels.SeekableByteChannel}, one
|
||||||
* positions when using binary mode.
|
* will be able to seek to arbitrary positions when using binary mode.
|
||||||
* @throws IOException If the file could not be opened for writing.
|
* @throws IOException If the file could not be opened for writing.
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
WritableByteChannel openForWrite(@Nonnull String path) throws IOException;
|
WritableByteChannel openForWrite( @Nonnull String path ) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens a file with a given path, and returns an {@link OutputStream} for appending to it.
|
* Opens a file with a given path, and returns an {@link OutputStream} for appending to it.
|
||||||
*
|
*
|
||||||
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram".
|
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram".
|
||||||
* @return A stream for writing to. If the channel implements {@link java.nio.channels.SeekableByteChannel}, one will be able to seek to arbitrary
|
* @return A stream for writing to. If the channel implements {@link java.nio.channels.SeekableByteChannel}, one
|
||||||
* positions when using binary mode.
|
* will be able to seek to arbitrary positions when using binary mode.
|
||||||
* @throws IOException If the file could not be opened for writing.
|
* @throws IOException If the file could not be opened for writing.
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
WritableByteChannel openForAppend(@Nonnull String path) throws IOException;
|
WritableByteChannel openForAppend( @Nonnull String path ) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the amount of free space on the mount, in bytes. You should decrease this value as the user writes to the mount, and write operations should fail
|
* Get the amount of free space on the mount, in bytes. You should decrease this value as the user writes to the
|
||||||
* once it reaches zero.
|
* mount, and write operations should fail once it reaches zero.
|
||||||
*
|
*
|
||||||
* @return The amount of free space, in bytes.
|
* @return The amount of free space, in bytes.
|
||||||
* @throws IOException If the remaining space could not be computed.
|
* @throws IOException If the remaining space could not be computed.
|
||||||
@@ -79,12 +77,14 @@ public interface IWritableMount extends IMount {
|
|||||||
long getRemainingSpace() throws IOException;
|
long getRemainingSpace() throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the capacity of this mount. This should be equal to the size of all files/directories on this mount, minus the {@link #getRemainingSpace()}.
|
* Get the capacity of this mount. This should be equal to the size of all files/directories on this mount, minus
|
||||||
|
* the {@link #getRemainingSpace()}.
|
||||||
*
|
*
|
||||||
* @return The capacity of this mount, in bytes.
|
* @return The capacity of this mount, in bytes.
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
default OptionalLong getCapacity() {
|
default OptionalLong getCapacity()
|
||||||
|
{
|
||||||
return OptionalLong.empty();
|
return OptionalLong.empty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||||
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
|
||||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||||
*/
|
*/
|
||||||
package dan200.computercraft.api.lua;
|
package dan200.computercraft.api.lua;
|
||||||
@@ -9,7 +9,8 @@ import dan200.computercraft.api.ComputerCraftAPI;
|
|||||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||||
import dan200.computercraft.api.peripheral.IPeripheralProvider;
|
import dan200.computercraft.api.peripheral.IPeripheralProvider;
|
||||||
import dan200.computercraft.core.asm.LuaMethod;
|
import dan200.computercraft.core.asm.LuaMethod;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.world.Container;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
@@ -18,20 +19,19 @@ import javax.annotation.Nonnull;
|
|||||||
*
|
*
|
||||||
* Unlike normal objects ({@link IDynamicLuaObject} or {@link IPeripheral}), methods do not target this object but
|
* Unlike normal objects ({@link IDynamicLuaObject} or {@link IPeripheral}), methods do not target this object but
|
||||||
* instead are defined as {@code static} and accept their target as the first parameter. This allows you to inject
|
* instead are defined as {@code static} and accept their target as the first parameter. This allows you to inject
|
||||||
* methods onto objects you do not own, as well as declaring methods for a specific "trait" (for instance, a
|
* methods onto objects you do not own, as well as declaring methods for a specific "trait" (well, interface).
|
||||||
* {@link Capability}).
|
|
||||||
*
|
*
|
||||||
* Currently the "generic peripheral" system is incompatible with normal peripherals. Normal {@link IPeripheralProvider}
|
* Currently the "generic peripheral" system is incompatible with normal peripherals. Normal {@link IPeripheralProvider}
|
||||||
* or {@link IPeripheral} implementations take priority. Tile entities which use this system are given a peripheral name
|
* or {@link IPeripheral} implementations take priority. Tile entities which use this system are given a peripheral name
|
||||||
* determined by their id, rather than any peripheral provider. This will hopefully change in the future, once a suitable
|
* determined by their id, rather than any peripheral provider. This will hopefully change in the future, once a suitable
|
||||||
* design has been established.
|
* design has been established.
|
||||||
*
|
*
|
||||||
* For example, the main CC: Tweaked mod defines a generic source for inventories, which works on {@link IItemHandler}s:
|
* For example, the main CC: Tweaked mod defines a generic source for inventories, which works on {@link Container}s:
|
||||||
*
|
*
|
||||||
* <pre>{@code
|
* <pre>{@code
|
||||||
* public class InventoryMethods implements GenericSource {
|
* public class InventoryMethods implements GenericSource {
|
||||||
* \@LuaFunction( mainThread = true )
|
* \@LuaFunction( mainThread = true )
|
||||||
* public static int size(IItemHandler inventory) {
|
* public static int size(Container inventory) {
|
||||||
* return inventory.getSlots();
|
* return inventory.getSlots();
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
@@ -40,8 +40,6 @@ import javax.annotation.Nonnull;
|
|||||||
* }</pre>
|
* }</pre>
|
||||||
*
|
*
|
||||||
* @see ComputerCraftAPI#registerGenericSource(GenericSource)
|
* @see ComputerCraftAPI#registerGenericSource(GenericSource)
|
||||||
* @see ComputerCraftAPI#registerGenericCapability(Capability) New capabilities (those not built into Forge) must be
|
|
||||||
* explicitly given to the generic peripheral system, as there is no way to enumerate all capabilities.
|
|
||||||
*/
|
*/
|
||||||
public interface GenericSource
|
public interface GenericSource
|
||||||
{
|
{
|
||||||
@@ -54,5 +52,5 @@ public interface GenericSource
|
|||||||
* @return This source's identifier.
|
* @return This source's identifier.
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
Identifier id();
|
ResourceLocation id();
|
||||||
}
|
}
|
||||||
|
@@ -1,41 +1,23 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||||
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
|
||||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.api.lua;
|
package dan200.computercraft.api.lua;
|
||||||
|
|
||||||
import static dan200.computercraft.api.lua.LuaValues.checkFinite;
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import static dan200.computercraft.api.lua.LuaValues.checkFinite;
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The arguments passed to a function.
|
* The arguments passed to a function.
|
||||||
*/
|
*/
|
||||||
public interface IArguments {
|
public interface IArguments
|
||||||
/**
|
{
|
||||||
* Drop a number of arguments. The returned arguments instance will access arguments at position {@code i + count}, rather than {@code i}. However,
|
|
||||||
* errors will still use the given argument index.
|
|
||||||
*
|
|
||||||
* @param count The number of arguments to drop.
|
|
||||||
* @return The new {@link IArguments} instance.
|
|
||||||
*/
|
|
||||||
IArguments drop(int count);
|
|
||||||
|
|
||||||
default Object[] getAll() {
|
|
||||||
Object[] result = new Object[this.count()];
|
|
||||||
for (int i = 0; i < result.length; i++) {
|
|
||||||
result[i] = this.get(i);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the number of arguments passed to this function.
|
* Get the number of arguments passed to this function.
|
||||||
*
|
*
|
||||||
@@ -58,44 +40,22 @@ public interface IArguments {
|
|||||||
* @return The argument's value, or {@code null} if not present.
|
* @return The argument's value, or {@code null} if not present.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
Object get(int index);
|
Object get( int index );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an argument as an integer.
|
* Drop a number of arguments. The returned arguments instance will access arguments at position {@code i + count},
|
||||||
|
* rather than {@code i}. However, errors will still use the given argument index.
|
||||||
*
|
*
|
||||||
* @param index The argument number.
|
* @param count The number of arguments to drop.
|
||||||
* @return The argument's value.
|
* @return The new {@link IArguments} instance.
|
||||||
* @throws LuaException If the value is not an integer.
|
|
||||||
*/
|
*/
|
||||||
default int getInt(int index) throws LuaException {
|
IArguments drop( int count );
|
||||||
return (int) this.getLong(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
default Object[] getAll()
|
||||||
* Get an argument as a long.
|
{
|
||||||
*
|
Object[] result = new Object[count()];
|
||||||
* @param index The argument number.
|
for( int i = 0; i < result.length; i++ ) result[i] = get( i );
|
||||||
* @return The argument's value.
|
return result;
|
||||||
* @throws LuaException If the value is not a long.
|
|
||||||
*/
|
|
||||||
default long getLong(int index) throws LuaException {
|
|
||||||
Object value = this.get(index);
|
|
||||||
if (!(value instanceof Number)) {
|
|
||||||
throw LuaValues.badArgumentOf(index, "number", value);
|
|
||||||
}
|
|
||||||
return LuaValues.checkFiniteNum(index, (Number) value)
|
|
||||||
.longValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an argument as a finite number (not infinite or NaN).
|
|
||||||
*
|
|
||||||
* @param index The argument number.
|
|
||||||
* @return The argument's value.
|
|
||||||
* @throws LuaException If the value is not finite.
|
|
||||||
*/
|
|
||||||
default double getFiniteDouble(int index) throws LuaException {
|
|
||||||
return checkFinite(index, this.getDouble(index));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -106,14 +66,51 @@ public interface IArguments {
|
|||||||
* @throws LuaException If the value is not a number.
|
* @throws LuaException If the value is not a number.
|
||||||
* @see #getFiniteDouble(int) if you require this to be finite (i.e. not infinite or NaN).
|
* @see #getFiniteDouble(int) if you require this to be finite (i.e. not infinite or NaN).
|
||||||
*/
|
*/
|
||||||
default double getDouble(int index) throws LuaException {
|
default double getDouble( int index ) throws LuaException
|
||||||
Object value = this.get(index);
|
{
|
||||||
if (!(value instanceof Number)) {
|
Object value = get( index );
|
||||||
throw LuaValues.badArgumentOf(index, "number", value);
|
if( !(value instanceof Number) ) throw LuaValues.badArgumentOf( index, "number", value );
|
||||||
}
|
|
||||||
return ((Number) value).doubleValue();
|
return ((Number) value).doubleValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an argument as an integer.
|
||||||
|
*
|
||||||
|
* @param index The argument number.
|
||||||
|
* @return The argument's value.
|
||||||
|
* @throws LuaException If the value is not an integer.
|
||||||
|
*/
|
||||||
|
default int getInt( int index ) throws LuaException
|
||||||
|
{
|
||||||
|
return (int) getLong( index );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an argument as a long.
|
||||||
|
*
|
||||||
|
* @param index The argument number.
|
||||||
|
* @return The argument's value.
|
||||||
|
* @throws LuaException If the value is not a long.
|
||||||
|
*/
|
||||||
|
default long getLong( int index ) throws LuaException
|
||||||
|
{
|
||||||
|
Object value = get( index );
|
||||||
|
if( !(value instanceof Number) ) throw LuaValues.badArgumentOf( index, "number", value );
|
||||||
|
return LuaValues.checkFiniteNum( index, (Number) value ).longValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an argument as a finite number (not infinite or NaN).
|
||||||
|
*
|
||||||
|
* @param index The argument number.
|
||||||
|
* @return The argument's value.
|
||||||
|
* @throws LuaException If the value is not finite.
|
||||||
|
*/
|
||||||
|
default double getFiniteDouble( int index ) throws LuaException
|
||||||
|
{
|
||||||
|
return checkFinite( index, getDouble( index ) );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an argument as a boolean.
|
* Get an argument as a boolean.
|
||||||
*
|
*
|
||||||
@@ -121,14 +118,28 @@ public interface IArguments {
|
|||||||
* @return The argument's value.
|
* @return The argument's value.
|
||||||
* @throws LuaException If the value is not a boolean.
|
* @throws LuaException If the value is not a boolean.
|
||||||
*/
|
*/
|
||||||
default boolean getBoolean(int index) throws LuaException {
|
default boolean getBoolean( int index ) throws LuaException
|
||||||
Object value = this.get(index);
|
{
|
||||||
if (!(value instanceof Boolean)) {
|
Object value = get( index );
|
||||||
throw LuaValues.badArgumentOf(index, "boolean", value);
|
if( !(value instanceof Boolean) ) throw LuaValues.badArgumentOf( index, "boolean", value );
|
||||||
}
|
|
||||||
return (Boolean) value;
|
return (Boolean) value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an argument as a string.
|
||||||
|
*
|
||||||
|
* @param index The argument number.
|
||||||
|
* @return The argument's value.
|
||||||
|
* @throws LuaException If the value is not a string.
|
||||||
|
*/
|
||||||
|
@Nonnull
|
||||||
|
default String getString( int index ) throws LuaException
|
||||||
|
{
|
||||||
|
Object value = get( index );
|
||||||
|
if( !(value instanceof String) ) throw LuaValues.badArgumentOf( index, "string", value );
|
||||||
|
return (String) value;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a string argument as a byte array.
|
* Get a string argument as a byte array.
|
||||||
*
|
*
|
||||||
@@ -137,24 +148,9 @@ public interface IArguments {
|
|||||||
* @throws LuaException If the value is not a string.
|
* @throws LuaException If the value is not a string.
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
default ByteBuffer getBytes(int index) throws LuaException {
|
default ByteBuffer getBytes( int index ) throws LuaException
|
||||||
return LuaValues.encode(this.getString(index));
|
{
|
||||||
}
|
return LuaValues.encode( getString( index ) );
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an argument as a string.
|
|
||||||
*
|
|
||||||
* @param index The argument number.
|
|
||||||
* @return The argument's value.
|
|
||||||
* @throws LuaException If the value is not a string.
|
|
||||||
*/
|
|
||||||
@Nonnull
|
|
||||||
default String getString(int index) throws LuaException {
|
|
||||||
Object value = this.get(index);
|
|
||||||
if (!(value instanceof String)) {
|
|
||||||
throw LuaValues.badArgumentOf(index, "string", value);
|
|
||||||
}
|
|
||||||
return (String) value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -162,13 +158,14 @@ public interface IArguments {
|
|||||||
*
|
*
|
||||||
* @param index The argument number.
|
* @param index The argument number.
|
||||||
* @param klass The type of enum to parse.
|
* @param klass The type of enum to parse.
|
||||||
* @param <T> The type of enum to parse.
|
* @param <T> The type of enum to parse.
|
||||||
* @return The argument's value.
|
* @return The argument's value.
|
||||||
* @throws LuaException If the value is not a string or not a valid option for this enum.
|
* @throws LuaException If the value is not a string or not a valid option for this enum.
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
default <T extends Enum<T>> T getEnum(int index, Class<T> klass) throws LuaException {
|
default <T extends Enum<T>> T getEnum( int index, Class<T> klass ) throws LuaException
|
||||||
return LuaValues.checkEnum(index, klass, this.getString(index));
|
{
|
||||||
|
return LuaValues.checkEnum( index, klass, getString( index ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -179,14 +176,119 @@ public interface IArguments {
|
|||||||
* @throws LuaException If the value is not a table.
|
* @throws LuaException If the value is not a table.
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
default Map<?, ?> getTable(int index) throws LuaException {
|
default Map<?, ?> getTable( int index ) throws LuaException
|
||||||
Object value = this.get(index);
|
{
|
||||||
if (!(value instanceof Map)) {
|
Object value = get( index );
|
||||||
throw LuaValues.badArgumentOf(index, "table", value);
|
if( !(value instanceof Map) ) throw LuaValues.badArgumentOf( index, "table", value );
|
||||||
}
|
|
||||||
return (Map<?, ?>) value;
|
return (Map<?, ?>) value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an argument as a table in an unsafe manner.
|
||||||
|
*
|
||||||
|
* Classes implementing this interface may choose to implement a more optimised version which does not copy the
|
||||||
|
* table, instead returning a wrapper version, making it more efficient. However, the caller must guarantee that
|
||||||
|
* they do not access off the computer thread (and so should not be used with main-thread functions) or once the
|
||||||
|
* function call has finished (for instance, in callbacks).
|
||||||
|
*
|
||||||
|
* @param index The argument number.
|
||||||
|
* @return The argument's value.
|
||||||
|
* @throws LuaException If the value is not a table.
|
||||||
|
*/
|
||||||
|
@Nonnull
|
||||||
|
default LuaTable<?, ?> getTableUnsafe( int index ) throws LuaException
|
||||||
|
{
|
||||||
|
return new ObjectLuaTable( getTable( index ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an argument as a double.
|
||||||
|
*
|
||||||
|
* @param index The argument number.
|
||||||
|
* @return The argument's value, or {@link Optional#empty()} if not present.
|
||||||
|
* @throws LuaException If the value is not a number.
|
||||||
|
*/
|
||||||
|
@Nonnull
|
||||||
|
default Optional<Double> optDouble( int index ) throws LuaException
|
||||||
|
{
|
||||||
|
Object value = get( index );
|
||||||
|
if( value == null ) return Optional.empty();
|
||||||
|
if( !(value instanceof Number) ) throw LuaValues.badArgumentOf( index, "number", value );
|
||||||
|
return Optional.of( ((Number) value).doubleValue() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an argument as an int.
|
||||||
|
*
|
||||||
|
* @param index The argument number.
|
||||||
|
* @return The argument's value, or {@link Optional#empty()} if not present.
|
||||||
|
* @throws LuaException If the value is not a number.
|
||||||
|
*/
|
||||||
|
@Nonnull
|
||||||
|
default Optional<Integer> optInt( int index ) throws LuaException
|
||||||
|
{
|
||||||
|
return optLong( index ).map( Long::intValue );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an argument as a long.
|
||||||
|
*
|
||||||
|
* @param index The argument number.
|
||||||
|
* @return The argument's value, or {@link Optional#empty()} if not present.
|
||||||
|
* @throws LuaException If the value is not a number.
|
||||||
|
*/
|
||||||
|
default Optional<Long> optLong( int index ) throws LuaException
|
||||||
|
{
|
||||||
|
Object value = get( index );
|
||||||
|
if( value == null ) return Optional.empty();
|
||||||
|
if( !(value instanceof Number) ) throw LuaValues.badArgumentOf( index, "number", value );
|
||||||
|
return Optional.of( LuaValues.checkFiniteNum( index, (Number) value ).longValue() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an argument as a finite number (not infinite or NaN).
|
||||||
|
*
|
||||||
|
* @param index The argument number.
|
||||||
|
* @return The argument's value, or {@link Optional#empty()} if not present.
|
||||||
|
* @throws LuaException If the value is not finite.
|
||||||
|
*/
|
||||||
|
default Optional<Double> optFiniteDouble( int index ) throws LuaException
|
||||||
|
{
|
||||||
|
Optional<Double> value = optDouble( index );
|
||||||
|
if( value.isPresent() ) LuaValues.checkFiniteNum( index, value.get() );
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an argument as a boolean.
|
||||||
|
*
|
||||||
|
* @param index The argument number.
|
||||||
|
* @return The argument's value, or {@link Optional#empty()} if not present.
|
||||||
|
* @throws LuaException If the value is not a boolean.
|
||||||
|
*/
|
||||||
|
default Optional<Boolean> optBoolean( int index ) throws LuaException
|
||||||
|
{
|
||||||
|
Object value = get( index );
|
||||||
|
if( value == null ) return Optional.empty();
|
||||||
|
if( !(value instanceof Boolean) ) throw LuaValues.badArgumentOf( index, "boolean", value );
|
||||||
|
return Optional.of( (Boolean) value );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an argument as a string.
|
||||||
|
*
|
||||||
|
* @param index The argument number.
|
||||||
|
* @return The argument's value, or {@link Optional#empty()} if not present.
|
||||||
|
* @throws LuaException If the value is not a string.
|
||||||
|
*/
|
||||||
|
default Optional<String> optString( int index ) throws LuaException
|
||||||
|
{
|
||||||
|
Object value = get( index );
|
||||||
|
if( value == null ) return Optional.empty();
|
||||||
|
if( !(value instanceof String) ) throw LuaValues.badArgumentOf( index, "string", value );
|
||||||
|
return Optional.of( (String) value );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a string argument as a byte array.
|
* Get a string argument as a byte array.
|
||||||
*
|
*
|
||||||
@@ -194,26 +296,9 @@ public interface IArguments {
|
|||||||
* @return The argument's value, or {@link Optional#empty()} if not present. This is a <em>read only</em> buffer.
|
* @return The argument's value, or {@link Optional#empty()} if not present. This is a <em>read only</em> buffer.
|
||||||
* @throws LuaException If the value is not a string.
|
* @throws LuaException If the value is not a string.
|
||||||
*/
|
*/
|
||||||
default Optional<ByteBuffer> optBytes(int index) throws LuaException {
|
default Optional<ByteBuffer> optBytes( int index ) throws LuaException
|
||||||
return this.optString(index).map(LuaValues::encode);
|
{
|
||||||
}
|
return optString( index ).map( LuaValues::encode );
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an argument as a string.
|
|
||||||
*
|
|
||||||
* @param index The argument number.
|
|
||||||
* @return The argument's value, or {@link Optional#empty()} if not present.
|
|
||||||
* @throws LuaException If the value is not a string.
|
|
||||||
*/
|
|
||||||
default Optional<String> optString(int index) throws LuaException {
|
|
||||||
Object value = this.get(index);
|
|
||||||
if (value == null) {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
if (!(value instanceof String)) {
|
|
||||||
throw LuaValues.badArgumentOf(index, "string", value);
|
|
||||||
}
|
|
||||||
return Optional.of((String) value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -221,198 +306,150 @@ public interface IArguments {
|
|||||||
*
|
*
|
||||||
* @param index The argument number.
|
* @param index The argument number.
|
||||||
* @param klass The type of enum to parse.
|
* @param klass The type of enum to parse.
|
||||||
* @param <T> The type of enum to parse.
|
* @param <T> The type of enum to parse.
|
||||||
* @return The argument's value.
|
* @return The argument's value.
|
||||||
* @throws LuaException If the value is not a string or not a valid option for this enum.
|
* @throws LuaException If the value is not a string or not a valid option for this enum.
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
default <T extends Enum<T>> Optional<T> optEnum(int index, Class<T> klass) throws LuaException {
|
default <T extends Enum<T>> Optional<T> optEnum( int index, Class<T> klass ) throws LuaException
|
||||||
Optional<String> str = this.optString(index);
|
{
|
||||||
return str.isPresent() ? Optional.of(LuaValues.checkEnum(index, klass, str.get())) : Optional.empty();
|
Optional<String> str = optString( index );
|
||||||
|
return str.isPresent() ? Optional.of( LuaValues.checkEnum( index, klass, str.get() ) ) : Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an argument as a table.
|
||||||
|
*
|
||||||
|
* @param index The argument number.
|
||||||
|
* @return The argument's value, or {@link Optional#empty()} if not present.
|
||||||
|
* @throws LuaException If the value is not a table.
|
||||||
|
*/
|
||||||
|
default Optional<Map<?, ?>> optTable( int index ) throws LuaException
|
||||||
|
{
|
||||||
|
Object value = get( index );
|
||||||
|
if( value == null ) return Optional.empty();
|
||||||
|
if( !(value instanceof Map) ) throw LuaValues.badArgumentOf( index, "map", value );
|
||||||
|
return Optional.of( (Map<?, ?>) value );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an argument as a table in an unsafe manner.
|
||||||
|
*
|
||||||
|
* Classes implementing this interface may choose to implement a more optimised version which does not copy the
|
||||||
|
* table, instead returning a wrapper version, making it more efficient. However, the caller must guarantee that
|
||||||
|
* they do not access off the computer thread (and so should not be used with main-thread functions) or once the
|
||||||
|
* function call has finished (for instance, in callbacks).
|
||||||
|
*
|
||||||
|
* @param index The argument number.
|
||||||
|
* @return The argument's value, or {@link Optional#empty()} if not present.
|
||||||
|
* @throws LuaException If the value is not a table.
|
||||||
|
*/
|
||||||
|
@Nonnull
|
||||||
|
default Optional<LuaTable<?, ?>> optTableUnsafe( int index ) throws LuaException
|
||||||
|
{
|
||||||
|
Object value = get( index );
|
||||||
|
if( value == null ) return Optional.empty();
|
||||||
|
if( !(value instanceof Map) ) throw LuaValues.badArgumentOf( index, "map", value );
|
||||||
|
return Optional.of( new ObjectLuaTable( (Map<?, ?>) value ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an argument as a double.
|
* Get an argument as a double.
|
||||||
*
|
*
|
||||||
* @param index The argument number.
|
* @param index The argument number.
|
||||||
* @param def The default value, if this argument is not given.
|
* @param def The default value, if this argument is not given.
|
||||||
* @return The argument's value, or {@code def} if none was provided.
|
* @return The argument's value, or {@code def} if none was provided.
|
||||||
* @throws LuaException If the value is not a number.
|
* @throws LuaException If the value is not a number.
|
||||||
*/
|
*/
|
||||||
default double optDouble(int index, double def) throws LuaException {
|
default double optDouble( int index, double def ) throws LuaException
|
||||||
return this.optDouble(index).orElse(def);
|
{
|
||||||
}
|
return optDouble( index ).orElse( def );
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an argument as a double.
|
|
||||||
*
|
|
||||||
* @param index The argument number.
|
|
||||||
* @return The argument's value, or {@link Optional#empty()} if not present.
|
|
||||||
* @throws LuaException If the value is not a number.
|
|
||||||
*/
|
|
||||||
@Nonnull
|
|
||||||
default Optional<Double> optDouble(int index) throws LuaException {
|
|
||||||
Object value = this.get(index);
|
|
||||||
if (value == null) {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
if (!(value instanceof Number)) {
|
|
||||||
throw LuaValues.badArgumentOf(index, "number", value);
|
|
||||||
}
|
|
||||||
return Optional.of(((Number) value).doubleValue());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an argument as an int.
|
* Get an argument as an int.
|
||||||
*
|
*
|
||||||
* @param index The argument number.
|
* @param index The argument number.
|
||||||
* @param def The default value, if this argument is not given.
|
* @param def The default value, if this argument is not given.
|
||||||
* @return The argument's value, or {@code def} if none was provided.
|
* @return The argument's value, or {@code def} if none was provided.
|
||||||
* @throws LuaException If the value is not a number.
|
* @throws LuaException If the value is not a number.
|
||||||
*/
|
*/
|
||||||
default int optInt(int index, int def) throws LuaException {
|
default int optInt( int index, int def ) throws LuaException
|
||||||
return this.optInt(index).orElse(def);
|
{
|
||||||
}
|
return optInt( index ).orElse( def );
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an argument as an int.
|
|
||||||
*
|
|
||||||
* @param index The argument number.
|
|
||||||
* @return The argument's value, or {@link Optional#empty()} if not present.
|
|
||||||
* @throws LuaException If the value is not a number.
|
|
||||||
*/
|
|
||||||
@Nonnull
|
|
||||||
default Optional<Integer> optInt(int index) throws LuaException {
|
|
||||||
return this.optLong(index).map(Long::intValue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an argument as a long.
|
* Get an argument as a long.
|
||||||
*
|
*
|
||||||
* @param index The argument number.
|
* @param index The argument number.
|
||||||
* @return The argument's value, or {@link Optional#empty()} if not present.
|
* @param def The default value, if this argument is not given.
|
||||||
* @throws LuaException If the value is not a number.
|
|
||||||
*/
|
|
||||||
default Optional<Long> optLong(int index) throws LuaException {
|
|
||||||
Object value = this.get(index);
|
|
||||||
if (value == null) {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
if (!(value instanceof Number)) {
|
|
||||||
throw LuaValues.badArgumentOf(index, "number", value);
|
|
||||||
}
|
|
||||||
return Optional.of(LuaValues.checkFiniteNum(index, (Number) value)
|
|
||||||
.longValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an argument as a long.
|
|
||||||
*
|
|
||||||
* @param index The argument number.
|
|
||||||
* @param def The default value, if this argument is not given.
|
|
||||||
* @return The argument's value, or {@code def} if none was provided.
|
* @return The argument's value, or {@code def} if none was provided.
|
||||||
* @throws LuaException If the value is not a number.
|
* @throws LuaException If the value is not a number.
|
||||||
*/
|
*/
|
||||||
default long optLong(int index, long def) throws LuaException {
|
default long optLong( int index, long def ) throws LuaException
|
||||||
return this.optLong(index).orElse(def);
|
{
|
||||||
|
return optLong( index ).orElse( def );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an argument as a finite number (not infinite or NaN).
|
* Get an argument as a finite number (not infinite or NaN).
|
||||||
*
|
*
|
||||||
* @param index The argument number.
|
* @param index The argument number.
|
||||||
* @param def The default value, if this argument is not given.
|
* @param def The default value, if this argument is not given.
|
||||||
* @return The argument's value, or {@code def} if none was provided.
|
* @return The argument's value, or {@code def} if none was provided.
|
||||||
* @throws LuaException If the value is not finite.
|
* @throws LuaException If the value is not finite.
|
||||||
*/
|
*/
|
||||||
default double optFiniteDouble(int index, double def) throws LuaException {
|
default double optFiniteDouble( int index, double def ) throws LuaException
|
||||||
return this.optFiniteDouble(index).orElse(def);
|
{
|
||||||
}
|
return optFiniteDouble( index ).orElse( def );
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an argument as a finite number (not infinite or NaN).
|
|
||||||
*
|
|
||||||
* @param index The argument number.
|
|
||||||
* @return The argument's value, or {@link Optional#empty()} if not present.
|
|
||||||
* @throws LuaException If the value is not finite.
|
|
||||||
*/
|
|
||||||
default Optional<Double> optFiniteDouble(int index) throws LuaException {
|
|
||||||
Optional<Double> value = this.optDouble(index);
|
|
||||||
if (value.isPresent()) {
|
|
||||||
LuaValues.checkFiniteNum(index, value.get());
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an argument as a boolean.
|
* Get an argument as a boolean.
|
||||||
*
|
*
|
||||||
* @param index The argument number.
|
* @param index The argument number.
|
||||||
* @param def The default value, if this argument is not given.
|
* @param def The default value, if this argument is not given.
|
||||||
* @return The argument's value, or {@code def} if none was provided.
|
* @return The argument's value, or {@code def} if none was provided.
|
||||||
* @throws LuaException If the value is not a boolean.
|
* @throws LuaException If the value is not a boolean.
|
||||||
*/
|
*/
|
||||||
default boolean optBoolean(int index, boolean def) throws LuaException {
|
default boolean optBoolean( int index, boolean def ) throws LuaException
|
||||||
return this.optBoolean(index).orElse(def);
|
{
|
||||||
}
|
return optBoolean( index ).orElse( def );
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an argument as a boolean.
|
|
||||||
*
|
|
||||||
* @param index The argument number.
|
|
||||||
* @return The argument's value, or {@link Optional#empty()} if not present.
|
|
||||||
* @throws LuaException If the value is not a boolean.
|
|
||||||
*/
|
|
||||||
default Optional<Boolean> optBoolean(int index) throws LuaException {
|
|
||||||
Object value = this.get(index);
|
|
||||||
if (value == null) {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
if (!(value instanceof Boolean)) {
|
|
||||||
throw LuaValues.badArgumentOf(index, "boolean", value);
|
|
||||||
}
|
|
||||||
return Optional.of((Boolean) value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an argument as a string.
|
* Get an argument as a string.
|
||||||
*
|
*
|
||||||
* @param index The argument number.
|
* @param index The argument number.
|
||||||
* @param def The default value, if this argument is not given.
|
* @param def The default value, if this argument is not given.
|
||||||
* @return The argument's value, or {@code def} if none was provided.
|
* @return The argument's value, or {@code def} if none was provided.
|
||||||
* @throws LuaException If the value is not a string.
|
* @throws LuaException If the value is not a string.
|
||||||
*/
|
*/
|
||||||
default String optString(int index, String def) throws LuaException {
|
default String optString( int index, String def ) throws LuaException
|
||||||
return this.optString(index).orElse(def);
|
{
|
||||||
|
return optString( index ).orElse( def );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an argument as a table.
|
* Get an argument as a table.
|
||||||
*
|
*
|
||||||
* @param index The argument number.
|
* @param index The argument number.
|
||||||
* @param def The default value, if this argument is not given.
|
* @param def The default value, if this argument is not given.
|
||||||
* @return The argument's value, or {@code def} if none was provided.
|
* @return The argument's value, or {@code def} if none was provided.
|
||||||
* @throws LuaException If the value is not a table.
|
* @throws LuaException If the value is not a table.
|
||||||
*/
|
*/
|
||||||
default Map<?, ?> optTable(int index, Map<Object, Object> def) throws LuaException {
|
default Map<?, ?> optTable( int index, Map<Object, Object> def ) throws LuaException
|
||||||
return this.optTable(index).orElse(def);
|
{
|
||||||
|
return optTable( index ).orElse( def );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an argument as a table.
|
* This is called when the current function finishes, before any main thread tasks have run.
|
||||||
*
|
*
|
||||||
* @param index The argument number.
|
* Called when the current function returns, and so some values are no longer guaranteed to be safe to access.
|
||||||
* @return The argument's value, or {@link Optional#empty()} if not present.
|
|
||||||
* @throws LuaException If the value is not a table.
|
|
||||||
*/
|
*/
|
||||||
default Optional<Map<?, ?>> optTable(int index) throws LuaException {
|
default void releaseImmediate()
|
||||||
Object value = this.get(index);
|
{
|
||||||
if (value == null) {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
if (!(value instanceof Map)) {
|
|
||||||
throw LuaValues.badArgumentOf(index, "map", value);
|
|
||||||
}
|
|
||||||
return Optional.of((Map<?, ?>) value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,20 +1,21 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||||
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
|
||||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.api.lua;
|
package dan200.computercraft.api.lua;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import dan200.computercraft.api.filesystem.IFileSystem;
|
import dan200.computercraft.api.filesystem.IFileSystem;
|
||||||
import dan200.computercraft.api.peripheral.IComputerAccess;
|
import dan200.computercraft.api.peripheral.IComputerAccess;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An interface passed to {@link ILuaAPIFactory} in order to provide additional information about a computer.
|
* An interface passed to {@link ILuaAPIFactory} in order to provide additional information
|
||||||
|
* about a computer.
|
||||||
*/
|
*/
|
||||||
public interface IComputerSystem extends IComputerAccess {
|
public interface IComputerSystem extends IComputerAccess
|
||||||
|
{
|
||||||
/**
|
/**
|
||||||
* Get the file system for this computer.
|
* Get the file system for this computer.
|
||||||
*
|
*
|
||||||
|
@@ -1,24 +1,26 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||||
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
|
||||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.api.lua;
|
package dan200.computercraft.api.lua;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
|
|
||||||
import dan200.computercraft.api.peripheral.IDynamicPeripheral;
|
import dan200.computercraft.api.peripheral.IDynamicPeripheral;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An interface for representing custom objects returned by peripherals or other Lua objects.
|
* An interface for representing custom objects returned by peripherals or other Lua objects.
|
||||||
*
|
*
|
||||||
* Generally, one does not need to implement this type - it is sufficient to return an object with some methods annotated with {@link LuaFunction}. {@link
|
* Generally, one does not need to implement this type - it is sufficient to return an object with some methods
|
||||||
* IDynamicLuaObject} is useful when you wish your available methods to change at runtime.
|
* annotated with {@link LuaFunction}. {@link IDynamicLuaObject} is useful when you wish your available methods to
|
||||||
|
* change at runtime.
|
||||||
*/
|
*/
|
||||||
public interface IDynamicLuaObject {
|
public interface IDynamicLuaObject
|
||||||
|
{
|
||||||
/**
|
/**
|
||||||
* Get the names of the methods that this object implements. This should not change over the course of the object's lifetime.
|
* Get the names of the methods that this object implements. This should not change over the course of the object's
|
||||||
|
* lifetime.
|
||||||
*
|
*
|
||||||
* @return The method names this object provides.
|
* @return The method names this object provides.
|
||||||
* @see IDynamicPeripheral#getMethodNames()
|
* @see IDynamicPeripheral#getMethodNames()
|
||||||
@@ -29,12 +31,15 @@ public interface IDynamicLuaObject {
|
|||||||
/**
|
/**
|
||||||
* Called when a user calls one of the methods that this object implements.
|
* Called when a user calls one of the methods that this object implements.
|
||||||
*
|
*
|
||||||
* @param context The context of the currently running lua thread. This can be used to wait for events or otherwise yield.
|
* @param context The context of the currently running lua thread. This can be used to wait for events
|
||||||
* @param method An integer identifying which method index from {@link #getMethodNames()} the computer wishes to call.
|
* or otherwise yield.
|
||||||
|
* @param method An integer identifying which method index from {@link #getMethodNames()} the computer wishes
|
||||||
|
* to call.
|
||||||
* @param arguments The arguments for this method.
|
* @param arguments The arguments for this method.
|
||||||
* @return The result of this function. Either an immediate value ({@link MethodResult#of(Object...)} or an instruction to yield.
|
* @return The result of this function. Either an immediate value ({@link MethodResult#of(Object...)} or an
|
||||||
|
* instruction to yield.
|
||||||
* @throws LuaException If the function threw an exception.
|
* @throws LuaException If the function threw an exception.
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
MethodResult callMethod(@Nonnull ILuaContext context, int method, @Nonnull IArguments arguments) throws LuaException;
|
MethodResult callMethod( @Nonnull ILuaContext context, int method, @Nonnull IArguments arguments ) throws LuaException;
|
||||||
}
|
}
|
||||||
|
@@ -1,24 +1,24 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||||
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
|
||||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.api.lua;
|
package dan200.computercraft.api.lua;
|
||||||
|
|
||||||
import dan200.computercraft.api.ComputerCraftAPI;
|
import dan200.computercraft.api.ComputerCraftAPI;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a Lua object which is stored as a global variable on computer startup. This must either provide {@link LuaFunction} annotated functions or
|
* Represents a Lua object which is stored as a global variable on computer startup. This must either provide
|
||||||
* implement {@link IDynamicLuaObject}.
|
* {@link LuaFunction} annotated functions or implement {@link IDynamicLuaObject}.
|
||||||
*
|
*
|
||||||
* Before implementing this interface, consider alternative methods of providing methods. It is generally preferred to use peripherals to provide
|
* Before implementing this interface, consider alternative methods of providing methods. It is generally preferred
|
||||||
* functionality to users.
|
* to use peripherals to provide functionality to users.
|
||||||
*
|
*
|
||||||
* @see ILuaAPIFactory
|
* @see ILuaAPIFactory
|
||||||
* @see ComputerCraftAPI#registerAPIFactory(ILuaAPIFactory)
|
* @see ComputerCraftAPI#registerAPIFactory(ILuaAPIFactory)
|
||||||
*/
|
*/
|
||||||
public interface ILuaAPI {
|
public interface ILuaAPI
|
||||||
|
{
|
||||||
/**
|
/**
|
||||||
* Get the globals this API will be assigned to. This will override any other global, so you should
|
* Get the globals this API will be assigned to. This will override any other global, so you should
|
||||||
*
|
*
|
||||||
@@ -31,13 +31,15 @@ public interface ILuaAPI {
|
|||||||
*
|
*
|
||||||
* One should only interact with the file system.
|
* One should only interact with the file system.
|
||||||
*/
|
*/
|
||||||
default void startup() {
|
default void startup()
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called every time the computer is ticked. This can be used to process various.
|
* Called every time the computer is ticked. This can be used to process various.
|
||||||
*/
|
*/
|
||||||
default void update() {
|
default void update()
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -45,6 +47,7 @@ public interface ILuaAPI {
|
|||||||
*
|
*
|
||||||
* This should reset the state of the object, disposing any remaining file handles, or other resources.
|
* This should reset the state of the object, disposing any remaining file handles, or other resources.
|
||||||
*/
|
*/
|
||||||
default void shutdown() {
|
default void shutdown()
|
||||||
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,16 +1,15 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||||
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
|
||||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.api.lua;
|
package dan200.computercraft.api.lua;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.ComputerCraftAPI;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import dan200.computercraft.api.ComputerCraftAPI;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct an {@link ILuaAPI} for a specific computer.
|
* Construct an {@link ILuaAPI} for a specific computer.
|
||||||
*
|
*
|
||||||
@@ -18,7 +17,8 @@ import dan200.computercraft.api.ComputerCraftAPI;
|
|||||||
* @see ComputerCraftAPI#registerAPIFactory(ILuaAPIFactory)
|
* @see ComputerCraftAPI#registerAPIFactory(ILuaAPIFactory)
|
||||||
*/
|
*/
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface ILuaAPIFactory {
|
public interface ILuaAPIFactory
|
||||||
|
{
|
||||||
/**
|
/**
|
||||||
* Create a new API instance for a given computer.
|
* Create a new API instance for a given computer.
|
||||||
*
|
*
|
||||||
@@ -26,5 +26,5 @@ public interface ILuaAPIFactory {
|
|||||||
* @return The created API, or {@code null} if one should not be injected.
|
* @return The created API, or {@code null} if one should not be injected.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
ILuaAPI create(@Nonnull IComputerSystem computer);
|
ILuaAPI create( @Nonnull IComputerSystem computer );
|
||||||
}
|
}
|
||||||
|
@@ -1,9 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||||
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
|
||||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.api.lua;
|
package dan200.computercraft.api.lua;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
@@ -13,14 +12,16 @@ import javax.annotation.Nonnull;
|
|||||||
*
|
*
|
||||||
* @see MethodResult#yield(Object[], ILuaCallback)
|
* @see MethodResult#yield(Object[], ILuaCallback)
|
||||||
*/
|
*/
|
||||||
public interface ILuaCallback {
|
public interface ILuaCallback
|
||||||
|
{
|
||||||
/**
|
/**
|
||||||
* Resume this coroutine.
|
* Resume this coroutine.
|
||||||
*
|
*
|
||||||
* @param args The result of resuming this coroutine. These will have the same form as described in {@link LuaFunction}.
|
* @param args The result of resuming this coroutine. These will have the same form as described in
|
||||||
|
* {@link LuaFunction}.
|
||||||
* @return The result of this continuation. Either the result to return to the callee, or another yield.
|
* @return The result of this continuation. Either the result to return to the callee, or another yield.
|
||||||
* @throws LuaException On an error.
|
* @throws LuaException On an error.
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
MethodResult resume(Object[] args) throws LuaException;
|
MethodResult resume( Object[] args ) throws LuaException;
|
||||||
}
|
}
|
||||||
|
@@ -1,29 +1,47 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||||
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
|
||||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.api.lua;
|
package dan200.computercraft.api.lua;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An interface passed to peripherals and {@link IDynamicLuaObject}s by computers or turtles, providing methods that allow the peripheral call to interface
|
* An interface passed to peripherals and {@link IDynamicLuaObject}s by computers or turtles, providing methods
|
||||||
* with the computer.
|
* that allow the peripheral call to interface with the computer.
|
||||||
*/
|
*/
|
||||||
public interface ILuaContext {
|
public interface ILuaContext
|
||||||
|
{
|
||||||
/**
|
/**
|
||||||
* Queue a task to be executed on the main server thread at the beginning of next tick, but do not wait for it to complete. This should be used when you
|
* Queue a task to be executed on the main server thread at the beginning of next tick, but do not wait for it to
|
||||||
* need to interact with the world in a thread-safe manner but do not care about the result or you wish to run asynchronously.
|
* complete. This should be used when you need to interact with the world in a thread-safe manner but do not care
|
||||||
|
* about the result or you wish to run asynchronously.
|
||||||
*
|
*
|
||||||
* When the task has finished, it will enqueue a {@code task_completed} event, which takes the task id, a success value and the return values, or an
|
* When the task has finished, it will enqueue a {@code task_completed} event, which takes the task id, a success
|
||||||
* error message if it failed.
|
* value and the return values, or an error message if it failed.
|
||||||
*
|
*
|
||||||
* @param task The task to execute on the main thread.
|
* @param task The task to execute on the main thread.
|
||||||
* @return The "id" of the task. This will be the first argument to the {@code task_completed} event.
|
* @return The "id" of the task. This will be the first argument to the {@code task_completed} event.
|
||||||
* @throws LuaException If the task could not be queued.
|
* @throws LuaException If the task could not be queued.
|
||||||
* @see LuaFunction#mainThread() To run functions on the main thread and return their results synchronously.
|
* @see LuaFunction#mainThread() To run functions on the main thread and return their results synchronously.
|
||||||
*/
|
*/
|
||||||
long issueMainThreadTask(@Nonnull ILuaTask task) throws LuaException;
|
long issueMainThreadTask( @Nonnull ILuaTask task ) throws LuaException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queue a task to be executed on the main server thread at the beginning of next tick, waiting for it to complete.
|
||||||
|
* This should be used when you need to interact with the world in a thread-safe manner.
|
||||||
|
*
|
||||||
|
* Note that the return values of your task are handled as events, meaning more complex objects such as maps or
|
||||||
|
* {@link IDynamicLuaObject} will not preserve their identities.
|
||||||
|
*
|
||||||
|
* @param task The task to execute on the main thread.
|
||||||
|
* @return The objects returned by {@code task}.
|
||||||
|
* @throws LuaException If the task could not be queued, or if the task threw an exception.
|
||||||
|
*/
|
||||||
|
@Nonnull
|
||||||
|
default MethodResult executeMainThreadTask( @Nonnull ILuaTask task ) throws LuaException
|
||||||
|
{
|
||||||
|
return TaskCallback.make( this, task );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,29 +1,29 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||||
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
|
||||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.api.lua;
|
package dan200.computercraft.api.lua;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A function, which can be called from Lua. If you need to return a table of functions, it is recommended to use an object with {@link LuaFunction}
|
* A function, which can be called from Lua. If you need to return a table of functions, it is recommended to use
|
||||||
* methods, or implement {@link IDynamicLuaObject}.
|
* an object with {@link LuaFunction} methods, or implement {@link IDynamicLuaObject}.
|
||||||
*
|
*
|
||||||
* @see MethodResult#of(Object)
|
* @see MethodResult#of(Object)
|
||||||
*/
|
*/
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface ILuaFunction {
|
public interface ILuaFunction
|
||||||
|
{
|
||||||
/**
|
/**
|
||||||
* Call this function with a series of arguments. Note, this will <em>always</em> be called on the computer thread, and so its implementation must be
|
* Call this function with a series of arguments. Note, this will <em>always</em> be called on the computer thread,
|
||||||
* thread-safe.
|
* and so its implementation must be thread-safe.
|
||||||
*
|
*
|
||||||
* @param arguments The arguments for this function
|
* @param arguments The arguments for this function
|
||||||
* @return The result of calling this function.
|
* @return The result of calling this function.
|
||||||
* @throws LuaException Upon Lua errors.
|
* @throws LuaException Upon Lua errors.
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
MethodResult call(@Nonnull IArguments arguments) throws LuaException;
|
MethodResult call( @Nonnull IArguments arguments ) throws LuaException;
|
||||||
}
|
}
|
||||||
|
@@ -1,18 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
|
||||||
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
|
|
||||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package dan200.computercraft.api.lua;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
public interface ILuaObject {
|
|
||||||
@Nonnull
|
|
||||||
String[] getMethodNames();
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
Object[] callMethod(@Nonnull ILuaContext context, int method, @Nonnull Object[] arguments) throws LuaException, InterruptedException;
|
|
||||||
}
|
|
@@ -1,27 +1,29 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||||
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
|
||||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.api.lua;
|
package dan200.computercraft.api.lua;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A task which can be executed via {@link ILuaContext#issueMainThreadTask(ILuaTask)} This will be run on the main thread, at the beginning of the next
|
* A task which can be executed via {@link ILuaContext#issueMainThreadTask(ILuaTask)} This will be run on the main
|
||||||
* tick.
|
* thread, at the beginning of the
|
||||||
|
* next tick.
|
||||||
*
|
*
|
||||||
* @see ILuaContext#issueMainThreadTask(ILuaTask)
|
* @see ILuaContext#issueMainThreadTask(ILuaTask)
|
||||||
*/
|
*/
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface ILuaTask {
|
public interface ILuaTask
|
||||||
|
{
|
||||||
/**
|
/**
|
||||||
* Execute this task.
|
* Execute this task.
|
||||||
*
|
*
|
||||||
* @return The arguments to add to the {@code task_completed} event.
|
* @return The arguments to add to the {@code task_completed} event.
|
||||||
* @throws LuaException If you throw any exception from this function, a lua error will be raised with the same message as your exception. Use this
|
* @throws LuaException If you throw any exception from this function, a lua error will be raised with the
|
||||||
* to throw appropriate errors if the wrong arguments are supplied to your method.
|
* same message as your exception. Use this to throw appropriate errors if the wrong
|
||||||
|
* arguments are supplied to your method.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
Object[] execute() throws LuaException;
|
Object[] execute() throws LuaException;
|
||||||
|
@@ -1,9 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||||
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
|
||||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.api.lua;
|
package dan200.computercraft.api.lua;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@@ -11,20 +10,23 @@ import javax.annotation.Nullable;
|
|||||||
/**
|
/**
|
||||||
* An exception representing an error in Lua, like that raised by the {@code error()} function.
|
* An exception representing an error in Lua, like that raised by the {@code error()} function.
|
||||||
*/
|
*/
|
||||||
public class LuaException extends Exception {
|
public class LuaException extends Exception
|
||||||
|
{
|
||||||
private static final long serialVersionUID = -6136063076818512651L;
|
private static final long serialVersionUID = -6136063076818512651L;
|
||||||
private final boolean hasLevel;
|
private final boolean hasLevel;
|
||||||
private final int level;
|
private final int level;
|
||||||
|
|
||||||
public LuaException(@Nullable String message) {
|
public LuaException( @Nullable String message )
|
||||||
super(message);
|
{
|
||||||
this.hasLevel = false;
|
super( message );
|
||||||
this.level = 1;
|
hasLevel = false;
|
||||||
|
level = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaException(@Nullable String message, int level) {
|
public LuaException( @Nullable String message, int level )
|
||||||
super(message);
|
{
|
||||||
this.hasLevel = true;
|
super( message );
|
||||||
|
hasLevel = true;
|
||||||
this.level = level;
|
this.level = level;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,16 +35,19 @@ public class LuaException extends Exception {
|
|||||||
*
|
*
|
||||||
* @return Whether this has an explicit level.
|
* @return Whether this has an explicit level.
|
||||||
*/
|
*/
|
||||||
public boolean hasLevel() {
|
public boolean hasLevel()
|
||||||
return this.hasLevel;
|
{
|
||||||
|
return hasLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The level this error is raised at. Level 1 is the function's caller, level 2 is that function's caller, and so on.
|
* The level this error is raised at. Level 1 is the function's caller, level 2 is that function's caller, and so
|
||||||
|
* on.
|
||||||
*
|
*
|
||||||
* @return The level to raise the error at.
|
* @return The level to raise the error at.
|
||||||
*/
|
*/
|
||||||
public int getLevel() {
|
public int getLevel()
|
||||||
return this.level;
|
{
|
||||||
|
return level;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,27 +1,22 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||||
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
|
||||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.api.lua;
|
package dan200.computercraft.api.lua;
|
||||||
|
|
||||||
import java.lang.annotation.Documented;
|
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
import dan200.computercraft.api.peripheral.IComputerAccess;
|
import dan200.computercraft.api.peripheral.IComputerAccess;
|
||||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to mark a Java function which is callable from Lua.
|
* Used to mark a Java function which is callable from Lua.
|
||||||
*
|
*
|
||||||
* Methods annotated with {@link LuaFunction} must be public final instance methods. They can have any number of parameters, but they must be of the
|
* Methods annotated with {@link LuaFunction} must be public final instance methods. They can have any number of
|
||||||
* following types:
|
* parameters, but they must be of the following types:
|
||||||
*
|
*
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@link ILuaContext} (and {@link IComputerAccess} if on a {@link IPeripheral})</li>
|
* <li>{@link ILuaContext} (and {@link IComputerAccess} if on a {@link IPeripheral})</li>
|
||||||
@@ -41,9 +36,10 @@ import dan200.computercraft.api.peripheral.IPeripheral;
|
|||||||
* {@link MethodResult#of(Object...)}.
|
* {@link MethodResult#of(Object...)}.
|
||||||
*/
|
*/
|
||||||
@Documented
|
@Documented
|
||||||
@Retention (RetentionPolicy.RUNTIME)
|
@Retention( RetentionPolicy.RUNTIME )
|
||||||
@Target (ElementType.METHOD)
|
@Target( ElementType.METHOD )
|
||||||
public @interface LuaFunction {
|
public @interface LuaFunction
|
||||||
|
{
|
||||||
/**
|
/**
|
||||||
* Explicitly specify the method names of this function. If not given, it uses the name of the annotated method.
|
* Explicitly specify the method names of this function. If not given, it uses the name of the annotated method.
|
||||||
*
|
*
|
||||||
@@ -52,10 +48,20 @@ public @interface LuaFunction {
|
|||||||
String[] value() default {};
|
String[] value() default {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run this function on the main server thread. This should be specified for any method which interacts with Minecraft in a thread-unsafe manner.
|
* Run this function on the main server thread. This should be specified for any method which interacts with
|
||||||
|
* Minecraft in a thread-unsafe manner.
|
||||||
*
|
*
|
||||||
* @return Whether this functi
|
* @return Whether this function should be run on the main thread.
|
||||||
* @see ILuaContext#issueMainThreadTask(ILuaTask)
|
* @see ILuaContext#issueMainThreadTask(ILuaTask)
|
||||||
*/
|
*/
|
||||||
boolean mainThread() default false;
|
boolean mainThread() default false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow using "unsafe" arguments, such {@link IArguments#getTableUnsafe(int)}.
|
||||||
|
*
|
||||||
|
* This is incompatible with {@link #mainThread()}.
|
||||||
|
*
|
||||||
|
* @return Whether this function supports unsafe arguments.
|
||||||
|
*/
|
||||||
|
boolean unsafe() default false;
|
||||||
}
|
}
|
||||||
|
113
src/main/java/dan200/computercraft/api/lua/LuaTable.java
Normal file
113
src/main/java/dan200/computercraft/api/lua/LuaTable.java
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||||
|
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
|
||||||
|
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||||
|
*/
|
||||||
|
package dan200.computercraft.api.lua;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static dan200.computercraft.api.lua.LuaValues.*;
|
||||||
|
|
||||||
|
public interface LuaTable<K, V> extends Map<K, V>
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Compute the length of the array part of this table.
|
||||||
|
*
|
||||||
|
* @return This table's length.
|
||||||
|
*/
|
||||||
|
default int length()
|
||||||
|
{
|
||||||
|
int size = 0;
|
||||||
|
while( containsKey( (double) (size + 1) ) ) size++;
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an array entry as an integer.
|
||||||
|
*
|
||||||
|
* @param index The index in the table, starting at 1.
|
||||||
|
* @return The table's value.
|
||||||
|
* @throws LuaException If the value is not an integer.
|
||||||
|
*/
|
||||||
|
default long getLong( int index ) throws LuaException
|
||||||
|
{
|
||||||
|
Object value = get( (double) index );
|
||||||
|
if( !(value instanceof Number) ) throw badTableItem( index, "number", getType( value ) );
|
||||||
|
|
||||||
|
Number number = (Number) value;
|
||||||
|
double asDouble = number.doubleValue();
|
||||||
|
if( !Double.isFinite( asDouble ) ) throw badTableItem( index, "number", getNumericType( asDouble ) );
|
||||||
|
return number.longValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a table entry as an integer.
|
||||||
|
*
|
||||||
|
* @param key The name of the field in the table.
|
||||||
|
* @return The table's value.
|
||||||
|
* @throws LuaException If the value is not an integer.
|
||||||
|
*/
|
||||||
|
default long getLong( String key ) throws LuaException
|
||||||
|
{
|
||||||
|
Object value = get( key );
|
||||||
|
if( !(value instanceof Number) ) throw badField( key, "number", getType( value ) );
|
||||||
|
|
||||||
|
Number number = (Number) value;
|
||||||
|
double asDouble = number.doubleValue();
|
||||||
|
if( !Double.isFinite( asDouble ) ) throw badField( key, "number", getNumericType( asDouble ) );
|
||||||
|
return number.longValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an array entry as an integer.
|
||||||
|
*
|
||||||
|
* @param index The index in the table, starting at 1.
|
||||||
|
* @return The table's value.
|
||||||
|
* @throws LuaException If the value is not an integer.
|
||||||
|
*/
|
||||||
|
default int getInt( int index ) throws LuaException
|
||||||
|
{
|
||||||
|
return (int) getLong( index );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a table entry as an integer.
|
||||||
|
*
|
||||||
|
* @param key The name of the field in the table.
|
||||||
|
* @return The table's value.
|
||||||
|
* @throws LuaException If the value is not an integer.
|
||||||
|
*/
|
||||||
|
default int getInt( String key ) throws LuaException
|
||||||
|
{
|
||||||
|
return (int) getLong( key );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
default V put( K o, V o2 )
|
||||||
|
{
|
||||||
|
throw new UnsupportedOperationException( "Cannot modify LuaTable" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default V remove( Object o )
|
||||||
|
{
|
||||||
|
throw new UnsupportedOperationException( "Cannot modify LuaTable" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default void putAll( @Nonnull Map<? extends K, ? extends V> map )
|
||||||
|
{
|
||||||
|
throw new UnsupportedOperationException( "Cannot modify LuaTable" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default void clear()
|
||||||
|
{
|
||||||
|
throw new UnsupportedOperationException( "Cannot modify LuaTable" );
|
||||||
|
}
|
||||||
|
}
|
@@ -1,24 +1,24 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||||
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
|
||||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.api.lua;
|
package dan200.computercraft.api.lua;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Various utility functions for operating with Lua values.
|
* Various utility functions for operating with Lua values.
|
||||||
*
|
*
|
||||||
* @see IArguments
|
* @see IArguments
|
||||||
*/
|
*/
|
||||||
public final class LuaValues {
|
public final class LuaValues
|
||||||
private LuaValues() {
|
{
|
||||||
|
private LuaValues()
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,116 +28,134 @@ public final class LuaValues {
|
|||||||
* @return The encoded string.
|
* @return The encoded string.
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public static ByteBuffer encode(@Nonnull String string) {
|
public static ByteBuffer encode( @Nonnull String string )
|
||||||
|
{
|
||||||
byte[] chars = new byte[string.length()];
|
byte[] chars = new byte[string.length()];
|
||||||
for (int i = 0; i < chars.length; i++) {
|
for( int i = 0; i < chars.length; i++ )
|
||||||
char c = string.charAt(i);
|
{
|
||||||
|
char c = string.charAt( i );
|
||||||
chars[i] = c < 256 ? (byte) c : 63;
|
chars[i] = c < 256 ? (byte) c : 63;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ByteBuffer.wrap(chars)
|
return ByteBuffer.wrap( chars ).asReadOnlyBuffer();
|
||||||
.asReadOnlyBuffer();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a "bad argument" exception, from an expected type and the actual value provided.
|
* Returns a more detailed representation of this number's type. If this is finite, it will just return "number",
|
||||||
|
* otherwise it returns whether it is infinite or NaN.
|
||||||
*
|
*
|
||||||
* @param index The argument number, starting from 0.
|
* @param value The value to extract the type for.
|
||||||
* @param expected The expected type for this argument.
|
* @return This value's numeric type.
|
||||||
* @param actual The actual value provided for this argument.
|
|
||||||
* @return The constructed exception, which should be thrown immediately.
|
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public static LuaException badArgumentOf(int index, @Nonnull String expected, @Nullable Object actual) {
|
public static String getNumericType( double value )
|
||||||
return badArgument(index, expected, getType(actual));
|
{
|
||||||
}
|
if( Double.isNaN( value ) ) return "nan";
|
||||||
|
if( value == Double.POSITIVE_INFINITY ) return "inf";
|
||||||
/**
|
if( value == Double.NEGATIVE_INFINITY ) return "-inf";
|
||||||
* Construct a "bad argument" exception, from an expected and actual type.
|
return "number";
|
||||||
*
|
|
||||||
* @param index The argument number, starting from 0.
|
|
||||||
* @param expected The expected type for this argument.
|
|
||||||
* @param actual The provided type for this argument.
|
|
||||||
* @return The constructed exception, which should be thrown immediately.
|
|
||||||
*/
|
|
||||||
@Nonnull
|
|
||||||
public static LuaException badArgument(int index, @Nonnull String expected, @Nonnull String actual) {
|
|
||||||
return new LuaException("bad argument #" + (index + 1) + " (" + expected + " expected, got " + actual + ")");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a string representation of the given value's type.
|
* Get a string representation of the given value's type.
|
||||||
*
|
*
|
||||||
* @param value The value whose type we are trying to compute.
|
* @param value The value whose type we are trying to compute.
|
||||||
* @return A string representation of the given value's type, in a similar format to that provided by Lua's {@code type} function.
|
* @return A string representation of the given value's type, in a similar format to that provided by Lua's
|
||||||
|
* {@code type} function.
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public static String getType(@Nullable Object value) {
|
public static String getType( @Nullable Object value )
|
||||||
if (value == null) {
|
{
|
||||||
return "nil";
|
if( value == null ) return "nil";
|
||||||
}
|
if( value instanceof String ) return "string";
|
||||||
if (value instanceof String) {
|
if( value instanceof Boolean ) return "boolean";
|
||||||
return "string";
|
if( value instanceof Number ) return "number";
|
||||||
}
|
if( value instanceof Map ) return "table";
|
||||||
if (value instanceof Boolean) {
|
|
||||||
return "boolean";
|
|
||||||
}
|
|
||||||
if (value instanceof Number) {
|
|
||||||
return "number";
|
|
||||||
}
|
|
||||||
if (value instanceof Map) {
|
|
||||||
return "table";
|
|
||||||
}
|
|
||||||
return "userdata";
|
return "userdata";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensure a numeric argument is finite (i.e. not infinite or {@link Double#NaN}.
|
* Construct a "bad argument" exception, from an expected type and the actual value provided.
|
||||||
*
|
*
|
||||||
* @param index The argument index to check.
|
* @param index The argument number, starting from 0.
|
||||||
* @param value The value to check.
|
* @param expected The expected type for this argument.
|
||||||
* @return The input {@code value}.
|
* @param actual The actual value provided for this argument.
|
||||||
* @throws LuaException If this is not a finite number.
|
* @return The constructed exception, which should be thrown immediately.
|
||||||
*/
|
|
||||||
public static Number checkFiniteNum(int index, Number value) throws LuaException {
|
|
||||||
checkFinite(index, value.doubleValue());
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ensure a numeric argument is finite (i.e. not infinite or {@link Double#NaN}.
|
|
||||||
*
|
|
||||||
* @param index The argument index to check.
|
|
||||||
* @param value The value to check.
|
|
||||||
* @return The input {@code value}.
|
|
||||||
* @throws LuaException If this is not a finite number.
|
|
||||||
*/
|
|
||||||
public static double checkFinite(int index, double value) throws LuaException {
|
|
||||||
if (!Double.isFinite(value)) {
|
|
||||||
throw badArgument(index, "number", getNumericType(value));
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a more detailed representation of this number's type. If this is finite, it will just return "number", otherwise it returns whether it is
|
|
||||||
* infinite or NaN.
|
|
||||||
*
|
|
||||||
* @param value The value to extract the type for.
|
|
||||||
* @return This value's numeric type.
|
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public static String getNumericType(double value) {
|
public static LuaException badArgumentOf( int index, @Nonnull String expected, @Nullable Object actual )
|
||||||
if (Double.isNaN(value)) {
|
{
|
||||||
return "nan";
|
return badArgument( index, expected, getType( actual ) );
|
||||||
}
|
}
|
||||||
if (value == Double.POSITIVE_INFINITY) {
|
|
||||||
return "inf";
|
/**
|
||||||
}
|
* Construct a "bad argument" exception, from an expected and actual type.
|
||||||
if (value == Double.NEGATIVE_INFINITY) {
|
*
|
||||||
return "-inf";
|
* @param index The argument number, starting from 0.
|
||||||
}
|
* @param expected The expected type for this argument.
|
||||||
return "number";
|
* @param actual The provided type for this argument.
|
||||||
|
* @return The constructed exception, which should be thrown immediately.
|
||||||
|
*/
|
||||||
|
@Nonnull
|
||||||
|
public static LuaException badArgument( int index, @Nonnull String expected, @Nonnull String actual )
|
||||||
|
{
|
||||||
|
return new LuaException( "bad argument #" + (index + 1) + " (" + expected + " expected, got " + actual + ")" );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a table item exception, from an expected and actual type.
|
||||||
|
*
|
||||||
|
* @param index The index into the table, starting from 1.
|
||||||
|
* @param expected The expected type for this table item.
|
||||||
|
* @param actual The provided type for this table item.
|
||||||
|
* @return The constructed exception, which should be thrown immediately.
|
||||||
|
*/
|
||||||
|
@Nonnull
|
||||||
|
public static LuaException badTableItem( int index, @Nonnull String expected, @Nonnull String actual )
|
||||||
|
{
|
||||||
|
return new LuaException( "table item #" + index + " is not " + expected + " (got " + actual + ")" );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a field exception, from an expected and actual type.
|
||||||
|
*
|
||||||
|
* @param key The name of the field.
|
||||||
|
* @param expected The expected type for this table item.
|
||||||
|
* @param actual The provided type for this table item.
|
||||||
|
* @return The constructed exception, which should be thrown immediately.
|
||||||
|
*/
|
||||||
|
@Nonnull
|
||||||
|
public static LuaException badField( String key, @Nonnull String expected, @Nonnull String actual )
|
||||||
|
{
|
||||||
|
return new LuaException( "field " + key + " is not " + expected + " (got " + actual + ")" );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure a numeric argument is finite (i.e. not infinite or {@link Double#NaN}.
|
||||||
|
*
|
||||||
|
* @param index The argument index to check.
|
||||||
|
* @param value The value to check.
|
||||||
|
* @return The input {@code value}.
|
||||||
|
* @throws LuaException If this is not a finite number.
|
||||||
|
*/
|
||||||
|
public static Number checkFiniteNum( int index, Number value ) throws LuaException
|
||||||
|
{
|
||||||
|
checkFinite( index, value.doubleValue() );
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure a numeric argument is finite (i.e. not infinite or {@link Double#NaN}.
|
||||||
|
*
|
||||||
|
* @param index The argument index to check.
|
||||||
|
* @param value The value to check.
|
||||||
|
* @return The input {@code value}.
|
||||||
|
* @throws LuaException If this is not a finite number.
|
||||||
|
*/
|
||||||
|
public static double checkFinite( int index, double value ) throws LuaException
|
||||||
|
{
|
||||||
|
if( !Double.isFinite( value ) ) throw badArgument( index, "number", getNumericType( value ) );
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -146,18 +164,17 @@ public final class LuaValues {
|
|||||||
* @param index The argument index to check.
|
* @param index The argument index to check.
|
||||||
* @param klass The class of the enum instance.
|
* @param klass The class of the enum instance.
|
||||||
* @param value The value to extract.
|
* @param value The value to extract.
|
||||||
* @param <T> The type of enum we are extracting.
|
* @param <T> The type of enum we are extracting.
|
||||||
* @return The parsed enum value.
|
* @return The parsed enum value.
|
||||||
* @throws LuaException If this is not a known enum value.
|
* @throws LuaException If this is not a known enum value.
|
||||||
*/
|
*/
|
||||||
public static <T extends Enum<T>> T checkEnum(int index, Class<T> klass, String value) throws LuaException {
|
public static <T extends Enum<T>> T checkEnum( int index, Class<T> klass, String value ) throws LuaException
|
||||||
for (T possibility : klass.getEnumConstants()) {
|
{
|
||||||
if (possibility.name()
|
for( T possibility : klass.getEnumConstants() )
|
||||||
.equalsIgnoreCase(value)) {
|
{
|
||||||
return possibility;
|
if( possibility.name().equalsIgnoreCase( value ) ) return possibility;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new LuaException("bad argument #" + (index + 1) + " (unknown option " + value + ")");
|
throw new LuaException( "bad argument #" + (index + 1) + " (unknown option " + value + ")" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,42 +1,43 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||||
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
|
||||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.api.lua;
|
package dan200.computercraft.api.lua;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.peripheral.IComputerAccess;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import dan200.computercraft.api.peripheral.IComputerAccess;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The result of invoking a Lua method.
|
* The result of invoking a Lua method.
|
||||||
*
|
*
|
||||||
* Method results either return a value immediately ({@link #of(Object...)} or yield control to the parent coroutine. When the current coroutine is resumed,
|
* Method results either return a value immediately ({@link #of(Object...)} or yield control to the parent coroutine.
|
||||||
* we invoke the provided {@link ILuaCallback#resume(Object[])} callback.
|
* When the current coroutine is resumed, we invoke the provided {@link ILuaCallback#resume(Object[])} callback.
|
||||||
*/
|
*/
|
||||||
public final class MethodResult {
|
public final class MethodResult
|
||||||
private static final MethodResult empty = new MethodResult(null, null);
|
{
|
||||||
|
private static final MethodResult empty = new MethodResult( null, null );
|
||||||
|
|
||||||
private final Object[] result;
|
private final Object[] result;
|
||||||
private final ILuaCallback callback;
|
private final ILuaCallback callback;
|
||||||
private final int adjust;
|
private final int adjust;
|
||||||
|
|
||||||
private MethodResult(Object[] arguments, ILuaCallback callback) {
|
private MethodResult( Object[] arguments, ILuaCallback callback )
|
||||||
this.result = arguments;
|
{
|
||||||
|
result = arguments;
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
this.adjust = 0;
|
adjust = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private MethodResult(Object[] arguments, ILuaCallback callback, int adjust) {
|
private MethodResult( Object[] arguments, ILuaCallback callback, int adjust )
|
||||||
this.result = arguments;
|
{
|
||||||
|
result = arguments;
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
this.adjust = adjust;
|
this.adjust = adjust;
|
||||||
}
|
}
|
||||||
@@ -47,25 +48,28 @@ public final class MethodResult {
|
|||||||
* @return A method result which returns immediately with no values.
|
* @return A method result which returns immediately with no values.
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public static MethodResult of() {
|
public static MethodResult of()
|
||||||
|
{
|
||||||
return empty;
|
return empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a single value immediately.
|
* Return a single value immediately.
|
||||||
*
|
*
|
||||||
* Integers, doubles, floats, strings, booleans, {@link Map}, {@link Collection}s, arrays and {@code null} will be converted to their corresponding Lua
|
* Integers, doubles, floats, strings, booleans, {@link Map}, {@link Collection}s, arrays and {@code null} will be
|
||||||
* type. {@code byte[]} and {@link ByteBuffer} will be treated as binary strings. {@link ILuaFunction} will be treated as a function.
|
* converted to their corresponding Lua type. {@code byte[]} and {@link ByteBuffer} will be treated as binary
|
||||||
|
* strings. {@link ILuaFunction} will be treated as a function.
|
||||||
*
|
*
|
||||||
* In order to provide a custom object with methods, one may return a {@link IDynamicLuaObject}, or an arbitrary class with {@link LuaFunction}
|
* In order to provide a custom object with methods, one may return a {@link IDynamicLuaObject}, or an arbitrary
|
||||||
* annotations. Anything else will be converted to {@code nil}.
|
* class with {@link LuaFunction} annotations. Anything else will be converted to {@code nil}.
|
||||||
*
|
*
|
||||||
* @param value The value to return to the calling Lua function.
|
* @param value The value to return to the calling Lua function.
|
||||||
* @return A method result which returns immediately with the given value.
|
* @return A method result which returns immediately with the given value.
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public static MethodResult of(@Nullable Object value) {
|
public static MethodResult of( @Nullable Object value )
|
||||||
return new MethodResult(new Object[] {value}, null);
|
{
|
||||||
|
return new MethodResult( new Object[] { value }, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -75,88 +79,95 @@ public final class MethodResult {
|
|||||||
* @return A method result which returns immediately with the given values.
|
* @return A method result which returns immediately with the given values.
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public static MethodResult of(@Nullable Object... values) {
|
public static MethodResult of( @Nullable Object... values )
|
||||||
return values == null || values.length == 0 ? empty : new MethodResult(values, null);
|
{
|
||||||
|
return values == null || values.length == 0 ? empty : new MethodResult( values, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wait for an event to occur on the computer, suspending the thread until it arises. This method is exactly equivalent to {@code os.pullEvent()} in
|
* Wait for an event to occur on the computer, suspending the thread until it arises. This method is exactly
|
||||||
* lua.
|
* equivalent to {@code os.pullEvent()} in lua.
|
||||||
*
|
*
|
||||||
* @param filter A specific event to wait for, or null to wait for any event.
|
* @param filter A specific event to wait for, or null to wait for any event.
|
||||||
* @param callback The callback to resume with the name of the event that occurred, and any event parameters.
|
* @param callback The callback to resume with the name of the event that occurred, and any event parameters.
|
||||||
* @return The method result which represents this yield.
|
* @return The method result which represents this yield.
|
||||||
* @see IComputerAccess#queueEvent(String, Object[])
|
* @see IComputerAccess#queueEvent(String, Object[])
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public static MethodResult pullEvent(@Nullable String filter, @Nonnull ILuaCallback callback) {
|
public static MethodResult pullEvent( @Nullable String filter, @Nonnull ILuaCallback callback )
|
||||||
Objects.requireNonNull(callback, "callback cannot be null");
|
{
|
||||||
return new MethodResult(new Object[] {filter}, results -> {
|
Objects.requireNonNull( callback, "callback cannot be null" );
|
||||||
if (results.length >= 1 && results[0].equals("terminate")) {
|
return new MethodResult( new Object[] { filter }, results -> {
|
||||||
throw new LuaException("Terminated", 0);
|
if( results.length >= 1 && Objects.equals( results[0], "terminate" ) )
|
||||||
|
{
|
||||||
|
throw new LuaException( "Terminated", 0 );
|
||||||
}
|
}
|
||||||
return callback.resume(results);
|
return callback.resume( results );
|
||||||
});
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The same as {@link #pullEvent(String, ILuaCallback)}, except "terminated" events are ignored. Only use this if you want to prevent program
|
* The same as {@link #pullEvent(String, ILuaCallback)}, except "terminated" events are ignored. Only use this if
|
||||||
* termination, which is not recommended. This method is exactly equivalent to {@code os.pullEventRaw()} in Lua.
|
* you want to prevent program termination, which is not recommended. This method is exactly equivalent to
|
||||||
|
* {@code os.pullEventRaw()} in Lua.
|
||||||
*
|
*
|
||||||
* @param filter A specific event to wait for, or null to wait for any event.
|
* @param filter A specific event to wait for, or null to wait for any event.
|
||||||
* @param callback The callback to resume with the name of the event that occurred, and any event parameters.
|
* @param callback The callback to resume with the name of the event that occurred, and any event parameters.
|
||||||
* @return The method result which represents this yield.
|
* @return The method result which represents this yield.
|
||||||
* @see #pullEvent(String, ILuaCallback)
|
* @see #pullEvent(String, ILuaCallback)
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public static MethodResult pullEventRaw(@Nullable String filter, @Nonnull ILuaCallback callback) {
|
public static MethodResult pullEventRaw( @Nullable String filter, @Nonnull ILuaCallback callback )
|
||||||
Objects.requireNonNull(callback, "callback cannot be null");
|
{
|
||||||
return new MethodResult(new Object[] {filter}, callback);
|
Objects.requireNonNull( callback, "callback cannot be null" );
|
||||||
|
return new MethodResult( new Object[] { filter }, callback );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Yield the current coroutine with some arguments until it is resumed. This method is exactly equivalent to {@code coroutine.yield()} in lua. Use
|
* Yield the current coroutine with some arguments until it is resumed. This method is exactly equivalent to
|
||||||
* {@code pullEvent()} if you wish to wait for events.
|
* {@code coroutine.yield()} in lua. Use {@code pullEvent()} if you wish to wait for events.
|
||||||
*
|
*
|
||||||
* @param arguments An object array containing the arguments to pass to coroutine.yield()
|
* @param arguments An object array containing the arguments to pass to coroutine.yield()
|
||||||
* @param callback The callback to resume with an array containing the return values from coroutine.yield()
|
* @param callback The callback to resume with an array containing the return values from coroutine.yield()
|
||||||
* @return The method result which represents this yield.
|
* @return The method result which represents this yield.
|
||||||
* @see #pullEvent(String, ILuaCallback)
|
* @see #pullEvent(String, ILuaCallback)
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public static MethodResult yield(@Nullable Object[] arguments, @Nonnull ILuaCallback callback) {
|
public static MethodResult yield( @Nullable Object[] arguments, @Nonnull ILuaCallback callback )
|
||||||
Objects.requireNonNull(callback, "callback cannot be null");
|
{
|
||||||
return new MethodResult(arguments, callback);
|
Objects.requireNonNull( callback, "callback cannot be null" );
|
||||||
|
return new MethodResult( arguments, callback );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public Object[] getResult() {
|
public Object[] getResult()
|
||||||
return this.result;
|
{
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public ILuaCallback getCallback() {
|
public ILuaCallback getCallback()
|
||||||
return this.callback;
|
{
|
||||||
|
return callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getErrorAdjust() {
|
public int getErrorAdjust()
|
||||||
return this.adjust;
|
{
|
||||||
|
return adjust;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Increase the Lua error by a specific amount. One should never need to use this function - it largely exists for some CC internal code.
|
* Increase the Lua error by a specific amount. One should never need to use this function - it largely exists for
|
||||||
|
* some CC internal code.
|
||||||
*
|
*
|
||||||
* @param adjust The amount to increase the level by.
|
* @param adjust The amount to increase the level by.
|
||||||
* @return The new {@link MethodResult} with an adjusted error. This has no effect on immediate results.
|
* @return The new {@link MethodResult} with an adjusted error. This has no effect on immediate results.
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public MethodResult adjustError(int adjust) {
|
public MethodResult adjustError( int adjust )
|
||||||
if (adjust < 0) {
|
{
|
||||||
throw new IllegalArgumentException("cannot adjust by a negative amount");
|
if( adjust < 0 ) throw new IllegalArgumentException( "cannot adjust by a negative amount" );
|
||||||
}
|
if( adjust == 0 || callback == null ) return this;
|
||||||
if (adjust == 0 || this.callback == null) {
|
return new MethodResult( result, callback, this.adjust + adjust );
|
||||||
return this;
|
|
||||||
}
|
|
||||||
return new MethodResult(this.result, this.callback, this.adjust + adjust);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user