mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-11-02 14:43:00 +00:00
Compare commits
834 Commits
v1.97.3
...
v1.18.1-1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7b3537761b | ||
|
|
6ad2cdaf62 | ||
|
|
4914ad0040 | ||
|
|
27102e6381 | ||
|
|
9083e4f97b | ||
|
|
f74a386312 | ||
|
|
ad0080ef32 | ||
|
|
a549400776 | ||
|
|
d2405ee3c3 | ||
|
|
2145d0fe14 | ||
|
|
687352572d | ||
|
|
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 | ||
|
|
7f3490591d | ||
|
|
095101831c | ||
|
|
7b7527ec80 | ||
|
|
8ffd45c66e | ||
|
|
e247bd823e | ||
|
|
276956eed8 | ||
|
|
a4c5ecf8df | ||
|
|
99de00e16e | ||
|
|
600227e481 | ||
|
|
18d66bd727 | ||
|
|
d3563a3854 | ||
|
|
c2dc8bf675 | ||
|
|
603119e1e6 | ||
|
|
d9b3f17b52 | ||
|
|
993bccc51f | ||
|
|
96d3b27064 | ||
|
|
f33f57ea35 | ||
|
|
070479d901 | ||
|
|
2fe40f669d | ||
|
|
1b39c9f470 | ||
|
|
814d5cbcd1 | ||
|
|
4d8862c78e | ||
|
|
6cc2f035db | ||
|
|
cf3f1d3d48 | ||
|
|
bca964629a | ||
|
|
ea7a218f4a | ||
|
|
544bcaa599 | ||
|
|
ab6b861cd6 | ||
|
|
72e8fc03d3 | ||
|
|
0e94355a85 | ||
|
|
482ae0d22e | ||
|
|
6dd33f7099 | ||
|
|
045472577a | ||
|
|
9f539dbd59 | ||
|
|
ca367e7cc7 | ||
|
|
f6fd0ad172 | ||
|
|
0d35331b82 | ||
|
|
076b454c8f | ||
|
|
36e0dcbad0 | ||
|
|
0b5fe990e5 | ||
|
|
29ece2a6e3 | ||
|
|
eba26dedab | ||
|
|
13779d6ad3 | ||
|
|
d700f1f500 | ||
|
|
06bf84f151 | ||
|
|
8ba20985d7 | ||
|
|
7bb7b5e638 | ||
|
|
297426419b | ||
|
|
eb61c5c5d7 | ||
|
|
cf2bc667c1 | ||
|
|
c8449086ee | ||
|
|
662bead8be | ||
|
|
acaa61a720 | ||
|
|
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 | ||
|
|
7086cb8a02 | ||
|
|
8dbc930c2f | ||
|
|
61eb67849d | ||
|
|
c2316ef256 | ||
|
|
0d22270f8b | ||
|
|
abb9c14256 | ||
|
|
815e534dc6 | ||
|
|
51dde077fe | ||
|
|
31d0b7afcd | ||
|
|
95b0d950aa | ||
|
|
efa2be2821 | ||
|
|
670db97fc7 | ||
|
|
1650b72edb | ||
|
|
a5bca3f0df | ||
|
|
88f41314c7 | ||
|
|
5ef8d52c13 | ||
|
|
0b65d56ab0 | ||
|
|
a256b70685 | ||
|
|
f16d1499fe | ||
|
|
79ca851e4f | ||
|
|
d5c54d64a6 | ||
|
|
5cfdd2339f | ||
|
|
3ab3213290 | ||
|
|
46c9840d00 | ||
|
|
b3f2f14e96 | ||
|
|
3ace49d27f | ||
|
|
9bd662d8dc | ||
|
|
df7a40354e | ||
|
|
c489d4bc4f | ||
|
|
2b029bd506 | ||
|
|
2227845658 | ||
|
|
2d3e88ef59 | ||
|
|
0bfe960cbd | ||
|
|
a735f23e1f | ||
|
|
de6f27ceaf | ||
|
|
2fab1a3054 | ||
|
|
d4745ae47e | ||
|
|
dc21e2dbc9 | ||
|
|
75dfa71275 | ||
|
|
d71bf225cc | ||
|
|
8644c4ebf6 | ||
|
|
b323db30ee | ||
|
|
53efd6b303 | ||
|
|
97faa1b3bc | ||
|
|
7404133d40 | ||
|
|
e18e24407e | ||
|
|
026afa7f73 | ||
|
|
29cc5bb86b | ||
|
|
aa9d3c8269 | ||
|
|
f8074636bc | ||
|
|
db2cde4a4c | ||
|
|
5eec7d9172 | ||
|
|
8b9735d72e | ||
|
|
1866916cb8 | ||
|
|
f38a6a9d43 | ||
|
|
0f6db63020 | ||
|
|
51fcd83b87 | ||
|
|
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 |
@@ -1,5 +1,5 @@
|
||||
image:
|
||||
file: .gitpod.Dockerfile
|
||||
file: config/gitpod/Dockerfile
|
||||
|
||||
ports:
|
||||
- port: 25565
|
||||
@@ -7,12 +7,14 @@ ports:
|
||||
|
||||
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:
|
||||
- init: ./gradlew
|
||||
- name: Setup pre-commit hool
|
||||
init: pre-commit install --config config/pre-commit/config.yml --allow-missing-config
|
||||
|
||||
@@ -7,7 +7,7 @@ plugins {
|
||||
id 'fabric-loom' version '0.10-SNAPSHOT'
|
||||
}
|
||||
|
||||
def javaVersion = JavaLanguageVersion.of(16)
|
||||
def javaVersion = JavaLanguageVersion.of(17)
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion = javaVersion
|
||||
@@ -83,8 +83,8 @@ dependencies {
|
||||
include 'com.electronwill.night-config:toml:3.6.3'
|
||||
include "me.shedaniel.cloth:cloth-config-fabric:${cloth_config_version}"
|
||||
|
||||
modRuntimeOnly "me.shedaniel:RoughlyEnoughItems-api-fabric:6.0.254-alpha"
|
||||
modRuntimeOnly "me.shedaniel:RoughlyEnoughItems-fabric:6.0.254-alpha"
|
||||
//modRuntimeOnly "me.shedaniel:RoughlyEnoughItems-api-fabric:6.0.254-alpha"
|
||||
//modRuntimeOnly "me.shedaniel:RoughlyEnoughItems-fabric:6.0.254-alpha"
|
||||
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter-params:5.7.0'
|
||||
@@ -93,7 +93,7 @@ dependencies {
|
||||
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.1'
|
||||
cctJavadoc 'cc.tweaked:cct-javadoc:1.4.2'
|
||||
}
|
||||
|
||||
processResources {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
module: [kind=event] redstone
|
||||
---
|
||||
|
||||
The @{redstone} event is fired whenever any redstone inputs on the computer change.
|
||||
The @{event!redstone} event is fired whenever any redstone inputs on the computer change.
|
||||
|
||||
## Example
|
||||
Prints a message when a redstone input changes:
|
||||
|
||||
@@ -2,14 +2,13 @@
|
||||
org.gradle.jvmargs=-Xmx1G
|
||||
|
||||
# Mod properties
|
||||
mod_version=1.97.2
|
||||
mod_version=1.99.1
|
||||
|
||||
# Minecraft properties
|
||||
mc_version=1.17.1
|
||||
fabric_api_version=0.40.1+1.17
|
||||
fabric_loader_version=0.12.0
|
||||
mc_version=1.18.1
|
||||
fabric_api_version=0.44.0+1.18
|
||||
fabric_loader_version=0.12.11
|
||||
|
||||
cloth_api_version=2.0.54
|
||||
cloth_config_version=5.0.34
|
||||
jankson_version=1.2.0
|
||||
modmenu_version=2.0.2
|
||||
cloth_config_version=6.0.42
|
||||
modmenu_version=3.0.0
|
||||
|
||||
@@ -3,12 +3,11 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft;
|
||||
|
||||
import dan200.computercraft.core.apis.http.options.Action;
|
||||
import dan200.computercraft.core.apis.http.options.AddressRule;
|
||||
import dan200.computercraft.shared.ComputerCraftRegistry.ModBlocks;
|
||||
import dan200.computercraft.shared.Registry.ModBlocks;
|
||||
import dan200.computercraft.shared.common.ColourableRecipe;
|
||||
import dan200.computercraft.shared.computer.core.ClientComputerRegistry;
|
||||
import dan200.computercraft.shared.computer.core.ServerComputerRegistry;
|
||||
@@ -37,24 +36,20 @@ import net.minecraft.world.item.ItemStack;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static dan200.computercraft.shared.ComputerCraftRegistry.init;
|
||||
import static dan200.computercraft.shared.Registry.init;
|
||||
|
||||
public final class ComputerCraft implements ModInitializer
|
||||
{
|
||||
public static final String MOD_ID = "computercraft";
|
||||
|
||||
// Configuration fields
|
||||
public static int computerSpaceLimit = 1000 * 1000;
|
||||
public static int floppySpaceLimit = 125 * 1000;
|
||||
public static int maximumFilesOpen = 128;
|
||||
public static boolean disableLua51Features = false;
|
||||
public static String defaultComputerSettings = "";
|
||||
public static boolean debugEnable = true;
|
||||
public static boolean logComputerErrors = true;
|
||||
public static boolean commandRequireCreative = true;
|
||||
|
||||
@@ -64,10 +59,11 @@ public final class ComputerCraft implements ModInitializer
|
||||
|
||||
public static boolean httpEnabled = true;
|
||||
public static boolean httpWebsocketEnabled = true;
|
||||
public static List<AddressRule> httpRules = Collections.unmodifiableList( Arrays.asList(
|
||||
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 httpMaxWebsockets = 4;
|
||||
public static int httpDownloadBandwidth = 32 * 1024 * 1024;
|
||||
@@ -80,7 +76,6 @@ public final class ComputerCraft implements ModInitializer
|
||||
public static int modemHighAltitudeRangeDuringStorm = 384;
|
||||
public static int maxNotesPerTick = 8;
|
||||
public static MonitorRenderer monitorRenderer = MonitorRenderer.BEST;
|
||||
public static double monitorDistanceSq = 4096;
|
||||
public static int monitorDistance = 65;
|
||||
public static long monitorBandwidth = 1_000_000;
|
||||
|
||||
@@ -98,6 +93,7 @@ public final class ComputerCraft implements ModInitializer
|
||||
|
||||
public static int pocketTermWidth = 26;
|
||||
public static int pocketTermHeight = 20;
|
||||
|
||||
public static int monitorWidth = 8;
|
||||
public static int monitorHeight = 6;
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft;
|
||||
|
||||
import dan200.computercraft.api.ComputerCraftAPI.IComputerCraftAPI;
|
||||
@@ -35,7 +34,6 @@ 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.MinecraftServer;
|
||||
import net.minecraft.server.packs.resources.ReloadableResourceManager;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Level;
|
||||
@@ -59,36 +57,24 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
|
||||
|
||||
public static InputStream getResourceFile( String domain, String subPath )
|
||||
{
|
||||
MinecraftServer server = GameInstanceUtils.getServer();
|
||||
if( server != null )
|
||||
ReloadableResourceManager manager = (ReloadableResourceManager) ((MinecraftServerAccess) GameInstanceUtils.getServer()).callGetResourceManager();
|
||||
try
|
||||
{
|
||||
ReloadableResourceManager manager = (ReloadableResourceManager) ((MinecraftServerAccess) server).callGetResourceManager();
|
||||
try
|
||||
{
|
||||
return manager.getResource( new ResourceLocation( domain, subPath ) )
|
||||
.getInputStream();
|
||||
}
|
||||
catch( IOException ignored )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return manager.getResource( new ResourceLocation( domain, subPath ) ).getInputStream();
|
||||
}
|
||||
catch( IOException ignored )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String getInstalledVersion()
|
||||
{
|
||||
if( version != null )
|
||||
{
|
||||
return version;
|
||||
}
|
||||
return version = FabricLoader.getInstance()
|
||||
.getModContainer( ComputerCraft.MOD_ID )
|
||||
.map( x -> x.getMetadata()
|
||||
.getVersion()
|
||||
.toString() )
|
||||
if( version != null ) return version;
|
||||
return version = FabricLoader.getInstance().getModContainer( ComputerCraft.MOD_ID )
|
||||
.map( x -> x.getMetadata().getVersion().toString() )
|
||||
.orElse( "unknown" );
|
||||
}
|
||||
|
||||
@@ -114,14 +100,9 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
|
||||
@Override
|
||||
public IMount createResourceMount( @Nonnull String domain, @Nonnull String subPath )
|
||||
{
|
||||
MinecraftServer server = GameInstanceUtils.getServer();
|
||||
if( server != null )
|
||||
{
|
||||
ReloadableResourceManager manager = (ReloadableResourceManager) ((MinecraftServerAccess) server).callGetResourceManager();
|
||||
ResourceMount mount = ResourceMount.get( domain, subPath, manager );
|
||||
return mount.exists( "" ) ? mount : null;
|
||||
}
|
||||
return null;
|
||||
ReloadableResourceManager manager = (ReloadableResourceManager) ((MinecraftServerAccess) GameInstanceUtils.getServer()).callGetResourceManager();
|
||||
ResourceMount mount = ResourceMount.get( domain, subPath, manager );
|
||||
return mount.exists( "" ) ? mount : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -130,12 +111,24 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
|
||||
Peripherals.register( provider );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerGenericSource( @Nonnull GenericSource 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 )
|
||||
{
|
||||
@@ -154,18 +147,6 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
|
||||
MediaProviders.register( provider );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerPocketUpgrade( @Nonnull IPocketUpgrade upgrade )
|
||||
{
|
||||
PocketUpgrades.register( upgrade );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerGenericSource( @Nonnull GenericSource source )
|
||||
{
|
||||
GenericMethod.register( source );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public IPacketNetwork getWirelessNetwork()
|
||||
|
||||
@@ -36,19 +36,14 @@ import javax.annotation.Nullable;
|
||||
*/
|
||||
public final class ComputerCraftAPI
|
||||
{
|
||||
public static final String MOD_ID = "computercraft";
|
||||
|
||||
@Nonnull
|
||||
public static String getInstalledVersion()
|
||||
{
|
||||
return getInstance().getInstalledVersion();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Deprecated
|
||||
public static String getAPIVersion()
|
||||
{
|
||||
return getInstalledVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a numbered directory in a subfolder of the save directory for a given world, and returns that number.
|
||||
*
|
||||
@@ -139,9 +134,9 @@ 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 recommended to call
|
||||
* this during the load() method of your mod.
|
||||
* 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.
|
||||
*
|
||||
* @param upgrade The turtle upgrade to register.
|
||||
* @see ITurtleUpgrade
|
||||
@@ -151,6 +146,19 @@ public final class ComputerCraftAPI
|
||||
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 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a bundled redstone provider to provide bundled redstone output for blocks.
|
||||
*
|
||||
@@ -188,11 +196,6 @@ public final class ComputerCraftAPI
|
||||
getInstance().registerMediaProvider( provider );
|
||||
}
|
||||
|
||||
public static void registerPocketUpgrade( @Nonnull IPocketUpgrade upgrade )
|
||||
{
|
||||
getInstance().registerPocketUpgrade( upgrade );
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to get the game-wide wireless network.
|
||||
*
|
||||
@@ -273,14 +276,13 @@ public final class ComputerCraftAPI
|
||||
|
||||
void registerTurtleUpgrade( @Nonnull ITurtleUpgrade upgrade );
|
||||
|
||||
void registerPocketUpgrade( @Nonnull IPocketUpgrade upgrade );
|
||||
|
||||
void registerBundledRedstoneProvider( @Nonnull IBundledRedstoneProvider provider );
|
||||
|
||||
int getBundledRedstoneOutput( @Nonnull Level world, @Nonnull BlockPos pos, @Nonnull Direction side );
|
||||
|
||||
void registerMediaProvider( @Nonnull IMediaProvider provider );
|
||||
|
||||
void registerPocketUpgrade( @Nonnull IPocketUpgrade upgrade );
|
||||
|
||||
@Nonnull
|
||||
IPacketNetwork getWirelessNetwork();
|
||||
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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 ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. 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.client;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
|
||||
@@ -183,6 +183,24 @@ public interface IArguments
|
||||
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.
|
||||
*
|
||||
@@ -314,6 +332,27 @@ public interface IArguments
|
||||
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.
|
||||
*
|
||||
@@ -404,4 +443,13 @@ public interface IArguments
|
||||
{
|
||||
return optTable( index ).orElse( def );
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when the current function finishes, before any main thread tasks have run.
|
||||
*
|
||||
* Called when the current function returns, and so some values are no longer guaranteed to be safe to access.
|
||||
*/
|
||||
default void releaseImmediate()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,8 +51,17 @@ public @interface LuaFunction
|
||||
* 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)
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
114
src/main/java/dan200/computercraft/api/lua/LuaTable.java
Normal file
114
src/main/java/dan200/computercraft/api/lua/LuaTable.java
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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.
|
||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||
*/
|
||||
package dan200.computercraft.api.lua;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
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" );
|
||||
}
|
||||
}
|
||||
@@ -102,6 +102,34 @@ public final class LuaValues
|
||||
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}.
|
||||
*
|
||||
|
||||
@@ -98,7 +98,10 @@ public final class MethodResult
|
||||
{
|
||||
Objects.requireNonNull( callback, "callback cannot be null" );
|
||||
return new MethodResult( new Object[] { filter }, results -> {
|
||||
if( results.length >= 1 && results[0].equals( "terminate" ) ) throw new LuaException( "Terminated", 0 );
|
||||
if( results.length >= 1 && Objects.equals( results[0], "terminate" ) )
|
||||
{
|
||||
throw new LuaException( "Terminated", 0 );
|
||||
}
|
||||
return callback.resume( results );
|
||||
} );
|
||||
}
|
||||
|
||||
@@ -5,10 +5,12 @@
|
||||
*/
|
||||
package dan200.computercraft.api.lua;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* An implementation of {@link IArguments} which wraps an array of {@link Object}.
|
||||
@@ -16,6 +18,8 @@ import java.util.Objects;
|
||||
public final class ObjectArguments implements IArguments
|
||||
{
|
||||
private static final IArguments EMPTY = new ObjectArguments();
|
||||
|
||||
private boolean released = false;
|
||||
private final List<Object> args;
|
||||
|
||||
@Deprecated
|
||||
@@ -63,4 +67,34 @@ public final class ObjectArguments implements IArguments
|
||||
{
|
||||
return args.toArray();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public LuaTable<?, ?> getTableUnsafe( int index ) throws LuaException
|
||||
{
|
||||
if( released )
|
||||
{
|
||||
throw new IllegalStateException( "Cannot use getTableUnsafe after IArguments has been released" );
|
||||
}
|
||||
|
||||
return IArguments.super.getTableUnsafe( index );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Optional<LuaTable<?, ?>> optTableUnsafe( int index ) throws LuaException
|
||||
{
|
||||
if( released )
|
||||
{
|
||||
throw new IllegalStateException( "Cannot use optTableUnsafe after IArguments has been released" );
|
||||
}
|
||||
|
||||
return IArguments.super.optTableUnsafe( index );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void releaseImmediate()
|
||||
{
|
||||
released = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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 java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class ObjectLuaTable implements LuaTable<Object, Object>
|
||||
{
|
||||
private final Map<Object, Object> map;
|
||||
|
||||
public ObjectLuaTable( Map<?, ?> map )
|
||||
{
|
||||
this.map = Collections.unmodifiableMap( map );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size()
|
||||
{
|
||||
return map.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return map.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsKey( Object o )
|
||||
{
|
||||
return map.containsKey( o );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsValue( Object o )
|
||||
{
|
||||
return map.containsKey( o );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get( Object o )
|
||||
{
|
||||
return map.get( o );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Set<Object> keySet()
|
||||
{
|
||||
return map.keySet();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Collection<Object> values()
|
||||
{
|
||||
return map.values();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Set<Entry<Object, Object>> entrySet()
|
||||
{
|
||||
return map.entrySet();
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,8 @@ import dan200.computercraft.api.lua.LuaFunction;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* The interface that defines a peripheral.
|
||||
@@ -30,6 +32,18 @@ public interface IPeripheral
|
||||
@Nonnull
|
||||
String getType();
|
||||
|
||||
/**
|
||||
* Return additional types/traits associated with this object.
|
||||
*
|
||||
* @return A collection of additional object traits.
|
||||
* @see PeripheralType#getAdditionalTypes()
|
||||
*/
|
||||
@Nonnull
|
||||
default Set<String> getAdditionalTypes()
|
||||
{
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Is called when when a computer is attaching to the peripheral.
|
||||
*
|
||||
|
||||
@@ -6,9 +6,13 @@
|
||||
package dan200.computercraft.api.peripheral;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* The type of a {@link GenericPeripheral}.
|
||||
@@ -18,13 +22,19 @@ import javax.annotation.Nullable;
|
||||
*/
|
||||
public final class PeripheralType
|
||||
{
|
||||
private static final PeripheralType UNTYPED = new PeripheralType( null );
|
||||
private static final PeripheralType UNTYPED = new PeripheralType( null, Collections.emptySet() );
|
||||
|
||||
private final String type;
|
||||
private final Set<String> additionalTypes;
|
||||
|
||||
public PeripheralType( String type )
|
||||
public PeripheralType( String type, Set<String> additionalTypes )
|
||||
{
|
||||
this.type = type;
|
||||
this.additionalTypes = additionalTypes;
|
||||
if( additionalTypes.contains( null ) )
|
||||
{
|
||||
throw new IllegalArgumentException( "All additional types must be non-null" );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -46,7 +56,55 @@ public final class PeripheralType
|
||||
public static PeripheralType ofType( @Nonnull String type )
|
||||
{
|
||||
if( Strings.isNullOrEmpty( type ) ) throw new IllegalArgumentException( "type cannot be null or empty" );
|
||||
return new PeripheralType( type );
|
||||
return new PeripheralType( type, Collections.emptySet() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new non-empty peripheral type with additional traits.
|
||||
*
|
||||
* @param type The name of the type.
|
||||
* @param additionalTypes Additional types, or "traits" of this peripheral. For instance, {@literal "inventory"}.
|
||||
* @return The constructed peripheral type.
|
||||
*/
|
||||
public static PeripheralType ofType( @Nonnull String type, Collection<String> additionalTypes )
|
||||
{
|
||||
if( Strings.isNullOrEmpty( type ) ) throw new IllegalArgumentException( "type cannot be null or empty" );
|
||||
return new PeripheralType( type, ImmutableSet.copyOf( additionalTypes ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new non-empty peripheral type with additional traits.
|
||||
*
|
||||
* @param type The name of the type.
|
||||
* @param additionalTypes Additional types, or "traits" of this peripheral. For instance, {@literal "inventory"}.
|
||||
* @return The constructed peripheral type.
|
||||
*/
|
||||
public static PeripheralType ofType( @Nonnull String type, @Nonnull String... additionalTypes )
|
||||
{
|
||||
if( Strings.isNullOrEmpty( type ) ) throw new IllegalArgumentException( "type cannot be null or empty" );
|
||||
return new PeripheralType( type, ImmutableSet.copyOf( additionalTypes ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new peripheral type with no primary type but additional traits.
|
||||
*
|
||||
* @param additionalTypes Additional types, or "traits" of this peripheral. For instance, {@literal "inventory"}.
|
||||
* @return The constructed peripheral type.
|
||||
*/
|
||||
public static PeripheralType ofAdditional( Collection<String> additionalTypes )
|
||||
{
|
||||
return new PeripheralType( null, ImmutableSet.copyOf( additionalTypes ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new peripheral type with no primary type but additional traits.
|
||||
*
|
||||
* @param additionalTypes Additional types, or "traits" of this peripheral. For instance, {@literal "inventory"}.
|
||||
* @return The constructed peripheral type.
|
||||
*/
|
||||
public static PeripheralType ofAdditional( @Nonnull String... additionalTypes )
|
||||
{
|
||||
return new PeripheralType( null, ImmutableSet.copyOf( additionalTypes ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,4 +117,15 @@ public final class PeripheralType
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get any additional types or "traits" of this peripheral. These effectively act as a standard set of interfaces
|
||||
* a peripheral might have.
|
||||
*
|
||||
* @return All additional types.
|
||||
*/
|
||||
public Set<String> getAdditionalTypes()
|
||||
{
|
||||
return additionalTypes;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
package dan200.computercraft.api.pocket;
|
||||
|
||||
import dan200.computercraft.api.ComputerCraftAPI;
|
||||
import dan200.computercraft.api.IUpgradeBase;
|
||||
import dan200.computercraft.api.upgrades.IUpgradeBase;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import net.minecraft.world.level.Level;
|
||||
|
||||
|
||||
@@ -3,18 +3,13 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. 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.turtle;
|
||||
|
||||
import dan200.computercraft.shared.util.NonNullSupplier;
|
||||
import net.minecraft.Util;
|
||||
import dan200.computercraft.api.upgrades.IUpgradeBase;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* A base class for {@link ITurtleUpgrade}s.
|
||||
@@ -26,9 +21,9 @@ public abstract class AbstractTurtleUpgrade implements ITurtleUpgrade
|
||||
private final ResourceLocation id;
|
||||
private final TurtleUpgradeType type;
|
||||
private final String adjective;
|
||||
private final NonNullSupplier<ItemStack> stack;
|
||||
private final ItemStack stack;
|
||||
|
||||
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, String adjective, NonNullSupplier<ItemStack> stack )
|
||||
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, String adjective, ItemStack stack )
|
||||
{
|
||||
this.id = id;
|
||||
this.type = type;
|
||||
@@ -36,39 +31,9 @@ public abstract class AbstractTurtleUpgrade implements ITurtleUpgrade
|
||||
this.stack = stack;
|
||||
}
|
||||
|
||||
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, NonNullSupplier<ItemStack> stack )
|
||||
{
|
||||
this( id, type, Util.makeDescriptionId( "upgrade", id ) + ".adjective", stack );
|
||||
}
|
||||
|
||||
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, String adjective, ItemStack stack )
|
||||
{
|
||||
this( id, type, adjective, () -> stack );
|
||||
}
|
||||
|
||||
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, ItemStack stack )
|
||||
{
|
||||
this( id, type, () -> stack );
|
||||
}
|
||||
|
||||
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, String adjective, ItemLike item )
|
||||
{
|
||||
this( id, type, adjective, new CachedStack( () -> item ) );
|
||||
}
|
||||
|
||||
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, ItemLike item )
|
||||
{
|
||||
this( id, type, new CachedStack( () -> item ) );
|
||||
}
|
||||
|
||||
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, String adjective, Supplier<? extends ItemLike> item )
|
||||
{
|
||||
this( id, type, adjective, new CachedStack( item ) );
|
||||
}
|
||||
|
||||
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, Supplier<? extends ItemLike> item )
|
||||
{
|
||||
this( id, type, new CachedStack( item ) );
|
||||
this( id, type, IUpgradeBase.getDefaultAdjective( id ), stack );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@@ -96,32 +61,6 @@ public abstract class AbstractTurtleUpgrade implements ITurtleUpgrade
|
||||
@Override
|
||||
public final ItemStack getCraftingItem()
|
||||
{
|
||||
return stack.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* A supplier which converts an item into an item stack.
|
||||
*
|
||||
* Constructing item stacks is somewhat expensive due to attaching capabilities. We cache it if given a consistent item.
|
||||
*/
|
||||
private static final class CachedStack implements NonNullSupplier<ItemStack>
|
||||
{
|
||||
private final Supplier<? extends ItemLike> provider;
|
||||
private Item item;
|
||||
private ItemStack stack;
|
||||
|
||||
CachedStack( Supplier<? extends ItemLike> provider )
|
||||
{
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ItemStack get()
|
||||
{
|
||||
Item item = provider.get().asItem();
|
||||
if( item == this.item && stack != null ) return stack;
|
||||
return stack = new ItemStack( this.item = item );
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,7 +253,7 @@ public class FakePlayer extends ServerPlayer
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trackChunk( ChunkPos chunkPos, Packet<?> packet, Packet<?> packet2 )
|
||||
public void trackChunk( ChunkPos chunkPos, Packet<?> packet )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
package dan200.computercraft.api.turtle;
|
||||
|
||||
import dan200.computercraft.api.ComputerCraftAPI;
|
||||
import dan200.computercraft.api.IUpgradeBase;
|
||||
import dan200.computercraft.api.upgrades.IUpgradeBase;
|
||||
import dan200.computercraft.api.client.TransformedModel;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import net.fabricmc.api.EnvType;
|
||||
|
||||
@@ -3,10 +3,11 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. 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;
|
||||
package dan200.computercraft.api.upgrades;
|
||||
|
||||
import dan200.computercraft.api.pocket.IPocketUpgrade;
|
||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
@@ -81,4 +82,18 @@ public interface IUpgradeBase
|
||||
if( craftingShareTag == null ) return shareTag.isEmpty();
|
||||
return shareTag.equals( craftingShareTag );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a suitable default unlocalised adjective for an upgrade ID. This converts "modid:some_upgrade" to
|
||||
* "upgrade.modid.some_upgrade.adjective".
|
||||
*
|
||||
* @param id The upgrade ID.
|
||||
* @return The generated adjective.
|
||||
* @see #getUnlocalisedAdjective()
|
||||
*/
|
||||
@Nonnull
|
||||
static String getDefaultAdjective( @Nonnull ResourceLocation id )
|
||||
{
|
||||
return Util.makeDescriptionId( "upgrade", id ) + ".adjective";
|
||||
}
|
||||
}
|
||||
@@ -3,11 +3,10 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.shared.ComputerCraftRegistry;
|
||||
import dan200.computercraft.shared.Registry;
|
||||
import dan200.computercraft.shared.common.IColouredItem;
|
||||
import dan200.computercraft.shared.media.items.ItemDisk;
|
||||
import dan200.computercraft.shared.media.items.ItemTreasureDisk;
|
||||
@@ -34,6 +33,7 @@ import java.util.function.Consumer;
|
||||
public final class ClientRegistry
|
||||
{
|
||||
private static final String[] EXTRA_MODELS = new String[] {
|
||||
// Turtle upgrades
|
||||
"turtle_modem_normal_off_left",
|
||||
"turtle_modem_normal_on_left",
|
||||
"turtle_modem_normal_off_right",
|
||||
@@ -49,6 +49,7 @@ public final class ClientRegistry
|
||||
"turtle_speaker_upgrade_left",
|
||||
"turtle_speaker_upgrade_right",
|
||||
|
||||
// Turtle block renderer
|
||||
"turtle_colour",
|
||||
"turtle_elf_overlay",
|
||||
};
|
||||
@@ -85,10 +86,10 @@ public final class ClientRegistry
|
||||
{
|
||||
ColorProviderRegistry.ITEM.register( ( stack, layer ) -> {
|
||||
return layer == 1 ? ((ItemDisk) stack.getItem()).getColour( stack ) : 0xFFFFFF;
|
||||
}, ComputerCraftRegistry.ModItems.DISK );
|
||||
}, Registry.ModItems.DISK );
|
||||
|
||||
ColorProviderRegistry.ITEM.register( ( stack, layer ) -> layer == 1 ? ItemTreasureDisk.getColour( stack ) : 0xFFFFFF,
|
||||
ComputerCraftRegistry.ModItems.TREASURE_DISK );
|
||||
Registry.ModItems.TREASURE_DISK );
|
||||
|
||||
ColorProviderRegistry.ITEM.register( ( stack, layer ) -> {
|
||||
switch( layer )
|
||||
@@ -102,12 +103,12 @@ public final class ClientRegistry
|
||||
int light = ItemPocketComputer.getLightState( stack );
|
||||
return light == -1 ? Colour.BLACK.getHex() : light;
|
||||
}
|
||||
}, ComputerCraftRegistry.ModItems.POCKET_COMPUTER_NORMAL, ComputerCraftRegistry.ModItems.POCKET_COMPUTER_ADVANCED );
|
||||
}, Registry.ModItems.POCKET_COMPUTER_NORMAL, Registry.ModItems.POCKET_COMPUTER_ADVANCED );
|
||||
|
||||
// Setup turtle colours
|
||||
ColorProviderRegistry.ITEM.register( ( stack, tintIndex ) -> tintIndex == 0 ? ((IColouredItem) stack.getItem()).getColour( stack ) : 0xFFFFFF,
|
||||
ComputerCraftRegistry.ModBlocks.TURTLE_NORMAL,
|
||||
ComputerCraftRegistry.ModBlocks.TURTLE_ADVANCED );
|
||||
Registry.ModBlocks.TURTLE_NORMAL,
|
||||
Registry.ModBlocks.TURTLE_ADVANCED );
|
||||
}
|
||||
|
||||
private static BakedModel bake( ModelBakery loader, UnbakedModel model, ResourceLocation identifier )
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client;
|
||||
|
||||
import dan200.computercraft.fabric.mixin.ChatComponentAccess;
|
||||
@@ -25,17 +24,19 @@ public class ClientTableFormatter implements TableFormatter
|
||||
{
|
||||
public static final ClientTableFormatter INSTANCE = new ClientTableFormatter();
|
||||
|
||||
private static Int2IntOpenHashMap lastHeights = new Int2IntOpenHashMap();
|
||||
private static final Int2IntOpenHashMap lastHeights = new Int2IntOpenHashMap();
|
||||
|
||||
private static Font renderer()
|
||||
{
|
||||
return Minecraft.getInstance().font;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Component getPadding( Component component, int width )
|
||||
{
|
||||
int extraWidth = width - getWidth( component );
|
||||
if( extraWidth <= 0 )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if( extraWidth <= 0 ) return null;
|
||||
|
||||
Font renderer = renderer();
|
||||
|
||||
@@ -46,11 +47,6 @@ public class ClientTableFormatter implements TableFormatter
|
||||
return ChatHelpers.coloured( StringUtils.repeat( ' ', spaces ) + StringUtils.repeat( (char) 712, extra ), ChatFormatting.GRAY );
|
||||
}
|
||||
|
||||
private static Font renderer()
|
||||
{
|
||||
return Minecraft.getInstance().font;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColumnPadding()
|
||||
{
|
||||
@@ -71,7 +67,7 @@ public class ClientTableFormatter implements TableFormatter
|
||||
|
||||
// TODO: Trim the text if it goes over the allowed length
|
||||
// int maxWidth = MathHelper.floor( chat.getChatWidth() / chat.getScale() );
|
||||
// List<ITextProperties> list = RenderComponentsUtil.func_238505_a_( component, maxWidth, mc.fontRenderer );
|
||||
// List<ITextProperties> list = RenderComponentsUtil.wrapComponents( component, maxWidth, mc.fontRenderer );
|
||||
// if( !list.isEmpty() ) chat.printChatMessageWithOptionalDeletion( list.get( 0 ), id );
|
||||
((ChatComponentAccess) chat).callAddMessage( component, id );
|
||||
}
|
||||
@@ -86,10 +82,7 @@ public class ClientTableFormatter implements TableFormatter
|
||||
int height = TableFormatter.super.display( table );
|
||||
lastHeights.put( table.getId(), height );
|
||||
|
||||
for( int i = height; i < lastHeight; i++ )
|
||||
{
|
||||
((ChatComponentAccess) chat).callRemoveById( i + table.getId() );
|
||||
}
|
||||
for( int i = height; i < lastHeight; i++ ) ((ChatComponentAccess) chat).callRemoveById( i + table.getId() );
|
||||
return height;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client;
|
||||
|
||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
||||
|
||||
@@ -8,6 +8,7 @@ package dan200.computercraft.client.gui;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.client.gui.widgets.ComputerSidebar;
|
||||
import dan200.computercraft.client.gui.widgets.DynamicImageButton;
|
||||
import dan200.computercraft.client.gui.widgets.WidgetTerminal;
|
||||
import dan200.computercraft.shared.computer.core.ClientComputer;
|
||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||
@@ -36,7 +37,6 @@ import java.util.List;
|
||||
|
||||
public abstract class ComputerScreenBase<T extends ContainerComputerBase> extends AbstractContainerScreen<T>
|
||||
{
|
||||
|
||||
private static final Component OK = new TranslatableComponent( "gui.ok" );
|
||||
private static final Component CANCEL = new TranslatableComponent( "gui.cancel" );
|
||||
private static final Component OVERWRITE = new TranslatableComponent( "gui.computercraft.upload.overwrite_button" );
|
||||
@@ -94,6 +94,7 @@ public abstract class ComputerScreenBase<T extends ContainerComputerBase> extend
|
||||
return super.keyPressed( key, scancode, modifiers );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final void render( @Nonnull PoseStack stack, int mouseX, int mouseY, float partialTicks )
|
||||
{
|
||||
@@ -102,12 +103,24 @@ public abstract class ComputerScreenBase<T extends ContainerComputerBase> extend
|
||||
renderTooltip( stack, mouseX, mouseY );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked( double x, double y, int button )
|
||||
{
|
||||
boolean changed = super.mouseClicked( x, y, button );
|
||||
// Clicking the terminate/shutdown button steals focus, which means then pressing "enter" will click the button
|
||||
// again. Restore the focus to the terminal in these cases.
|
||||
if( getFocused() instanceof DynamicImageButton ) setFocused( terminal );
|
||||
return changed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean mouseDragged( double x, double y, int button, double deltaX, double deltaY )
|
||||
{
|
||||
return getFocused() != null && getFocused().mouseDragged( x, y, button, deltaX, deltaY ) || super.mouseDragged( x, y, button, deltaX, deltaY );
|
||||
return (getFocused() != null && getFocused().mouseDragged( x, y, button, deltaX, deltaY ))
|
||||
|| super.mouseDragged( x, y, button, deltaX, deltaY );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void renderLabels( @Nonnull PoseStack transform, int mouseX, int mouseY )
|
||||
{
|
||||
@@ -207,7 +220,7 @@ public abstract class ComputerScreenBase<T extends ContainerComputerBase> extend
|
||||
|
||||
private void continueUpload()
|
||||
{
|
||||
if( minecraft.screen instanceof OptionScreen ) ((OptionScreen) minecraft.screen).disable();
|
||||
if( minecraft.screen instanceof OptionScreen screen ) screen.disable();
|
||||
NetworkHandler.sendToServer( new ContinueUploadMessage( computer.getInstanceID(), true ) );
|
||||
}
|
||||
|
||||
@@ -224,5 +237,4 @@ public abstract class ComputerScreenBase<T extends ContainerComputerBase> extend
|
||||
() -> minecraft.setScreen( this )
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,19 +3,17 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client.gui;
|
||||
|
||||
import com.mojang.blaze3d.vertex.Tesselator;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import com.mojang.math.Matrix4f;
|
||||
import com.mojang.math.Transformation;
|
||||
import dan200.computercraft.client.FrameInfo;
|
||||
import dan200.computercraft.client.render.RenderTypes;
|
||||
import dan200.computercraft.core.terminal.Terminal;
|
||||
import dan200.computercraft.core.terminal.TextBuffer;
|
||||
import dan200.computercraft.shared.util.Colour;
|
||||
import dan200.computercraft.shared.util.Palette;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
@@ -24,25 +22,138 @@ import javax.annotation.Nullable;
|
||||
|
||||
import static dan200.computercraft.client.render.RenderTypes.FULL_BRIGHT_LIGHTMAP;
|
||||
|
||||
/**
|
||||
* Handles rendering fixed width text and computer terminals.
|
||||
*
|
||||
* This class has several modes of usage:
|
||||
* <ul>
|
||||
* <li>{@link #drawString}: Drawing basic text without a terminal (such as for printouts). Unlike the other methods,
|
||||
* this accepts a lightmap coordinate as, unlike terminals, printed pages render fullbright.</li>
|
||||
* <li>{@link #drawTerminalWithoutCursor}/{@link #drawCursor}: Draw a terminal without a cursor and then draw the cursor
|
||||
* separately. This is used by the monitor renderer to render the terminal to a VBO and draw the cursor dynamically.
|
||||
* </li>
|
||||
* <li>{@link #drawTerminal}: Draw a terminal with a cursor. This is used by the various computer GUIs to render the
|
||||
* whole term.</li>
|
||||
* <li>{@link #drawBlocker}: When rendering a terminal using {@link RenderTypes#TERMINAL_WITHOUT_DEPTH} you need to
|
||||
* render an additional "depth blocker" on top of the monitor.</li>
|
||||
* </ul>
|
||||
*/
|
||||
public final class FixedWidthFontRenderer
|
||||
{
|
||||
public static final ResourceLocation FONT = new ResourceLocation( "computercraft", "textures/gui/term_font.png" );
|
||||
|
||||
public static final int FONT_HEIGHT = 9;
|
||||
public static final int FONT_WIDTH = 6;
|
||||
public static final float WIDTH = 256.0f;
|
||||
|
||||
public static final float BACKGROUND_START = (WIDTH - 6.0f) / WIDTH;
|
||||
public static final float BACKGROUND_END = (WIDTH - 4.0f) / WIDTH;
|
||||
private static final Matrix4f IDENTITY = Transformation.identity()
|
||||
.getMatrix();
|
||||
public static final ResourceLocation FONT = new ResourceLocation( "computercraft", "textures/gui/term_font.png" );
|
||||
|
||||
|
||||
private FixedWidthFontRenderer()
|
||||
{
|
||||
}
|
||||
|
||||
public static void drawString( @Nonnull Matrix4f transform, @Nonnull VertexConsumer renderer, float x, float y, @Nonnull TextBuffer text,
|
||||
@Nonnull TextBuffer textColour, @Nullable TextBuffer backgroundColour, @Nonnull Palette palette, boolean greyscale,
|
||||
float leftMarginSize, float rightMarginSize, int light )
|
||||
public static float toGreyscale( double[] rgb )
|
||||
{
|
||||
return (float) ((rgb[0] + rgb[1] + rgb[2]) / 3);
|
||||
}
|
||||
|
||||
public static int getColour( char c, Colour def )
|
||||
{
|
||||
return 15 - Terminal.getColour( c, def );
|
||||
}
|
||||
|
||||
private static void drawChar( Matrix4f transform, VertexConsumer buffer, float x, float y, int index, float r, float g, float b, int light )
|
||||
{
|
||||
// Short circuit to avoid the common case - the texture should be blank here after all.
|
||||
if( index == '\0' || index == ' ' ) return;
|
||||
|
||||
int column = index % 16;
|
||||
int row = index / 16;
|
||||
|
||||
int xStart = 1 + column * (FONT_WIDTH + 2);
|
||||
int yStart = 1 + row * (FONT_HEIGHT + 2);
|
||||
|
||||
buffer.vertex( transform, x, y, 0f ).color( r, g, b, 1.0f ).uv( xStart / WIDTH, yStart / WIDTH ).uv2( light ).endVertex();
|
||||
buffer.vertex( transform, x, y + FONT_HEIGHT, 0f ).color( r, g, b, 1.0f ).uv( xStart / WIDTH, (yStart + FONT_HEIGHT) / WIDTH ).uv2( light ).endVertex();
|
||||
buffer.vertex( transform, x + FONT_WIDTH, y, 0f ).color( r, g, b, 1.0f ).uv( (xStart + FONT_WIDTH) / WIDTH, yStart / WIDTH ).uv2( light ).endVertex();
|
||||
buffer.vertex( transform, x + FONT_WIDTH, y, 0f ).color( r, g, b, 1.0f ).uv( (xStart + FONT_WIDTH) / WIDTH, yStart / WIDTH ).uv2( light ).endVertex();
|
||||
buffer.vertex( transform, x, y + FONT_HEIGHT, 0f ).color( r, g, b, 1.0f ).uv( xStart / WIDTH, (yStart + FONT_HEIGHT) / WIDTH ).uv2( light ).endVertex();
|
||||
buffer.vertex( transform, x + FONT_WIDTH, y + FONT_HEIGHT, 0f ).color( r, g, b, 1.0f ).uv( (xStart + FONT_WIDTH) / WIDTH, (yStart + FONT_HEIGHT) / WIDTH ).uv2( light ).endVertex();
|
||||
}
|
||||
|
||||
private static void drawQuad( Matrix4f transform, VertexConsumer buffer, float x, float y, float width, float height, float r, float g, float b )
|
||||
{
|
||||
buffer.vertex( transform, x, y, 0 ).color( r, g, b, 1.0f ).uv( BACKGROUND_START, BACKGROUND_START ).endVertex();
|
||||
buffer.vertex( transform, x, y + height, 0 ).color( r, g, b, 1.0f ).uv( BACKGROUND_START, BACKGROUND_END ).endVertex();
|
||||
buffer.vertex( transform, x + width, y, 0 ).color( r, g, b, 1.0f ).uv( BACKGROUND_END, BACKGROUND_START ).endVertex();
|
||||
buffer.vertex( transform, x + width, y, 0 ).color( r, g, b, 1.0f ).uv( BACKGROUND_END, BACKGROUND_START ).endVertex();
|
||||
buffer.vertex( transform, x, y + height, 0 ).color( r, g, b, 1.0f ).uv( BACKGROUND_START, BACKGROUND_END ).endVertex();
|
||||
buffer.vertex( transform, x + width, y + height, 0 ).color( r, g, b, 1.0f ).uv( BACKGROUND_END, BACKGROUND_END ).endVertex();
|
||||
}
|
||||
|
||||
private static void drawQuad( Matrix4f transform, VertexConsumer buffer, float x, float y, float width, float height, Palette palette, boolean greyscale, char colourIndex )
|
||||
{
|
||||
double[] colour = palette.getColour( getColour( colourIndex, Colour.BLACK ) );
|
||||
float r, g, b;
|
||||
if( greyscale )
|
||||
{
|
||||
r = g = b = toGreyscale( colour );
|
||||
}
|
||||
else
|
||||
{
|
||||
r = (float) colour[0];
|
||||
g = (float) colour[1];
|
||||
b = (float) colour[2];
|
||||
}
|
||||
|
||||
drawQuad( transform, buffer, x, y, width, height, r, g, b );
|
||||
}
|
||||
|
||||
private static void drawBackground(
|
||||
@Nonnull Matrix4f transform, @Nonnull VertexConsumer renderer, float x, float y,
|
||||
@Nonnull TextBuffer backgroundColour, @Nonnull Palette palette, boolean greyscale,
|
||||
float leftMarginSize, float rightMarginSize, float height
|
||||
)
|
||||
{
|
||||
if( leftMarginSize > 0 )
|
||||
{
|
||||
drawQuad( transform, renderer, x - leftMarginSize, y, leftMarginSize, height, palette, greyscale, backgroundColour.charAt( 0 ) );
|
||||
}
|
||||
|
||||
if( rightMarginSize > 0 )
|
||||
{
|
||||
drawQuad( transform, renderer, x + backgroundColour.length() * FONT_WIDTH, y, rightMarginSize, height, palette, greyscale, backgroundColour.charAt( backgroundColour.length() - 1 ) );
|
||||
}
|
||||
|
||||
// Batch together runs of identical background cells.
|
||||
int blockStart = 0;
|
||||
char blockColour = '\0';
|
||||
for( int i = 0; i < backgroundColour.length(); i++ )
|
||||
{
|
||||
char colourIndex = backgroundColour.charAt( i );
|
||||
if( colourIndex == blockColour ) continue;
|
||||
|
||||
if( blockColour != '\0' )
|
||||
{
|
||||
drawQuad( transform, renderer, x + blockStart * FONT_WIDTH, y, FONT_WIDTH * (i - blockStart), height, palette, greyscale, blockColour );
|
||||
}
|
||||
|
||||
blockColour = colourIndex;
|
||||
blockStart = i;
|
||||
}
|
||||
|
||||
if( blockColour != '\0' )
|
||||
{
|
||||
drawQuad( transform, renderer, x + blockStart * FONT_WIDTH, y, FONT_WIDTH * (backgroundColour.length() - blockStart), height, palette, greyscale, blockColour );
|
||||
}
|
||||
}
|
||||
|
||||
public static void drawString(
|
||||
@Nonnull Matrix4f transform, @Nonnull VertexConsumer renderer, float x, float y,
|
||||
@Nonnull TextBuffer text, @Nonnull TextBuffer textColour, @Nullable TextBuffer backgroundColour,
|
||||
@Nonnull Palette palette, boolean greyscale, float leftMarginSize, float rightMarginSize, int light
|
||||
)
|
||||
{
|
||||
if( backgroundColour != null )
|
||||
{
|
||||
@@ -66,223 +177,49 @@ public final class FixedWidthFontRenderer
|
||||
|
||||
// Draw char
|
||||
int index = text.charAt( i );
|
||||
if( index > 255 )
|
||||
{
|
||||
index = '?';
|
||||
}
|
||||
if( index > 255 ) index = '?';
|
||||
drawChar( transform, renderer, x + i * FONT_WIDTH, y, index, r, g, b, light );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void drawBackground( @Nonnull Matrix4f transform, @Nonnull VertexConsumer renderer, float x, float y,
|
||||
@Nonnull TextBuffer backgroundColour, @Nonnull Palette palette, boolean greyscale, float leftMarginSize,
|
||||
float rightMarginSize, float height )
|
||||
{
|
||||
if( leftMarginSize > 0 )
|
||||
{
|
||||
drawQuad( transform, renderer, x - leftMarginSize, y, leftMarginSize, height, palette, greyscale, backgroundColour.charAt( 0 ) );
|
||||
}
|
||||
|
||||
if( rightMarginSize > 0 )
|
||||
{
|
||||
drawQuad( transform,
|
||||
renderer,
|
||||
x + backgroundColour.length() * FONT_WIDTH,
|
||||
y,
|
||||
rightMarginSize,
|
||||
height,
|
||||
palette,
|
||||
greyscale,
|
||||
backgroundColour.charAt( backgroundColour.length() - 1 ) );
|
||||
}
|
||||
|
||||
// Batch together runs of identical background cells.
|
||||
int blockStart = 0;
|
||||
char blockColour = '\0';
|
||||
for( int i = 0; i < backgroundColour.length(); i++ )
|
||||
{
|
||||
char colourIndex = backgroundColour.charAt( i );
|
||||
if( colourIndex == blockColour )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if( blockColour != '\0' )
|
||||
{
|
||||
drawQuad( transform, renderer, x + blockStart * FONT_WIDTH, y, FONT_WIDTH * (i - blockStart), height, palette, greyscale, blockColour );
|
||||
}
|
||||
|
||||
blockColour = colourIndex;
|
||||
blockStart = i;
|
||||
}
|
||||
|
||||
if( blockColour != '\0' )
|
||||
{
|
||||
drawQuad( transform,
|
||||
renderer,
|
||||
x + blockStart * FONT_WIDTH,
|
||||
y,
|
||||
FONT_WIDTH * (backgroundColour.length() - blockStart),
|
||||
height,
|
||||
palette,
|
||||
greyscale,
|
||||
blockColour );
|
||||
}
|
||||
}
|
||||
|
||||
public static int getColour( char c, Colour def )
|
||||
{
|
||||
return 15 - Terminal.getColour( c, def );
|
||||
}
|
||||
|
||||
public static float toGreyscale( double[] rgb )
|
||||
{
|
||||
return (float) ((rgb[0] + rgb[1] + rgb[2]) / 3);
|
||||
}
|
||||
|
||||
private static void drawChar( Matrix4f transform, VertexConsumer buffer, float x, float y, int index, float r, float g, float b, int light )
|
||||
{
|
||||
// Short circuit to avoid the common case - the texture should be blank here after all.
|
||||
if( index == '\0' || index == ' ' )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int column = index % 16;
|
||||
int row = index / 16;
|
||||
|
||||
int xStart = 1 + column * (FONT_WIDTH + 2);
|
||||
int yStart = 1 + row * (FONT_HEIGHT + 2);
|
||||
|
||||
buffer.vertex( transform, x, y, 0f )
|
||||
.color( r, g, b, 1.0f )
|
||||
.uv( xStart / WIDTH, yStart / WIDTH )
|
||||
.uv2( light )
|
||||
.endVertex();
|
||||
buffer.vertex( transform, x, y + FONT_HEIGHT, 0f )
|
||||
.color( r, g, b, 1.0f )
|
||||
.uv( xStart / WIDTH, (yStart + FONT_HEIGHT) / WIDTH )
|
||||
.uv2( light )
|
||||
.endVertex();
|
||||
buffer.vertex( transform, x + FONT_WIDTH, y, 0f )
|
||||
.color( r, g, b, 1.0f )
|
||||
.uv( (xStart + FONT_WIDTH) / WIDTH, yStart / WIDTH )
|
||||
.uv2( light )
|
||||
.endVertex();
|
||||
buffer.vertex( transform, x + FONT_WIDTH, y, 0f )
|
||||
.color( r, g, b, 1.0f )
|
||||
.uv( (xStart + FONT_WIDTH) / WIDTH, yStart / WIDTH )
|
||||
.uv2( light )
|
||||
.endVertex();
|
||||
buffer.vertex( transform, x, y + FONT_HEIGHT, 0f )
|
||||
.color( r, g, b, 1.0f )
|
||||
.uv( xStart / WIDTH, (yStart + FONT_HEIGHT) / WIDTH )
|
||||
.uv2( light )
|
||||
.endVertex();
|
||||
buffer.vertex( transform, x + FONT_WIDTH, y + FONT_HEIGHT, 0f )
|
||||
.color( r, g, b, 1.0f )
|
||||
.uv( (xStart + FONT_WIDTH) / WIDTH, (yStart + FONT_HEIGHT) / WIDTH )
|
||||
.uv2( light )
|
||||
.endVertex();
|
||||
}
|
||||
|
||||
private static void drawQuad( Matrix4f transform, VertexConsumer buffer, float x, float y, float width, float height, Palette palette,
|
||||
boolean greyscale, char colourIndex )
|
||||
{
|
||||
double[] colour = palette.getColour( getColour( colourIndex, Colour.BLACK ) );
|
||||
float r, g, b;
|
||||
if( greyscale )
|
||||
{
|
||||
r = g = b = toGreyscale( colour );
|
||||
}
|
||||
else
|
||||
{
|
||||
r = (float) colour[0];
|
||||
g = (float) colour[1];
|
||||
b = (float) colour[2];
|
||||
}
|
||||
|
||||
drawQuad( transform, buffer, x, y, width, height, r, g, b );
|
||||
}
|
||||
|
||||
private static void drawQuad( Matrix4f transform, VertexConsumer buffer, float x, float y, float width, float height, float r, float g, float b )
|
||||
{
|
||||
buffer.vertex( transform, x, y, 0 )
|
||||
.color( r, g, b, 1.0f )
|
||||
.uv( BACKGROUND_START, BACKGROUND_START )
|
||||
.endVertex();
|
||||
buffer.vertex( transform, x, y + height, 0 )
|
||||
.color( r, g, b, 1.0f )
|
||||
.uv( BACKGROUND_START, BACKGROUND_END )
|
||||
.endVertex();
|
||||
buffer.vertex( transform, x + width, y, 0 )
|
||||
.color( r, g, b, 1.0f )
|
||||
.uv( BACKGROUND_END, BACKGROUND_START )
|
||||
.endVertex();
|
||||
buffer.vertex( transform, x + width, y, 0 )
|
||||
.color( r, g, b, 1.0f )
|
||||
.uv( BACKGROUND_END, BACKGROUND_START )
|
||||
.endVertex();
|
||||
buffer.vertex( transform, x, y + height, 0 )
|
||||
.color( r, g, b, 1.0f )
|
||||
.uv( BACKGROUND_START, BACKGROUND_END )
|
||||
.endVertex();
|
||||
buffer.vertex( transform, x + width, y + height, 0 )
|
||||
.color( r, g, b, 1.0f )
|
||||
.uv( BACKGROUND_END, BACKGROUND_END )
|
||||
.endVertex();
|
||||
}
|
||||
|
||||
public static void drawTerminalWithoutCursor( @Nonnull Matrix4f transform, @Nonnull VertexConsumer buffer, float x, float y,
|
||||
@Nonnull Terminal terminal, boolean greyscale, float topMarginSize, float bottomMarginSize,
|
||||
float leftMarginSize, float rightMarginSize )
|
||||
public static void drawTerminalWithoutCursor(
|
||||
@Nonnull Matrix4f transform, @Nonnull VertexConsumer buffer, float x, float y,
|
||||
@Nonnull Terminal terminal, boolean greyscale,
|
||||
float topMarginSize, float bottomMarginSize, float leftMarginSize, float rightMarginSize
|
||||
)
|
||||
{
|
||||
Palette palette = terminal.getPalette();
|
||||
int height = terminal.getHeight();
|
||||
|
||||
// Top and bottom margins
|
||||
drawBackground( transform,
|
||||
buffer,
|
||||
x,
|
||||
y - topMarginSize,
|
||||
terminal.getBackgroundColourLine( 0 ),
|
||||
palette,
|
||||
greyscale,
|
||||
leftMarginSize,
|
||||
rightMarginSize,
|
||||
topMarginSize );
|
||||
drawBackground(
|
||||
transform, buffer, x, y - topMarginSize,
|
||||
terminal.getBackgroundColourLine( 0 ), palette, greyscale,
|
||||
leftMarginSize, rightMarginSize, topMarginSize
|
||||
);
|
||||
|
||||
drawBackground( transform,
|
||||
buffer,
|
||||
x,
|
||||
y + height * FONT_HEIGHT,
|
||||
terminal.getBackgroundColourLine( height - 1 ),
|
||||
palette,
|
||||
greyscale,
|
||||
leftMarginSize,
|
||||
rightMarginSize,
|
||||
bottomMarginSize );
|
||||
drawBackground(
|
||||
transform, buffer, x, y + height * FONT_HEIGHT,
|
||||
terminal.getBackgroundColourLine( height - 1 ), palette, greyscale,
|
||||
leftMarginSize, rightMarginSize, bottomMarginSize
|
||||
);
|
||||
|
||||
// The main text
|
||||
for( int i = 0; i < height; i++ )
|
||||
{
|
||||
drawString( transform,
|
||||
buffer,
|
||||
x,
|
||||
y + FixedWidthFontRenderer.FONT_HEIGHT * i,
|
||||
terminal.getLine( i ),
|
||||
terminal.getTextColourLine( i ),
|
||||
terminal.getBackgroundColourLine( i ),
|
||||
palette,
|
||||
greyscale,
|
||||
leftMarginSize,
|
||||
rightMarginSize, FULL_BRIGHT_LIGHTMAP );
|
||||
drawString(
|
||||
transform, buffer, x, y + FixedWidthFontRenderer.FONT_HEIGHT * i,
|
||||
terminal.getLine( i ), terminal.getTextColourLine( i ), terminal.getBackgroundColourLine( i ),
|
||||
palette, greyscale, leftMarginSize, rightMarginSize, FULL_BRIGHT_LIGHTMAP
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static void drawCursor( @Nonnull Matrix4f transform, @Nonnull VertexConsumer buffer, float x, float y, @Nonnull Terminal terminal,
|
||||
boolean greyscale )
|
||||
public static void drawCursor(
|
||||
@Nonnull Matrix4f transform, @Nonnull VertexConsumer buffer, float x, float y,
|
||||
@Nonnull Terminal terminal, boolean greyscale
|
||||
)
|
||||
{
|
||||
Palette palette = terminal.getPalette();
|
||||
int width = terminal.getWidth();
|
||||
@@ -309,52 +246,40 @@ public final class FixedWidthFontRenderer
|
||||
}
|
||||
}
|
||||
|
||||
public static void drawTerminal( @Nonnull Matrix4f transform, @Nonnull VertexConsumer buffer, float x, float y, @Nonnull Terminal terminal,
|
||||
boolean greyscale, float topMarginSize, float bottomMarginSize, float leftMarginSize, float rightMarginSize )
|
||||
public static void drawTerminal(
|
||||
@Nonnull Matrix4f transform, @Nonnull VertexConsumer buffer, float x, float y,
|
||||
@Nonnull Terminal terminal, boolean greyscale,
|
||||
float topMarginSize, float bottomMarginSize, float leftMarginSize, float rightMarginSize
|
||||
)
|
||||
{
|
||||
drawTerminalWithoutCursor( transform, buffer, x, y, terminal, greyscale, topMarginSize, bottomMarginSize, leftMarginSize, rightMarginSize );
|
||||
drawCursor( transform, buffer, x, y, terminal, greyscale );
|
||||
}
|
||||
|
||||
public static void drawTerminal( @Nonnull Matrix4f transform, float x, float y, @Nonnull Terminal terminal, boolean greyscale, float topMarginSize,
|
||||
float bottomMarginSize, float leftMarginSize, float rightMarginSize )
|
||||
public static void drawTerminal(
|
||||
@Nonnull Matrix4f transform, float x, float y, @Nonnull Terminal terminal, boolean greyscale,
|
||||
float topMarginSize, float bottomMarginSize, float leftMarginSize, float rightMarginSize
|
||||
)
|
||||
{
|
||||
MultiBufferSource.BufferSource renderer = Minecraft.getInstance()
|
||||
.renderBuffers()
|
||||
.bufferSource();
|
||||
MultiBufferSource.BufferSource renderer = MultiBufferSource.immediate( Tesselator.getInstance().getBuilder() );
|
||||
VertexConsumer buffer = renderer.getBuffer( RenderTypes.TERMINAL_WITH_DEPTH );
|
||||
drawTerminal( transform, buffer, x, y, terminal, greyscale, topMarginSize, bottomMarginSize, leftMarginSize, rightMarginSize );
|
||||
renderer.endBatch();
|
||||
}
|
||||
|
||||
public static void drawTerminal( float x, float y, @Nonnull Terminal terminal, boolean greyscale, float topMarginSize, float bottomMarginSize,
|
||||
float leftMarginSize, float rightMarginSize )
|
||||
{
|
||||
drawTerminal( IDENTITY, x, y, terminal, greyscale, topMarginSize, bottomMarginSize, leftMarginSize, rightMarginSize );
|
||||
}
|
||||
|
||||
public static void drawEmptyTerminal( float x, float y, float width, float height )
|
||||
public static void drawEmptyTerminal( @Nonnull Matrix4f transform, @Nonnull MultiBufferSource renderer, float x, float y, float width, float height )
|
||||
{
|
||||
Colour colour = Colour.BLACK;
|
||||
drawEmptyTerminal( IDENTITY, x, y, width, height );
|
||||
drawQuad( transform, renderer.getBuffer( RenderTypes.TERMINAL_WITH_DEPTH ), x, y, width, height, colour.getR(), colour.getG(), colour.getB() );
|
||||
}
|
||||
|
||||
public static void drawEmptyTerminal( @Nonnull Matrix4f transform, float x, float y, float width, float height )
|
||||
{
|
||||
MultiBufferSource.BufferSource renderer = Minecraft.getInstance()
|
||||
.renderBuffers()
|
||||
.bufferSource();
|
||||
MultiBufferSource.BufferSource renderer = MultiBufferSource.immediate( Tesselator.getInstance().getBuilder() );
|
||||
drawEmptyTerminal( transform, renderer, x, y, width, height );
|
||||
renderer.endBatch();
|
||||
}
|
||||
|
||||
public static void drawEmptyTerminal( @Nonnull Matrix4f transform, @Nonnull MultiBufferSource renderer, float x, float y, float width,
|
||||
float height )
|
||||
{
|
||||
Colour colour = Colour.BLACK;
|
||||
drawQuad( transform, renderer.getBuffer( RenderTypes.TERMINAL_WITH_DEPTH ), x, y, width, height, colour.getR(), colour.getG(), colour.getB() );
|
||||
}
|
||||
|
||||
public static void drawBlocker( @Nonnull Matrix4f transform, @Nonnull MultiBufferSource renderer, float x, float y, float width, float height )
|
||||
{
|
||||
Colour colour = Colour.BLACK;
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client.gui;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
@@ -20,14 +19,15 @@ import net.minecraft.world.entity.player.Inventory;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import static dan200.computercraft.client.render.ComputerBorderRenderer.BORDER;
|
||||
import static dan200.computercraft.client.render.ComputerBorderRenderer.getTexture;
|
||||
|
||||
public final class GuiComputer<T extends ContainerComputerBase> extends ComputerScreenBase<T>
|
||||
{
|
||||
private final int termWidth;
|
||||
private final int termHeight;
|
||||
|
||||
private GuiComputer( T container, Inventory player, Component title, int termWidth, int termHeight )
|
||||
private GuiComputer(
|
||||
T container, Inventory player, Component title, int termWidth, int termHeight
|
||||
)
|
||||
{
|
||||
super( container, player, title, BORDER );
|
||||
this.termWidth = termWidth;
|
||||
@@ -37,19 +37,31 @@ public final class GuiComputer<T extends ContainerComputerBase> extends Computer
|
||||
imageHeight = WidgetTerminal.getHeight( termHeight ) + BORDER * 2;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static GuiComputer<ContainerComputerBase> create( ContainerComputerBase container, Inventory inventory, Component component )
|
||||
{
|
||||
return new GuiComputer<>( container, inventory, component, ComputerCraft.computerTermWidth, ComputerCraft.computerTermHeight );
|
||||
return new GuiComputer<>(
|
||||
container, inventory, component,
|
||||
ComputerCraft.computerTermWidth, ComputerCraft.computerTermHeight
|
||||
);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static GuiComputer<ContainerComputerBase> createPocket( ContainerComputerBase container, Inventory inventory, Component component )
|
||||
{
|
||||
return new GuiComputer<>( container, inventory, component, ComputerCraft.pocketTermWidth, ComputerCraft.pocketTermHeight );
|
||||
return new GuiComputer<>(
|
||||
container, inventory, component,
|
||||
ComputerCraft.pocketTermWidth, ComputerCraft.pocketTermHeight
|
||||
);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static GuiComputer<ContainerViewComputer> createView( ContainerViewComputer container, Inventory inventory, Component component )
|
||||
{
|
||||
return new GuiComputer<>( container, inventory, component, container.getWidth(), container.getHeight() );
|
||||
return new GuiComputer<>(
|
||||
container, inventory, component,
|
||||
container.getWidth(), container.getHeight()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -63,9 +75,11 @@ public final class GuiComputer<T extends ContainerComputerBase> extends Computer
|
||||
@Override
|
||||
public void renderBg( @Nonnull PoseStack stack, float partialTicks, int mouseX, int mouseY )
|
||||
{
|
||||
// Draw a border around the terminal
|
||||
ComputerBorderRenderer.render(
|
||||
getTexture( family ), terminal.x, terminal.y, getBlitOffset(),
|
||||
RenderTypes.FULL_BRIGHT_LIGHTMAP, terminal.getWidth(), terminal.getHeight() );
|
||||
ComputerBorderRenderer.getTexture( family ), terminal.x, terminal.y, getBlitOffset(),
|
||||
RenderTypes.FULL_BRIGHT_LIGHTMAP, terminal.getWidth(), terminal.getHeight()
|
||||
);
|
||||
ComputerSidebar.renderBackground( stack, leftPos, topPos + sidebarYOffset );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,14 +3,12 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client.gui;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive;
|
||||
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
@@ -26,6 +24,14 @@ public class GuiDiskDrive extends AbstractContainerScreen<ContainerDiskDrive>
|
||||
super( container, player, title );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderBg( @Nonnull PoseStack transform, float partialTicks, int mouseX, int mouseY )
|
||||
{
|
||||
RenderSystem.setShaderColor( 1.0F, 1.0F, 1.0F, 1.0F );
|
||||
RenderSystem.setShaderTexture( 0, BACKGROUND );
|
||||
blit( transform, leftPos, topPos, 0, 0, imageWidth, imageHeight );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render( @Nonnull PoseStack transform, int mouseX, int mouseY, float partialTicks )
|
||||
{
|
||||
@@ -33,13 +39,4 @@ public class GuiDiskDrive extends AbstractContainerScreen<ContainerDiskDrive>
|
||||
super.render( transform, mouseX, mouseY, partialTicks );
|
||||
renderTooltip( transform, mouseX, mouseY );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderBg( @Nonnull PoseStack transform, float partialTicks, int mouseX, int mouseY )
|
||||
{
|
||||
RenderSystem.setShader( GameRenderer::getPositionTexShader );
|
||||
RenderSystem.setShaderColor( 1.0F, 1.0F, 1.0F, 1.0F );
|
||||
RenderSystem.setShaderTexture( 0, BACKGROUND );
|
||||
blit( transform, leftPos, topPos, 0, 0, imageWidth, imageHeight );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client.gui;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
@@ -25,14 +24,6 @@ public class GuiPrinter extends AbstractContainerScreen<ContainerPrinter>
|
||||
super( container, player, title );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render( @Nonnull PoseStack stack, int mouseX, int mouseY, float partialTicks )
|
||||
{
|
||||
renderBackground( stack );
|
||||
super.render( stack, mouseX, mouseY, partialTicks );
|
||||
renderTooltip( stack, mouseX, mouseY );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderBg( @Nonnull PoseStack transform, float partialTicks, int mouseX, int mouseY )
|
||||
{
|
||||
@@ -40,9 +31,14 @@ public class GuiPrinter extends AbstractContainerScreen<ContainerPrinter>
|
||||
RenderSystem.setShaderTexture( 0, BACKGROUND );
|
||||
blit( transform, leftPos, topPos, 0, 0, imageWidth, imageHeight );
|
||||
|
||||
if( getMenu().isPrinting() )
|
||||
{
|
||||
blit( transform, leftPos + 34, topPos + 21, 176, 0, 25, 45 );
|
||||
}
|
||||
if( getMenu().isPrinting() ) blit( transform, leftPos + 34, topPos + 21, 176, 0, 25, 45 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render( @Nonnull PoseStack stack, int mouseX, int mouseY, float partialTicks )
|
||||
{
|
||||
renderBackground( stack );
|
||||
super.render( stack, mouseX, mouseY, partialTicks );
|
||||
renderTooltip( stack, mouseX, mouseY );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,16 +3,15 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client.gui;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.Tesselator;
|
||||
import com.mojang.math.Matrix4f;
|
||||
import dan200.computercraft.core.terminal.TextBuffer;
|
||||
import dan200.computercraft.shared.common.ContainerHeldItem;
|
||||
import dan200.computercraft.shared.media.items.ItemPrintout;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.network.chat.Component;
|
||||
@@ -40,54 +39,72 @@ public class GuiPrintout extends AbstractContainerScreen<ContainerHeldItem>
|
||||
|
||||
String[] text = ItemPrintout.getText( container.getStack() );
|
||||
this.text = new TextBuffer[text.length];
|
||||
for( int i = 0; i < this.text.length; i++ )
|
||||
{
|
||||
this.text[i] = new TextBuffer( text[i] );
|
||||
}
|
||||
for( int i = 0; i < this.text.length; i++ ) this.text[i] = new TextBuffer( text[i] );
|
||||
|
||||
String[] colours = ItemPrintout.getColours( container.getStack() );
|
||||
this.colours = new TextBuffer[colours.length];
|
||||
for( int i = 0; i < this.colours.length; i++ )
|
||||
{
|
||||
this.colours[i] = new TextBuffer( colours[i] );
|
||||
}
|
||||
for( int i = 0; i < this.colours.length; i++ ) this.colours[i] = new TextBuffer( colours[i] );
|
||||
|
||||
page = 0;
|
||||
pages = Math.max( this.text.length / ItemPrintout.LINES_PER_PAGE, 1 );
|
||||
book = ((ItemPrintout) container.getStack()
|
||||
.getItem()).getType() == ItemPrintout.Type.BOOK;
|
||||
book = ((ItemPrintout) container.getStack().getItem()).getType() == ItemPrintout.Type.BOOK;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyPressed( int key, int scancode, int modifiers )
|
||||
{
|
||||
if( super.keyPressed( key, scancode, modifiers ) ) return true;
|
||||
|
||||
if( key == GLFW.GLFW_KEY_RIGHT )
|
||||
{
|
||||
if( page < pages - 1 ) page++;
|
||||
return true;
|
||||
}
|
||||
|
||||
if( key == GLFW.GLFW_KEY_LEFT )
|
||||
{
|
||||
if( page > 0 ) page--;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseScrolled( double x, double y, double delta )
|
||||
{
|
||||
if( super.mouseScrolled( x, y, delta ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if( super.mouseScrolled( x, y, delta ) ) return true;
|
||||
if( delta < 0 )
|
||||
{
|
||||
// Scroll up goes to the next page
|
||||
if( page < pages - 1 )
|
||||
{
|
||||
page++;
|
||||
}
|
||||
if( page < pages - 1 ) page++;
|
||||
return true;
|
||||
}
|
||||
|
||||
if( delta > 0 )
|
||||
{
|
||||
// Scroll down goes to the previous page
|
||||
if( page > 0 )
|
||||
{
|
||||
page--;
|
||||
}
|
||||
if( page > 0 ) page--;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderBg( @Nonnull PoseStack transform, float partialTicks, int mouseX, int mouseY )
|
||||
{
|
||||
// Draw the printout
|
||||
RenderSystem.setShaderColor( 1.0f, 1.0f, 1.0f, 1.0f );
|
||||
RenderSystem.enableDepthTest();
|
||||
|
||||
MultiBufferSource.BufferSource renderer = MultiBufferSource.immediate( Tesselator.getInstance().getBuilder() );
|
||||
Matrix4f matrix = transform.last().pose();
|
||||
drawBorder( matrix, renderer, leftPos, topPos, getBlitOffset(), page, pages, book, FULL_BRIGHT_LIGHTMAP );
|
||||
drawText( matrix, renderer, leftPos + X_TEXT_MARGIN, topPos + Y_TEXT_MARGIN, ItemPrintout.LINES_PER_PAGE * page, FULL_BRIGHT_LIGHTMAP, text, colours );
|
||||
renderer.endBatch();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render( @Nonnull PoseStack stack, int mouseX, int mouseY, float partialTicks )
|
||||
{
|
||||
@@ -104,50 +121,4 @@ public class GuiPrintout extends AbstractContainerScreen<ContainerHeldItem>
|
||||
{
|
||||
// Skip rendering labels.
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderBg( @Nonnull PoseStack transform, float partialTicks, int mouseX, int mouseY )
|
||||
{
|
||||
// Draw the printout
|
||||
RenderSystem.setShaderColor( 1.0f, 1.0f, 1.0f, 1.0f );
|
||||
RenderSystem.enableDepthTest();
|
||||
|
||||
MultiBufferSource.BufferSource renderer = Minecraft.getInstance()
|
||||
.renderBuffers()
|
||||
.bufferSource();
|
||||
Matrix4f matrix = transform.last()
|
||||
.pose();
|
||||
drawBorder( matrix, renderer, leftPos, topPos, getBlitOffset(), page, pages, book, FULL_BRIGHT_LIGHTMAP );
|
||||
drawText( matrix, renderer, leftPos + X_TEXT_MARGIN, topPos + Y_TEXT_MARGIN, ItemPrintout.LINES_PER_PAGE * page, FULL_BRIGHT_LIGHTMAP, text, colours );
|
||||
renderer.endBatch();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyPressed( int key, int scancode, int modifiers )
|
||||
{
|
||||
if( super.keyPressed( key, scancode, modifiers ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if( key == GLFW.GLFW_KEY_RIGHT )
|
||||
{
|
||||
if( page < pages - 1 )
|
||||
{
|
||||
page++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if( key == GLFW.GLFW_KEY_LEFT )
|
||||
{
|
||||
if( page > 0 )
|
||||
{
|
||||
page--;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client.gui;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
@@ -20,12 +19,12 @@ import net.minecraft.world.entity.player.Inventory;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import static dan200.computercraft.shared.turtle.inventory.ContainerTurtle.BORDER;
|
||||
import static dan200.computercraft.shared.turtle.inventory.ContainerTurtle.*;
|
||||
|
||||
public class GuiTurtle extends ComputerScreenBase<ContainerTurtle>
|
||||
{
|
||||
private static final ResourceLocation BACKGROUND_NORMAL = new ResourceLocation( "computercraft", "textures/gui/turtle_normal.png" );
|
||||
private static final ResourceLocation BACKGROUND_ADVANCED = new ResourceLocation( "computercraft", "textures/gui/turtle_advanced.png" );
|
||||
private static final ResourceLocation BACKGROUND_NORMAL = new ResourceLocation( ComputerCraft.MOD_ID, "textures/gui/turtle_normal.png" );
|
||||
private static final ResourceLocation BACKGROUND_ADVANCED = new ResourceLocation( ComputerCraft.MOD_ID, "textures/gui/turtle_advanced.png" );
|
||||
|
||||
private static final int TEX_WIDTH = 254;
|
||||
private static final int TEX_HEIGHT = 217;
|
||||
@@ -35,11 +34,10 @@ public class GuiTurtle extends ComputerScreenBase<ContainerTurtle>
|
||||
public GuiTurtle( ContainerTurtle container, Inventory player, Component title )
|
||||
{
|
||||
super( container, player, title, BORDER );
|
||||
|
||||
family = container.getFamily();
|
||||
|
||||
imageWidth = TEX_WIDTH + ComputerSidebar.WIDTH;
|
||||
imageHeight = TEX_HEIGHT;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -52,23 +50,22 @@ public class GuiTurtle extends ComputerScreenBase<ContainerTurtle>
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderBg( @Nonnull PoseStack transform, float partialTicks, int mouseX, int mouseY )
|
||||
protected void renderBg( @Nonnull PoseStack transform, float partialTicks, int mouseX, int mouseY )
|
||||
{
|
||||
boolean advanced = family == ComputerFamily.ADVANCED;
|
||||
RenderSystem.setShaderTexture( 0, advanced ? BACKGROUND_ADVANCED : BACKGROUND_NORMAL );
|
||||
blit( transform, leftPos + ComputerSidebar.WIDTH, topPos, 0, 0, TEX_WIDTH, TEX_HEIGHT );
|
||||
|
||||
// Draw selection slot
|
||||
int slot = getMenu().getSelectedSlot();
|
||||
if( slot >= 0 )
|
||||
{
|
||||
RenderSystem.setShaderColor( 1.0F, 1.0F, 1.0F, 1.0F );
|
||||
int slotX = slot % 4;
|
||||
int slotY = slot / 4;
|
||||
blit( transform, leftPos + ContainerTurtle.TURTLE_START_X - 2 + slotX * 18, topPos + ContainerTurtle.PLAYER_START_Y - 2 + slotY * 18,
|
||||
0,
|
||||
217,
|
||||
24,
|
||||
24 );
|
||||
blit( transform,
|
||||
leftPos + TURTLE_START_X - 2 + slotX * 18, topPos + PLAYER_START_Y - 2 + slotY * 18,
|
||||
0, 217, 24, 24
|
||||
);
|
||||
}
|
||||
|
||||
RenderSystem.setShaderTexture( 0, advanced ? ComputerBorderRenderer.BACKGROUND_ADVANCED : ComputerBorderRenderer.BACKGROUND_NORMAL );
|
||||
|
||||
@@ -10,6 +10,7 @@ import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.client.gui.widgets.WidgetTerminal;
|
||||
import dan200.computercraft.shared.computer.core.ClientComputer;
|
||||
import dan200.computercraft.shared.computer.inventory.ContainerComputerBase;
|
||||
import net.minecraft.client.KeyMapping;
|
||||
import net.minecraft.client.gui.Font;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.client.gui.screens.inventory.MenuAccess;
|
||||
@@ -43,9 +44,13 @@ public class NoTermComputerScreen<T extends ContainerComputerBase> extends Scree
|
||||
@Override
|
||||
protected void init()
|
||||
{
|
||||
this.passEvents = true;
|
||||
passEvents = true; // Pass mouse vents through to the game's mouse handler.
|
||||
// First ensure we're still grabbing the mouse, so the user can look around. Then reset bits of state that
|
||||
// grabbing unsets.
|
||||
minecraft.mouseHandler.grabMouse();
|
||||
minecraft.screen = this;
|
||||
KeyMapping.releaseAll();
|
||||
|
||||
super.init();
|
||||
minecraft.keyboardHandler.setSendRepeatsToGui( true );
|
||||
|
||||
@@ -102,7 +107,7 @@ public class NoTermComputerScreen<T extends ContainerComputerBase> extends Scree
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render( PoseStack transform, int mouseX, int mouseY, float partialTicks )
|
||||
public void render( @Nonnull PoseStack transform, int mouseX, int mouseY, float partialTicks )
|
||||
{
|
||||
super.render( transform, mouseX, mouseY, partialTicks );
|
||||
|
||||
|
||||
@@ -49,9 +49,9 @@ public final class OptionScreen extends Screen
|
||||
this.originalScreen = originalScreen;
|
||||
}
|
||||
|
||||
public static void show( Minecraft client, Component title, Component message, List<AbstractWidget> buttons, Runnable exit )
|
||||
public static void show( Minecraft minecraft, Component title, Component message, List<AbstractWidget> buttons, Runnable exit )
|
||||
{
|
||||
client.setScreen( new OptionScreen( title, message, buttons, exit, unwrap( client.screen ) ) );
|
||||
minecraft.setScreen( new OptionScreen( title, message, buttons, exit, unwrap( minecraft.screen ) ) );
|
||||
}
|
||||
|
||||
public static Screen unwrap( Screen screen )
|
||||
|
||||
@@ -8,7 +8,6 @@ package dan200.computercraft.client.gui.widgets;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.client.render.ComputerBorderRenderer;
|
||||
import dan200.computercraft.shared.command.text.ChatHelpers;
|
||||
import dan200.computercraft.shared.computer.core.ClientComputer;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.client.gui.components.AbstractWidget;
|
||||
@@ -55,10 +54,10 @@ public final class ComputerSidebar
|
||||
TEXTURE, TEX_SIZE, TEX_SIZE, b -> toggleComputer( computer ),
|
||||
() -> computer.isOn() ? Arrays.asList(
|
||||
new TranslatableComponent( "gui.computercraft.tooltip.turn_off" ),
|
||||
ChatHelpers.coloured( new TranslatableComponent( "gui.computercraft.tooltip.turn_off.key" ), ChatFormatting.GRAY )
|
||||
new TranslatableComponent( "gui.computercraft.tooltip.turn_off.key" ).withStyle( ChatFormatting.GRAY )
|
||||
) : Arrays.asList(
|
||||
new TranslatableComponent( "gui.computercraft.tooltip.turn_on" ),
|
||||
ChatHelpers.coloured( new TranslatableComponent( "gui.computercraft.tooltip.turn_off.key" ), ChatFormatting.GRAY )
|
||||
new TranslatableComponent( "gui.computercraft.tooltip.turn_off.key" ).withStyle( ChatFormatting.GRAY )
|
||||
)
|
||||
) );
|
||||
|
||||
@@ -69,7 +68,7 @@ public final class ComputerSidebar
|
||||
TEXTURE, TEX_SIZE, TEX_SIZE, b -> computer.queueEvent( "terminate" ),
|
||||
Arrays.asList(
|
||||
new TranslatableComponent( "gui.computercraft.tooltip.terminate" ),
|
||||
ChatHelpers.coloured( new TranslatableComponent( "gui.computercraft.tooltip.terminate.key" ), ChatFormatting.GRAY )
|
||||
new TranslatableComponent( "gui.computercraft.tooltip.terminate.key" ).withStyle( ChatFormatting.GRAY )
|
||||
)
|
||||
) );
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ package dan200.computercraft.client.gui.widgets;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import dan200.computercraft.shared.util.NonNullSupplier;
|
||||
import net.minecraft.client.gui.components.Button;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.network.chat.Component;
|
||||
@@ -16,7 +17,6 @@ import net.minecraft.resources.ResourceLocation;
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
import java.util.function.IntSupplier;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Version of {@link net.minecraft.client.gui.components.ImageButton} which allows changing some properties
|
||||
@@ -31,7 +31,7 @@ public class DynamicImageButton extends Button
|
||||
private final int yDiffTex;
|
||||
private final int textureWidth;
|
||||
private final int textureHeight;
|
||||
private final Supplier<List<Component>> tooltip;
|
||||
private final NonNullSupplier<List<Component>> tooltip;
|
||||
|
||||
public DynamicImageButton(
|
||||
Screen screen, int x, int y, int width, int height, int xTexStart, int yTexStart, int yDiffTex,
|
||||
@@ -50,7 +50,7 @@ public class DynamicImageButton extends Button
|
||||
public DynamicImageButton(
|
||||
Screen screen, int x, int y, int width, int height, IntSupplier xTexStart, int yTexStart, int yDiffTex,
|
||||
ResourceLocation texture, int textureWidth, int textureHeight,
|
||||
OnPress onPress, Supplier<List<Component>> tooltip
|
||||
OnPress onPress, NonNullSupplier<List<Component>> tooltip
|
||||
)
|
||||
{
|
||||
super( x, y, width, height, TextComponent.EMPTY, onPress );
|
||||
@@ -71,12 +71,12 @@ public class DynamicImageButton extends Button
|
||||
RenderSystem.disableDepthTest();
|
||||
|
||||
int yTex = yTexStart;
|
||||
if( isHovered() ) yTex += yDiffTex;
|
||||
if( isHoveredOrFocused() ) yTex += yDiffTex;
|
||||
|
||||
blit( stack, x, y, xTexStart.getAsInt(), yTex, width, height, textureWidth, textureHeight );
|
||||
RenderSystem.enableDepthTest();
|
||||
|
||||
if( isHovered() ) renderToolTip( stack, mouseX, mouseY );
|
||||
if( isHovered ) renderToolTip( stack, mouseX, mouseY );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@@ -87,11 +87,10 @@ public class DynamicImageButton extends Button
|
||||
return tooltip.isEmpty() ? TextComponent.EMPTY : tooltip.get( 0 );
|
||||
}
|
||||
|
||||
// @Override
|
||||
@Override
|
||||
public void renderToolTip( @Nonnull PoseStack stack, int mouseX, int mouseY )
|
||||
{
|
||||
List<Component> tooltip = this.tooltip.get();
|
||||
|
||||
if( !tooltip.isEmpty() )
|
||||
{
|
||||
screen.renderComponentTooltip( stack, tooltip, mouseX, mouseY );
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client.gui.widgets;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
@@ -65,15 +64,104 @@ public class WidgetTerminal extends AbstractWidget
|
||||
if( ch >= 32 && ch <= 126 || ch >= 160 && ch <= 255 ) // printable chars in byte range
|
||||
{
|
||||
// Queue the "char" event
|
||||
queueEvent( "char", Character.toString( ch ) );
|
||||
computer.queueEvent( "char", new Object[] { Character.toString( ch ) } );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean inTermRegion( double mouseX, double mouseY )
|
||||
@Override
|
||||
public boolean keyPressed( int key, int scancode, int modifiers )
|
||||
{
|
||||
return active && visible && mouseX >= innerX && mouseY >= innerY && mouseX < innerX + innerWidth && mouseY < innerY + innerHeight;
|
||||
if( key == GLFW.GLFW_KEY_ESCAPE ) return false;
|
||||
if( (modifiers & GLFW.GLFW_MOD_CONTROL) != 0 )
|
||||
{
|
||||
switch( key )
|
||||
{
|
||||
case GLFW.GLFW_KEY_T:
|
||||
if( terminateTimer < 0 ) terminateTimer = 0;
|
||||
return true;
|
||||
case GLFW.GLFW_KEY_S:
|
||||
if( shutdownTimer < 0 ) shutdownTimer = 0;
|
||||
return true;
|
||||
case GLFW.GLFW_KEY_R:
|
||||
if( rebootTimer < 0 ) rebootTimer = 0;
|
||||
return true;
|
||||
|
||||
case GLFW.GLFW_KEY_V:
|
||||
// Ctrl+V for paste
|
||||
String clipboard = Minecraft.getInstance().keyboardHandler.getClipboard();
|
||||
if( clipboard != null )
|
||||
{
|
||||
// Clip to the first occurrence of \r or \n
|
||||
int newLineIndex1 = clipboard.indexOf( "\r" );
|
||||
int newLineIndex2 = clipboard.indexOf( "\n" );
|
||||
if( newLineIndex1 >= 0 && newLineIndex2 >= 0 )
|
||||
{
|
||||
clipboard = clipboard.substring( 0, Math.min( newLineIndex1, newLineIndex2 ) );
|
||||
}
|
||||
else if( newLineIndex1 >= 0 )
|
||||
{
|
||||
clipboard = clipboard.substring( 0, newLineIndex1 );
|
||||
}
|
||||
else if( newLineIndex2 >= 0 )
|
||||
{
|
||||
clipboard = clipboard.substring( 0, newLineIndex2 );
|
||||
}
|
||||
|
||||
// Filter the string
|
||||
clipboard = SharedConstants.filterText( clipboard );
|
||||
if( !clipboard.isEmpty() )
|
||||
{
|
||||
// Clip to 512 characters and queue the event
|
||||
if( clipboard.length() > 512 ) clipboard = clipboard.substring( 0, 512 );
|
||||
computer.queueEvent( "paste", new Object[] { clipboard } );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( key >= 0 && terminateTimer < 0 && rebootTimer < 0 && shutdownTimer < 0 )
|
||||
{
|
||||
// Queue the "key" event and add to the down set
|
||||
boolean repeat = keysDown.get( key );
|
||||
keysDown.set( key );
|
||||
computer.keyDown( key, repeat );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyReleased( int key, int scancode, int modifiers )
|
||||
{
|
||||
// Queue the "key_up" event and remove from the down set
|
||||
if( key >= 0 && keysDown.get( key ) )
|
||||
{
|
||||
keysDown.set( key, false );
|
||||
computer.keyUp( key );
|
||||
}
|
||||
|
||||
switch( key )
|
||||
{
|
||||
case GLFW.GLFW_KEY_T:
|
||||
terminateTimer = -1;
|
||||
break;
|
||||
case GLFW.GLFW_KEY_R:
|
||||
rebootTimer = -1;
|
||||
break;
|
||||
case GLFW.GLFW_KEY_S:
|
||||
shutdownTimer = -1;
|
||||
break;
|
||||
case GLFW.GLFW_KEY_LEFT_CONTROL:
|
||||
case GLFW.GLFW_KEY_RIGHT_CONTROL:
|
||||
terminateTimer = rebootTimer = shutdownTimer = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -175,113 +263,27 @@ public class WidgetTerminal extends AbstractWidget
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyPressed( int key, int scancode, int modifiers )
|
||||
private boolean inTermRegion( double mouseX, double mouseY )
|
||||
{
|
||||
if( key == GLFW.GLFW_KEY_ESCAPE )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if( (modifiers & GLFW.GLFW_MOD_CONTROL) != 0 )
|
||||
{
|
||||
switch( key )
|
||||
{
|
||||
case GLFW.GLFW_KEY_T:
|
||||
if( terminateTimer < 0 )
|
||||
{
|
||||
terminateTimer = 0;
|
||||
}
|
||||
return true;
|
||||
case GLFW.GLFW_KEY_S:
|
||||
if( shutdownTimer < 0 )
|
||||
{
|
||||
shutdownTimer = 0;
|
||||
}
|
||||
return true;
|
||||
case GLFW.GLFW_KEY_R:
|
||||
if( rebootTimer < 0 )
|
||||
{
|
||||
rebootTimer = 0;
|
||||
}
|
||||
return true;
|
||||
|
||||
case GLFW.GLFW_KEY_V:
|
||||
// Ctrl+V for paste
|
||||
String clipboard = Minecraft.getInstance().keyboardHandler.getClipboard();
|
||||
if( clipboard != null )
|
||||
{
|
||||
// Clip to the first occurrence of \r or \n
|
||||
int newLineIndex1 = clipboard.indexOf( "\r" );
|
||||
int newLineIndex2 = clipboard.indexOf( "\n" );
|
||||
if( newLineIndex1 >= 0 && newLineIndex2 >= 0 )
|
||||
{
|
||||
clipboard = clipboard.substring( 0, Math.min( newLineIndex1, newLineIndex2 ) );
|
||||
}
|
||||
else if( newLineIndex1 >= 0 )
|
||||
{
|
||||
clipboard = clipboard.substring( 0, newLineIndex1 );
|
||||
}
|
||||
else if( newLineIndex2 >= 0 )
|
||||
{
|
||||
clipboard = clipboard.substring( 0, newLineIndex2 );
|
||||
}
|
||||
|
||||
// Filter the string
|
||||
clipboard = SharedConstants.filterText( clipboard );
|
||||
if( !clipboard.isEmpty() )
|
||||
{
|
||||
// Clip to 512 characters and queue the event
|
||||
if( clipboard.length() > 512 )
|
||||
{
|
||||
clipboard = clipboard.substring( 0, 512 );
|
||||
}
|
||||
queueEvent( "paste", clipboard );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( key >= 0 && terminateTimer < 0 && rebootTimer < 0 && shutdownTimer < 0 )
|
||||
{
|
||||
// Queue the "key" event and add to the down set
|
||||
boolean repeat = keysDown.get( key );
|
||||
keysDown.set( key );
|
||||
computer.keyDown( key, repeat );
|
||||
}
|
||||
|
||||
return true;
|
||||
return active && visible && mouseX >= innerX && mouseY >= innerY && mouseX < innerX + innerWidth && mouseY < innerY + innerHeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyReleased( int key, int scancode, int modifiers )
|
||||
public void update()
|
||||
{
|
||||
// Queue the "key_up" event and remove from the down set
|
||||
if( key >= 0 && keysDown.get( key ) )
|
||||
if( terminateTimer >= 0 && terminateTimer < TERMINATE_TIME && (terminateTimer += 0.05f) > TERMINATE_TIME )
|
||||
{
|
||||
keysDown.set( key, false );
|
||||
computer.keyUp( key );
|
||||
computer.queueEvent( "terminate" );
|
||||
}
|
||||
|
||||
switch( key )
|
||||
if( shutdownTimer >= 0 && shutdownTimer < TERMINATE_TIME && (shutdownTimer += 0.05f) > TERMINATE_TIME )
|
||||
{
|
||||
case GLFW.GLFW_KEY_T:
|
||||
terminateTimer = -1;
|
||||
break;
|
||||
case GLFW.GLFW_KEY_R:
|
||||
rebootTimer = -1;
|
||||
break;
|
||||
case GLFW.GLFW_KEY_S:
|
||||
shutdownTimer = -1;
|
||||
break;
|
||||
case GLFW.GLFW_KEY_LEFT_CONTROL:
|
||||
case GLFW.GLFW_KEY_RIGHT_CONTROL:
|
||||
terminateTimer = rebootTimer = shutdownTimer = -1;
|
||||
break;
|
||||
computer.shutdown();
|
||||
}
|
||||
|
||||
return true;
|
||||
if( rebootTimer >= 0 && rebootTimer < TERMINATE_TIME && (rebootTimer += 0.05f) > TERMINATE_TIME )
|
||||
{
|
||||
computer.reboot();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -307,44 +309,6 @@ public class WidgetTerminal extends AbstractWidget
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMouseOver( double x, double y )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private void queueEvent( String event, Object... args )
|
||||
{
|
||||
computer.queueEvent( event, args );
|
||||
}
|
||||
|
||||
public void update()
|
||||
{
|
||||
if( terminateTimer >= 0 && terminateTimer < TERMINATE_TIME && (terminateTimer += 0.05f) > TERMINATE_TIME )
|
||||
{
|
||||
queueEvent( "terminate" );
|
||||
}
|
||||
|
||||
if( shutdownTimer >= 0 && shutdownTimer < TERMINATE_TIME && (shutdownTimer += 0.05f) > TERMINATE_TIME )
|
||||
{
|
||||
computer.shutdown();
|
||||
}
|
||||
|
||||
if( rebootTimer >= 0 && rebootTimer < TERMINATE_TIME && (rebootTimer += 0.05f) > TERMINATE_TIME )
|
||||
{
|
||||
computer.reboot();
|
||||
}
|
||||
}
|
||||
|
||||
private void queueEvent( String event )
|
||||
{
|
||||
ClientComputer computer = this.computer;
|
||||
if( computer != null )
|
||||
{
|
||||
computer.queueEvent( event );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render( @Nonnull PoseStack transform, int mouseX, int mouseY, float partialTicks )
|
||||
{
|
||||
@@ -362,9 +326,9 @@ public class WidgetTerminal extends AbstractWidget
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateNarration( NarrationElementOutput builder )
|
||||
public void updateNarration( @Nonnull NarrationElementOutput output )
|
||||
{
|
||||
|
||||
// I'm not sure what the right option is here.
|
||||
}
|
||||
|
||||
public static int getWidth( int termWidth )
|
||||
|
||||
@@ -14,8 +14,8 @@ import dan200.computercraft.client.render.TileEntityMonitorRenderer;
|
||||
import dan200.computercraft.client.render.TileEntityTurtleRenderer;
|
||||
import dan200.computercraft.client.render.TurtleModelLoader;
|
||||
import dan200.computercraft.client.render.TurtlePlayerRenderer;
|
||||
import dan200.computercraft.fabric.events.ClientUnloadWorldEvent;
|
||||
import dan200.computercraft.shared.ComputerCraftRegistry;
|
||||
import dan200.computercraft.fabric.events.ComputerCraftCustomEvents;
|
||||
import dan200.computercraft.shared.Registry;
|
||||
import dan200.computercraft.shared.common.ContainerHeldItem;
|
||||
import dan200.computercraft.shared.common.IColouredItem;
|
||||
import dan200.computercraft.shared.common.TileGeneric;
|
||||
@@ -23,6 +23,7 @@ import dan200.computercraft.shared.computer.inventory.ContainerComputerBase;
|
||||
import dan200.computercraft.shared.computer.inventory.ContainerViewComputer;
|
||||
import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive;
|
||||
import dan200.computercraft.shared.peripheral.monitor.ClientMonitor;
|
||||
import dan200.computercraft.shared.peripheral.monitor.MonitorWatcher;
|
||||
import dan200.computercraft.shared.peripheral.printer.ContainerPrinter;
|
||||
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
|
||||
import dan200.computercraft.shared.turtle.inventory.ContainerTurtle;
|
||||
@@ -60,7 +61,7 @@ public final class ComputerCraftProxyClient implements ClientModInitializer
|
||||
}
|
||||
} );
|
||||
|
||||
ClientUnloadWorldEvent.EVENT.register( () -> ClientMonitor.destroyAll() );
|
||||
ComputerCraftCustomEvents.CLIENT_UNLOAD_WORLD_EVENT.register( () -> ClientMonitor.destroyAll() );
|
||||
|
||||
// Config
|
||||
ClientLifecycleEvents.CLIENT_STARTED.register( Config::clientStarted );
|
||||
@@ -70,20 +71,21 @@ public final class ComputerCraftProxyClient implements ClientModInitializer
|
||||
public void onInitializeClient()
|
||||
{
|
||||
FrameInfo.init();
|
||||
MonitorWatcher.init();
|
||||
registerContainers();
|
||||
|
||||
// While turtles themselves are not transparent, their upgrades may be.
|
||||
BlockRenderLayerMap.INSTANCE.putBlock( ComputerCraftRegistry.ModBlocks.TURTLE_NORMAL, RenderType.translucent() );
|
||||
BlockRenderLayerMap.INSTANCE.putBlock( ComputerCraftRegistry.ModBlocks.TURTLE_ADVANCED, RenderType.translucent() );
|
||||
BlockRenderLayerMap.INSTANCE.putBlock( Registry.ModBlocks.TURTLE_NORMAL, RenderType.translucent() );
|
||||
BlockRenderLayerMap.INSTANCE.putBlock( Registry.ModBlocks.TURTLE_ADVANCED, RenderType.translucent() );
|
||||
// Monitors' textures have transparent fronts and so count as cutouts.
|
||||
BlockRenderLayerMap.INSTANCE.putBlock( ComputerCraftRegistry.ModBlocks.MONITOR_NORMAL, RenderType.cutout() );
|
||||
BlockRenderLayerMap.INSTANCE.putBlock( ComputerCraftRegistry.ModBlocks.MONITOR_ADVANCED, RenderType.cutout() );
|
||||
BlockRenderLayerMap.INSTANCE.putBlock( Registry.ModBlocks.MONITOR_NORMAL, RenderType.cutout() );
|
||||
BlockRenderLayerMap.INSTANCE.putBlock( Registry.ModBlocks.MONITOR_ADVANCED, RenderType.cutout() );
|
||||
|
||||
// Setup TESRs
|
||||
BlockEntityRendererRegistry.register( ComputerCraftRegistry.ModTiles.MONITOR_NORMAL, TileEntityMonitorRenderer::new );
|
||||
BlockEntityRendererRegistry.register( ComputerCraftRegistry.ModTiles.MONITOR_ADVANCED, TileEntityMonitorRenderer::new );
|
||||
BlockEntityRendererRegistry.register( ComputerCraftRegistry.ModTiles.TURTLE_NORMAL, TileEntityTurtleRenderer::new );
|
||||
BlockEntityRendererRegistry.register( ComputerCraftRegistry.ModTiles.TURTLE_ADVANCED, TileEntityTurtleRenderer::new );
|
||||
BlockEntityRendererRegistry.register( Registry.ModBlockEntities.MONITOR_NORMAL, TileEntityMonitorRenderer::new );
|
||||
BlockEntityRendererRegistry.register( Registry.ModBlockEntities.MONITOR_ADVANCED, TileEntityMonitorRenderer::new );
|
||||
BlockEntityRendererRegistry.register( Registry.ModBlockEntities.TURTLE_NORMAL, TileEntityTurtleRenderer::new );
|
||||
BlockEntityRendererRegistry.register( Registry.ModBlockEntities.TURTLE_ADVANCED, TileEntityTurtleRenderer::new );
|
||||
|
||||
ClientSpriteRegistryCallback.event( InventoryMenu.BLOCK_ATLAS )
|
||||
.register( ClientRegistry::onTextureStitchEvent );
|
||||
@@ -92,17 +94,17 @@ public final class ComputerCraftProxyClient implements ClientModInitializer
|
||||
TurtleModelLoader.INSTANCE.loadModel(
|
||||
name ) : null );
|
||||
|
||||
EntityRendererRegistry.register( ComputerCraftRegistry.ModEntities.TURTLE_PLAYER, TurtlePlayerRenderer::new );
|
||||
EntityRendererRegistry.register( Registry.ModEntities.TURTLE_PLAYER, TurtlePlayerRenderer::new );
|
||||
|
||||
registerItemProperty( "state",
|
||||
( stack, world, player, integer ) -> ItemPocketComputer.getState( stack )
|
||||
.ordinal(),
|
||||
() -> ComputerCraftRegistry.ModItems.POCKET_COMPUTER_NORMAL,
|
||||
() -> ComputerCraftRegistry.ModItems.POCKET_COMPUTER_ADVANCED );
|
||||
() -> Registry.ModItems.POCKET_COMPUTER_NORMAL,
|
||||
() -> Registry.ModItems.POCKET_COMPUTER_ADVANCED );
|
||||
registerItemProperty( "state",
|
||||
( stack, world, player, integer ) -> IColouredItem.getColourBasic( stack ) != -1 ? 1 : 0,
|
||||
() -> ComputerCraftRegistry.ModItems.POCKET_COMPUTER_NORMAL,
|
||||
() -> ComputerCraftRegistry.ModItems.POCKET_COMPUTER_ADVANCED );
|
||||
() -> Registry.ModItems.POCKET_COMPUTER_NORMAL,
|
||||
() -> Registry.ModItems.POCKET_COMPUTER_ADVANCED );
|
||||
ClientRegistry.onItemColours();
|
||||
|
||||
initEvents();
|
||||
@@ -111,18 +113,18 @@ public final class ComputerCraftProxyClient implements ClientModInitializer
|
||||
// My IDE doesn't think so, but we do actually need these generics.
|
||||
private static void registerContainers()
|
||||
{
|
||||
ScreenRegistry.<ContainerComputerBase, GuiComputer<ContainerComputerBase>>register( ComputerCraftRegistry.ModContainers.COMPUTER, GuiComputer::create );
|
||||
ScreenRegistry.<ContainerComputerBase, GuiComputer<ContainerComputerBase>>register( ComputerCraftRegistry.ModContainers.POCKET_COMPUTER,
|
||||
ScreenRegistry.<ContainerComputerBase, GuiComputer<ContainerComputerBase>>register( Registry.ModContainers.COMPUTER, GuiComputer::create );
|
||||
ScreenRegistry.<ContainerComputerBase, GuiComputer<ContainerComputerBase>>register( Registry.ModContainers.POCKET_COMPUTER,
|
||||
GuiComputer::createPocket );
|
||||
ScreenRegistry.<ContainerComputerBase, NoTermComputerScreen<ContainerComputerBase>>register( ComputerCraftRegistry.ModContainers.POCKET_COMPUTER_NO_TERM,
|
||||
ScreenRegistry.<ContainerComputerBase, NoTermComputerScreen<ContainerComputerBase>>register( Registry.ModContainers.POCKET_COMPUTER_NO_TERM,
|
||||
NoTermComputerScreen::new );
|
||||
ScreenRegistry.<ContainerTurtle, GuiTurtle>register( ComputerCraftRegistry.ModContainers.TURTLE, GuiTurtle::new );
|
||||
ScreenRegistry.<ContainerTurtle, GuiTurtle>register( Registry.ModContainers.TURTLE, GuiTurtle::new );
|
||||
|
||||
ScreenRegistry.<ContainerPrinter, GuiPrinter>register( ComputerCraftRegistry.ModContainers.PRINTER, GuiPrinter::new );
|
||||
ScreenRegistry.<ContainerDiskDrive, GuiDiskDrive>register( ComputerCraftRegistry.ModContainers.DISK_DRIVE, GuiDiskDrive::new );
|
||||
ScreenRegistry.<ContainerHeldItem, GuiPrintout>register( ComputerCraftRegistry.ModContainers.PRINTOUT, GuiPrintout::new );
|
||||
ScreenRegistry.<ContainerPrinter, GuiPrinter>register( Registry.ModContainers.PRINTER, GuiPrinter::new );
|
||||
ScreenRegistry.<ContainerDiskDrive, GuiDiskDrive>register( Registry.ModContainers.DISK_DRIVE, GuiDiskDrive::new );
|
||||
ScreenRegistry.<ContainerHeldItem, GuiPrintout>register( Registry.ModContainers.PRINTOUT, GuiPrintout::new );
|
||||
|
||||
ScreenRegistry.<ContainerViewComputer, GuiComputer<ContainerViewComputer>>register( ComputerCraftRegistry.ModContainers.VIEW_COMPUTER,
|
||||
ScreenRegistry.<ContainerViewComputer, GuiComputer<ContainerViewComputer>>register( Registry.ModContainers.VIEW_COMPUTER,
|
||||
GuiComputer::createView );
|
||||
}
|
||||
|
||||
|
||||
@@ -3,14 +3,13 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client.render;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import com.mojang.math.Matrix3f;
|
||||
import com.mojang.math.Matrix4f;
|
||||
import dan200.computercraft.shared.ComputerCraftRegistry;
|
||||
import dan200.computercraft.shared.Registry;
|
||||
import dan200.computercraft.shared.peripheral.modem.wired.BlockCable;
|
||||
import dan200.computercraft.shared.peripheral.modem.wired.CableShapes;
|
||||
import dan200.computercraft.shared.util.WorldUtil;
|
||||
@@ -33,35 +32,34 @@ public final class CableHighlightRenderer
|
||||
{
|
||||
}
|
||||
|
||||
public static boolean drawHighlight( PoseStack stack, VertexConsumer consumer, Entity entity, double d, double e, double f, BlockPos pos,
|
||||
BlockState state )
|
||||
/*
|
||||
* Draw an outline for a specific part of a cable "Multipart".
|
||||
*
|
||||
* @see net.minecraft.client.renderer.LevelRenderer#renderHitOutline
|
||||
*/
|
||||
public static boolean drawHighlight( PoseStack stack, VertexConsumer buffer, Entity entity, double d, double e, double f, BlockPos pos, BlockState state )
|
||||
{
|
||||
HitResult hitResult = Minecraft.getInstance().hitResult;
|
||||
Camera info = Minecraft.getInstance().gameRenderer.getMainCamera();
|
||||
|
||||
// We only care about instances with both cable and modem.
|
||||
if( state.getBlock() != ComputerCraftRegistry.ModBlocks.CABLE || state.getValue( BlockCable.MODEM )
|
||||
.getFacing() == null || !state.getValue( BlockCable.CABLE ) )
|
||||
if( state.getBlock() != Registry.ModBlocks.CABLE || state.getValue( BlockCable.MODEM ).getFacing() == null || !state.getValue( BlockCable.CABLE ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
HitResult hitResult = Minecraft.getInstance().hitResult;
|
||||
|
||||
Vec3 hitPos = hitResult != null ? hitResult.getLocation() : new Vec3( d, e, f );
|
||||
|
||||
VoxelShape shape = WorldUtil.isVecInside( CableShapes.getModemShape( state ),
|
||||
hitPos.subtract( pos.getX(),
|
||||
pos.getY(),
|
||||
pos.getZ() ) ) ? CableShapes.getModemShape( state ) : CableShapes.getCableShape(
|
||||
state );
|
||||
VoxelShape shape = WorldUtil.isVecInside( CableShapes.getModemShape( state ), hitPos.subtract( pos.getX(), pos.getY(), pos.getZ() ) )
|
||||
? CableShapes.getModemShape( state )
|
||||
: CableShapes.getCableShape( state );
|
||||
|
||||
Vec3 cameraPos = info.getPosition();
|
||||
|
||||
double xOffset = pos.getX() - cameraPos.x();
|
||||
double yOffset = pos.getY() - cameraPos.y();
|
||||
double zOffset = pos.getZ() - cameraPos.z();
|
||||
Matrix4f matrix4f = stack.last()
|
||||
.pose();
|
||||
|
||||
Matrix4f matrix4f = stack.last().pose();
|
||||
Matrix3f normal = stack.last().normal();
|
||||
shape.forAllEdges( ( x1, y1, z1, x2, y2, z2 ) -> {
|
||||
float xDelta = (float) (x2 - x1);
|
||||
@@ -72,11 +70,13 @@ public final class CableHighlightRenderer
|
||||
yDelta = yDelta / len;
|
||||
zDelta = zDelta / len;
|
||||
|
||||
consumer.vertex( matrix4f, (float) (x1 + xOffset), (float) (y1 + yOffset), (float) (z1 + zOffset) )
|
||||
buffer
|
||||
.vertex( matrix4f, (float) (x1 + xOffset), (float) (y1 + yOffset), (float) (z1 + zOffset) )
|
||||
.color( 0, 0, 0, 0.4f )
|
||||
.normal( normal, xDelta, yDelta, zDelta )
|
||||
.endVertex();
|
||||
consumer.vertex( matrix4f, (float) (x2 + xOffset), (float) (y2 + yOffset), (float) (z2 + zOffset) )
|
||||
buffer
|
||||
.vertex( matrix4f, (float) (x2 + xOffset), (float) (y2 + yOffset), (float) (z2 + zOffset) )
|
||||
.color( 0, 0, 0, 0.4f )
|
||||
.normal( normal, xDelta, yDelta, zDelta )
|
||||
.endVertex();
|
||||
|
||||
@@ -22,15 +22,24 @@ public class ComputerBorderRenderer
|
||||
public static final ResourceLocation BACKGROUND_ADVANCED = new ResourceLocation( ComputerCraft.MOD_ID, "textures/gui/corners_advanced.png" );
|
||||
public static final ResourceLocation BACKGROUND_COMMAND = new ResourceLocation( ComputerCraft.MOD_ID, "textures/gui/corners_command.png" );
|
||||
public static final ResourceLocation BACKGROUND_COLOUR = new ResourceLocation( ComputerCraft.MOD_ID, "textures/gui/corners_colour.png" );
|
||||
|
||||
private static final Matrix4f IDENTITY = new Matrix4f();
|
||||
|
||||
static
|
||||
{
|
||||
IDENTITY.setIdentity();
|
||||
}
|
||||
|
||||
/**
|
||||
* The margin between the terminal and its border.
|
||||
*/
|
||||
public static final int MARGIN = 2;
|
||||
|
||||
/**
|
||||
* The width of the terminal border.
|
||||
*/
|
||||
public static final int BORDER = 12;
|
||||
private static final Matrix4f IDENTITY = new Matrix4f();
|
||||
|
||||
private static final int CORNER_TOP_Y = 28;
|
||||
private static final int CORNER_BOTTOM_Y = CORNER_TOP_Y + BORDER;
|
||||
private static final int CORNER_LEFT_X = BORDER;
|
||||
@@ -40,21 +49,16 @@ public class ComputerBorderRenderer
|
||||
private static final int LIGHT_CORNER_Y = 80;
|
||||
|
||||
public static final int LIGHT_HEIGHT = 8;
|
||||
|
||||
public static final int TEX_SIZE = 256;
|
||||
private static final float TEX_SCALE = 1 / (float) TEX_SIZE;
|
||||
|
||||
static
|
||||
{
|
||||
IDENTITY.setIdentity();
|
||||
}
|
||||
|
||||
private final Matrix4f transform;
|
||||
private final VertexConsumer builder;
|
||||
private final int light;
|
||||
private final int z;
|
||||
private final float r, g, b;
|
||||
|
||||
private final int light;
|
||||
|
||||
public ComputerBorderRenderer( Matrix4f transform, VertexConsumer builder, int z, int light, float r, float g, float b )
|
||||
{
|
||||
this.transform = transform;
|
||||
@@ -82,14 +86,19 @@ public class ComputerBorderRenderer
|
||||
}
|
||||
}
|
||||
|
||||
public static RenderType getRenderType( ResourceLocation location )
|
||||
{
|
||||
// See note in RenderTypes about why we use text rather than anything intuitive.
|
||||
return RenderType.text( location );
|
||||
}
|
||||
|
||||
public static void render( ResourceLocation location, int x, int y, int z, int light, int width, int height )
|
||||
{
|
||||
MultiBufferSource.BufferSource source = MultiBufferSource.immediate( Tesselator.getInstance().getBuilder() );
|
||||
render( IDENTITY, source.getBuffer( RenderType.text( location ) ), x, y, z, light, width, height, false, 1, 1, 1 );
|
||||
render( IDENTITY, source.getBuffer( getRenderType( location ) ), x, y, z, light, width, height, false, 1, 1, 1 );
|
||||
source.endBatch();
|
||||
}
|
||||
|
||||
|
||||
public static void render( Matrix4f transform, VertexConsumer buffer, int x, int y, int z, int light, int width, int height, boolean withLight, float r, float g, float b )
|
||||
{
|
||||
new ComputerBorderRenderer( transform, buffer, z, light, r, g, b ).doRender( x, y, width, height, withLight );
|
||||
@@ -125,16 +134,16 @@ public class ComputerBorderRenderer
|
||||
}
|
||||
}
|
||||
|
||||
private void renderLine( int x, int y, int u, int v, int width, int height )
|
||||
{
|
||||
renderTexture( x, y, u, v, width, height, BORDER, BORDER );
|
||||
}
|
||||
|
||||
private void renderCorner( int x, int y, int u, int v )
|
||||
{
|
||||
renderTexture( x, y, u, v, BORDER, BORDER, BORDER, BORDER );
|
||||
}
|
||||
|
||||
private void renderLine( int x, int y, int u, int v, int width, int height )
|
||||
{
|
||||
renderTexture( x, y, u, v, width, height, BORDER, BORDER );
|
||||
}
|
||||
|
||||
private void renderTexture( int x, int y, int u, int v, int width, int height )
|
||||
{
|
||||
renderTexture( x, y, u, v, width, height, width, height );
|
||||
@@ -142,25 +151,9 @@ public class ComputerBorderRenderer
|
||||
|
||||
private void renderTexture( int x, int y, int u, int v, int width, int height, int textureWidth, int textureHeight )
|
||||
{
|
||||
builder.vertex( transform, x, y + height, z )
|
||||
.color( r, g, b, 1.0f )
|
||||
.uv( u * TEX_SCALE, (v + textureHeight) * TEX_SCALE )
|
||||
.uv2( light )
|
||||
.endVertex();
|
||||
builder.vertex( transform, x + width, y + height, z )
|
||||
.color( r, g, b, 1.0f )
|
||||
.uv( (u + textureWidth) * TEX_SCALE, (v + textureHeight) * TEX_SCALE )
|
||||
.uv2( light )
|
||||
.endVertex();
|
||||
builder.vertex( transform, x + width, y, z )
|
||||
.color( r, g, b, 1.0f )
|
||||
.uv( (u + textureWidth) * TEX_SCALE, v * TEX_SCALE )
|
||||
.uv2( light )
|
||||
.endVertex();
|
||||
builder.vertex( transform, x, y, z )
|
||||
.color( r, g, b, 1.0f )
|
||||
.uv( u * TEX_SCALE, v * TEX_SCALE )
|
||||
.uv2( light )
|
||||
.endVertex();
|
||||
builder.vertex( transform, x, y + height, z ).color( r, g, b, 1.0f ).uv( u * TEX_SCALE, (v + textureHeight) * TEX_SCALE ).uv2( light ).endVertex();
|
||||
builder.vertex( transform, x + width, y + height, z ).color( r, g, b, 1.0f ).uv( (u + textureWidth) * TEX_SCALE, (v + textureHeight) * TEX_SCALE ).uv2( light ).endVertex();
|
||||
builder.vertex( transform, x + width, y, z ).color( r, g, b, 1.0f ).uv( (u + textureWidth) * TEX_SCALE, v * TEX_SCALE ).uv2( light ).endVertex();
|
||||
builder.vertex( transform, x, y, z ).color( r, g, b, 1.0f ).uv( u * TEX_SCALE, v * TEX_SCALE ).uv2( light ).endVertex();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,30 +3,36 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client.render;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.math.Vector3f;
|
||||
import dan200.computercraft.fabric.mixin.ItemInHandRendererAccess;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.ItemInHandRenderer;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.block.model.ItemTransforms;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.entity.HumanoidArm;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
@Environment( EnvType.CLIENT )
|
||||
public abstract class ItemMapLikeRenderer
|
||||
{
|
||||
public void renderItemFirstPerson(
|
||||
PoseStack transform, MultiBufferSource render, int lightTexture, InteractionHand hand, float pitch, float equipProgress,
|
||||
float swingProgress, ItemStack stack
|
||||
)
|
||||
/**
|
||||
* The main rendering method for the item.
|
||||
*
|
||||
* @param transform The matrix transformation stack
|
||||
* @param render The buffer to render to
|
||||
* @param stack The stack to render
|
||||
* @param light The packed lightmap coordinates.
|
||||
* @see ItemInHandRenderer#renderItem(LivingEntity, ItemStack, ItemTransforms.TransformType, boolean, PoseStack, MultiBufferSource, int)
|
||||
*/
|
||||
protected abstract void renderItem( PoseStack transform, MultiBufferSource render, ItemStack stack, int light );
|
||||
|
||||
public void renderItemFirstPerson( PoseStack transform, MultiBufferSource render, int lightTexture, InteractionHand hand, float pitch, float equipProgress, float swingProgress, ItemStack stack )
|
||||
{
|
||||
Player player = Minecraft.getInstance().player;
|
||||
|
||||
@@ -37,17 +43,60 @@ public abstract class ItemMapLikeRenderer
|
||||
}
|
||||
else
|
||||
{
|
||||
renderItemFirstPersonSide( transform,
|
||||
render,
|
||||
lightTexture,
|
||||
renderItemFirstPersonSide(
|
||||
transform, render, lightTexture,
|
||||
hand == InteractionHand.MAIN_HAND ? player.getMainArm() : player.getMainArm().getOpposite(),
|
||||
equipProgress,
|
||||
swingProgress,
|
||||
stack );
|
||||
equipProgress, swingProgress, stack
|
||||
);
|
||||
}
|
||||
transform.popPose();
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the item to one side of the player.
|
||||
*
|
||||
* @param transform The matrix transformation stack
|
||||
* @param render The buffer to render to
|
||||
* @param combinedLight The current light level
|
||||
* @param side The side to render on
|
||||
* @param equipProgress The equip progress of this item
|
||||
* @param swingProgress The swing progress of this item
|
||||
* @param stack The stack to render
|
||||
* @see ItemInHandRenderer#renderOneHandedMap(PoseStack, MultiBufferSource, int, float, HumanoidArm, float, ItemStack)
|
||||
*/
|
||||
private void renderItemFirstPersonSide( PoseStack transform, MultiBufferSource render, int combinedLight, HumanoidArm side, float equipProgress, float swingProgress, ItemStack stack )
|
||||
{
|
||||
Minecraft minecraft = Minecraft.getInstance();
|
||||
float offset = side == HumanoidArm.RIGHT ? 1f : -1f;
|
||||
transform.translate( offset * 0.125f, -0.125f, 0f );
|
||||
|
||||
// If the player is not invisible then render a single arm
|
||||
if( !minecraft.player.isInvisible() )
|
||||
{
|
||||
transform.pushPose();
|
||||
transform.mulPose( Vector3f.ZP.rotationDegrees( offset * 10f ) );
|
||||
((ItemInHandRendererAccess) minecraft.getItemInHandRenderer()).callRenderPlayerArm( transform, render, combinedLight, equipProgress, swingProgress, side );
|
||||
transform.popPose();
|
||||
}
|
||||
|
||||
// Setup the appropriate transformations. This is just copied from the
|
||||
// corresponding method in ItemRenderer.
|
||||
transform.pushPose();
|
||||
transform.translate( offset * 0.51f, -0.08f + equipProgress * -1.2f, -0.75f );
|
||||
float f1 = Mth.sqrt( swingProgress );
|
||||
float f2 = Mth.sin( f1 * (float) Math.PI );
|
||||
float f3 = -0.5f * f2;
|
||||
float f4 = 0.4f * Mth.sin( f1 * ((float) Math.PI * 2f) );
|
||||
float f5 = -0.3f * Mth.sin( swingProgress * (float) Math.PI );
|
||||
transform.translate( offset * f3, f4 - 0.3f * f2, f5 );
|
||||
transform.mulPose( Vector3f.XP.rotationDegrees( f2 * -45f ) );
|
||||
transform.mulPose( Vector3f.YP.rotationDegrees( offset * f2 * -30f ) );
|
||||
|
||||
renderItem( transform, render, stack, combinedLight );
|
||||
|
||||
transform.popPose();
|
||||
}
|
||||
|
||||
/**
|
||||
* Render an item in the middle of the screen.
|
||||
*
|
||||
@@ -58,9 +107,9 @@ public abstract class ItemMapLikeRenderer
|
||||
* @param equipProgress The equip progress of this item
|
||||
* @param swingProgress The swing progress of this item
|
||||
* @param stack The stack to render
|
||||
* @see ItemInHandRenderer#renderTwoHandedMap(PoseStack, MultiBufferSource, int, float, float, float)
|
||||
*/
|
||||
private void renderItemFirstPersonCenter( PoseStack transform, MultiBufferSource render, int combinedLight, float pitch, float equipProgress,
|
||||
float swingProgress, ItemStack stack )
|
||||
private void renderItemFirstPersonCenter( PoseStack transform, MultiBufferSource render, int combinedLight, float pitch, float equipProgress, float swingProgress, ItemStack stack )
|
||||
{
|
||||
Minecraft minecraft = Minecraft.getInstance();
|
||||
ItemInHandRenderer renderer = minecraft.getItemInHandRenderer();
|
||||
@@ -91,60 +140,4 @@ public abstract class ItemMapLikeRenderer
|
||||
|
||||
renderItem( transform, render, stack, combinedLight );
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the item to one side of the player.
|
||||
*
|
||||
* @param transform The matrix transformation stack
|
||||
* @param render The buffer to render to
|
||||
* @param combinedLight The current light level
|
||||
* @param side The side to render on
|
||||
* @param equipProgress The equip progress of this item
|
||||
* @param swingProgress The swing progress of this item
|
||||
* @param stack The stack to render
|
||||
*/
|
||||
private void renderItemFirstPersonSide( PoseStack transform, MultiBufferSource render, int combinedLight, HumanoidArm side, float equipProgress,
|
||||
float swingProgress, ItemStack stack )
|
||||
{
|
||||
Minecraft minecraft = Minecraft.getInstance();
|
||||
float offset = side == HumanoidArm.RIGHT ? 1f : -1f;
|
||||
transform.translate( offset * 0.125f, -0.125f, 0f );
|
||||
|
||||
// If the player is not invisible then render a single arm
|
||||
if( !minecraft.player.isInvisible() )
|
||||
{
|
||||
transform.pushPose();
|
||||
transform.mulPose( Vector3f.ZP.rotationDegrees( offset * 10f ) );
|
||||
((ItemInHandRendererAccess) minecraft.getItemInHandRenderer())
|
||||
.callRenderPlayerArm( transform, render, combinedLight, equipProgress, swingProgress, side );
|
||||
transform.popPose();
|
||||
}
|
||||
|
||||
// Setup the appropriate transformations. This is just copied from the
|
||||
// corresponding method in ItemRenderer.
|
||||
transform.pushPose();
|
||||
transform.translate( offset * 0.51f, -0.08f + equipProgress * -1.2f, -0.75f );
|
||||
float f1 = Mth.sqrt( swingProgress );
|
||||
float f2 = Mth.sin( f1 * (float) Math.PI );
|
||||
float f3 = -0.5f * f2;
|
||||
float f4 = 0.4f * Mth.sin( f1 * ((float) Math.PI * 2f) );
|
||||
float f5 = -0.3f * Mth.sin( swingProgress * (float) Math.PI );
|
||||
transform.translate( offset * f3, f4 - 0.3f * f2, f5 );
|
||||
transform.mulPose( Vector3f.XP.rotationDegrees( f2 * -45f ) );
|
||||
transform.mulPose( Vector3f.YP.rotationDegrees( offset * f2 * -30f ) );
|
||||
|
||||
renderItem( transform, render, stack, combinedLight );
|
||||
|
||||
transform.popPose();
|
||||
}
|
||||
|
||||
/**
|
||||
* The main rendering method for the item.
|
||||
*
|
||||
* @param transform The matrix transformation stack
|
||||
* @param render The buffer to render to
|
||||
* @param stack The stack to render
|
||||
* @param light TODO rebase
|
||||
*/
|
||||
protected abstract void renderItem( PoseStack transform, MultiBufferSource render, ItemStack stack, int light );
|
||||
}
|
||||
|
||||
@@ -3,10 +3,8 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client.render;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.*;
|
||||
import com.mojang.math.Matrix4f;
|
||||
import com.mojang.math.Vector3f;
|
||||
@@ -17,9 +15,7 @@ import dan200.computercraft.shared.computer.core.ClientComputer;
|
||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
|
||||
import dan200.computercraft.shared.util.Colour;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
@@ -39,7 +35,7 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderItem( PoseStack transform, MultiBufferSource render, ItemStack stack, int light )
|
||||
protected void renderItem( PoseStack transform, MultiBufferSource renderer, ItemStack stack, int light )
|
||||
{
|
||||
ClientComputer computer = ItemPocketComputer.createClientComputer( stack );
|
||||
Terminal terminal = computer == null ? null : computer.getTerminal();
|
||||
@@ -67,7 +63,7 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
|
||||
transform.scale( 0.5f, 0.5f, 0.5f );
|
||||
|
||||
float scale = 0.75f / Math.max( width + BORDER * 2, height + BORDER * 2 + LIGHT_HEIGHT );
|
||||
transform.scale( scale, scale, 0 );
|
||||
transform.scale( scale, scale, -1.0f );
|
||||
transform.translate( -0.5 * width, -0.5 * height, 0 );
|
||||
|
||||
// Render the main frame
|
||||
@@ -75,26 +71,21 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
|
||||
ComputerFamily family = item.getFamily();
|
||||
int frameColour = item.getColour( stack );
|
||||
|
||||
Matrix4f matrix = transform.last()
|
||||
.pose();
|
||||
renderFrame( matrix, render, family, frameColour, light, width, height );
|
||||
Matrix4f matrix = transform.last().pose();
|
||||
renderFrame( matrix, renderer, family, frameColour, light, width, height );
|
||||
|
||||
// Render the light
|
||||
int lightColour = ItemPocketComputer.getLightState( stack );
|
||||
if( lightColour == -1 )
|
||||
{
|
||||
lightColour = Colour.BLACK.getHex();
|
||||
}
|
||||
renderLight( matrix, lightColour, width, height );
|
||||
if( lightColour == -1 ) lightColour = Colour.BLACK.getHex();
|
||||
renderLight( matrix, renderer, lightColour, width, height );
|
||||
|
||||
if( computer != null && terminal != null )
|
||||
{
|
||||
FixedWidthFontRenderer.drawTerminal(
|
||||
matrix, render.getBuffer( RenderTypes.TERMINAL_WITHOUT_DEPTH ),
|
||||
matrix, renderer.getBuffer( RenderTypes.TERMINAL_WITHOUT_DEPTH ),
|
||||
MARGIN, MARGIN, terminal, !computer.isColour(), MARGIN, MARGIN, MARGIN, MARGIN
|
||||
);
|
||||
FixedWidthFontRenderer.drawBlocker( transform.last().pose(), render, 0, 0, width, height );
|
||||
|
||||
FixedWidthFontRenderer.drawBlocker( transform.last().pose(), renderer, 0, 0, width, height );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -106,45 +97,26 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
|
||||
|
||||
private static void renderFrame( Matrix4f transform, MultiBufferSource render, ComputerFamily family, int colour, int light, int width, int height )
|
||||
{
|
||||
RenderSystem.enableBlend();
|
||||
Minecraft.getInstance()
|
||||
.getTextureManager()
|
||||
.bindForSetup( colour != -1 ? ComputerBorderRenderer.BACKGROUND_COLOUR : ComputerBorderRenderer.getTexture( family ) );
|
||||
|
||||
ResourceLocation texture = colour != -1 ? ComputerBorderRenderer.BACKGROUND_COLOUR : ComputerBorderRenderer.getTexture( family );
|
||||
|
||||
float r = ((colour >>> 16) & 0xFF) / 255.0f;
|
||||
float g = ((colour >>> 8) & 0xFF) / 255.0f;
|
||||
float b = (colour & 0xFF) / 255.0f;
|
||||
|
||||
ComputerBorderRenderer.render( transform, render.getBuffer( RenderType.text( texture ) ), 0, 0, 0, light, width, height, true, r, g, b );
|
||||
ComputerBorderRenderer.render( transform, render.getBuffer( ComputerBorderRenderer.getRenderType( texture ) ), 0, 0, 0, light, width, height, true, r, g, b );
|
||||
}
|
||||
|
||||
private static void renderLight( Matrix4f transform, int colour, int width, int height )
|
||||
private static void renderLight( Matrix4f transform, MultiBufferSource render, int colour, int width, int height )
|
||||
{
|
||||
RenderSystem.disableTexture();
|
||||
|
||||
float r = ((colour >>> 16) & 0xFF) / 255.0f;
|
||||
float g = ((colour >>> 8) & 0xFF) / 255.0f;
|
||||
float b = (colour & 0xFF) / 255.0f;
|
||||
float z = 0.001f;
|
||||
|
||||
Tesselator tessellator = Tesselator.getInstance();
|
||||
BufferBuilder buffer = tessellator.getBuilder();
|
||||
buffer.begin( VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR );
|
||||
buffer.vertex( transform, width - LIGHT_HEIGHT * 2, height + LIGHT_HEIGHT + BORDER / 2.0f, 0 )
|
||||
.color( r, g, b, 1.0f )
|
||||
.endVertex();
|
||||
buffer.vertex( transform, width, height + LIGHT_HEIGHT + BORDER / 2.0f, 0 )
|
||||
.color( r, g, b, 1.0f )
|
||||
.endVertex();
|
||||
buffer.vertex( transform, width, height + BORDER / 2.0f, 0 )
|
||||
.color( r, g, b, 1.0f )
|
||||
.endVertex();
|
||||
buffer.vertex( transform, width - LIGHT_HEIGHT * 2, height + BORDER / 2.0f, 0 )
|
||||
.color( r, g, b, 1.0f )
|
||||
.endVertex();
|
||||
|
||||
tessellator.end();
|
||||
RenderSystem.enableTexture();
|
||||
VertexConsumer buffer = render.getBuffer( RenderTypes.POSITION_COLOR );
|
||||
buffer.vertex( transform, width - LIGHT_HEIGHT * 2, height + LIGHT_HEIGHT + BORDER / 2.0f, z ).color( r, g, b, 1.0f ).endVertex();
|
||||
buffer.vertex( transform, width, height + LIGHT_HEIGHT + BORDER / 2.0f, z ).color( r, g, b, 1.0f ).endVertex();
|
||||
buffer.vertex( transform, width, height + BORDER / 2.0f, z ).color( r, g, b, 1.0f ).endVertex();
|
||||
buffer.vertex( transform, width - LIGHT_HEIGHT * 2, height + BORDER / 2.0f, z ).color( r, g, b, 1.0f ).endVertex();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client.render;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
@@ -30,6 +29,21 @@ public final class ItemPrintoutRenderer extends ItemMapLikeRenderer
|
||||
{
|
||||
}
|
||||
|
||||
public boolean renderInFrame( PoseStack matrixStack, MultiBufferSource consumerProvider, ItemStack stack, int light )
|
||||
{
|
||||
if( !(stack.getItem() instanceof ItemPrintout) ) return false;
|
||||
|
||||
// Move a little bit forward to ensure we're not clipping with the frame
|
||||
matrixStack.translate( 0.0f, 0.0f, -0.001f );
|
||||
matrixStack.mulPose( Vector3f.ZP.rotationDegrees( 180f ) );
|
||||
matrixStack.scale( 0.95f, 0.95f, -0.95f );
|
||||
matrixStack.translate( -0.5f, -0.5f, 0.0f );
|
||||
|
||||
drawPrintout( matrixStack, consumerProvider, stack, light );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderItem( PoseStack transform, MultiBufferSource render, ItemStack stack, int light )
|
||||
{
|
||||
@@ -49,10 +63,7 @@ public final class ItemPrintoutRenderer extends ItemMapLikeRenderer
|
||||
double height = LINES_PER_PAGE * FONT_HEIGHT + Y_TEXT_MARGIN * 2;
|
||||
|
||||
// Non-books will be left aligned
|
||||
if( !book )
|
||||
{
|
||||
width += offsetAt( pages );
|
||||
}
|
||||
if( !book ) width += offsetAt( pages );
|
||||
|
||||
double visualWidth = width, visualHeight = height;
|
||||
|
||||
@@ -70,27 +81,11 @@ public final class ItemPrintoutRenderer extends ItemMapLikeRenderer
|
||||
transform.scale( scale, scale, scale );
|
||||
transform.translate( (max - width) / 2.0, (max - height) / 2.0, 0.0 );
|
||||
|
||||
Matrix4f matrix = transform.last()
|
||||
.pose();
|
||||
Matrix4f matrix = transform.last().pose();
|
||||
drawBorder( matrix, render, 0, 0, -0.01f, 0, pages, book, light );
|
||||
drawText( matrix, render, X_TEXT_MARGIN, Y_TEXT_MARGIN, 0, light, ItemPrintout.getText( stack ), ItemPrintout.getColours( stack ) );
|
||||
}
|
||||
|
||||
public boolean renderInFrame( PoseStack matrixStack, MultiBufferSource consumerProvider, ItemStack stack, int light )
|
||||
{
|
||||
if( !(stack.getItem() instanceof ItemPrintout) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Move a little bit forward to ensure we're not clipping with the frame
|
||||
matrixStack.translate( 0.0f, 0.0f, -0.001f );
|
||||
matrixStack.mulPose( Vector3f.ZP.rotationDegrees( 180f ) );
|
||||
matrixStack.scale( 0.95f, 0.95f, -0.95f );
|
||||
matrixStack.translate( -0.5f, -0.5f, 0.0f );
|
||||
|
||||
drawPrintout( matrixStack, consumerProvider, stack, light );
|
||||
|
||||
return true;
|
||||
drawText(
|
||||
matrix, render, X_TEXT_MARGIN, Y_TEXT_MARGIN, 0, light,
|
||||
ItemPrintout.getText( stack ), ItemPrintout.getColours( stack )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client.render;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
@@ -27,8 +26,8 @@ import java.util.EnumSet;
|
||||
import static net.minecraft.core.Direction.*;
|
||||
|
||||
/**
|
||||
* Overrides monitor highlighting to only render the outline of the <em>whole</em> monitor, rather than the current block. This means you do not get an
|
||||
* intrusive outline on top of the screen.
|
||||
* Overrides monitor highlighting to only render the outline of the <em>whole</em> monitor, rather than the current
|
||||
* block. This means you do not get an intrusive outline on top of the screen.
|
||||
*/
|
||||
@Environment( EnvType.CLIENT )
|
||||
public final class MonitorHighlightRenderer
|
||||
@@ -37,115 +36,62 @@ public final class MonitorHighlightRenderer
|
||||
{
|
||||
}
|
||||
|
||||
public static boolean drawHighlight( PoseStack matrixStack, VertexConsumer vertexConsumer, Entity entity, double d, double e, double f, BlockPos pos, BlockState blockState )
|
||||
public static boolean drawHighlight( PoseStack transformStack, VertexConsumer buffer, Entity entity, double d, double e, double f, BlockPos pos, BlockState blockState )
|
||||
{
|
||||
// Preserve normal behaviour when crouching.
|
||||
if( entity.isCrouching() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if( entity.isCrouching() ) return false;
|
||||
|
||||
Level world = entity.getCommandSenderWorld();
|
||||
|
||||
BlockEntity tile = world.getBlockEntity( pos );
|
||||
if( !(tile instanceof TileMonitor monitor) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if( !(tile instanceof TileMonitor monitor) ) return false;
|
||||
|
||||
// Determine which sides are part of the external faces of the monitor, and so which need to be rendered.
|
||||
EnumSet<Direction> faces = EnumSet.allOf( Direction.class );
|
||||
Direction front = monitor.getFront();
|
||||
faces.remove( front );
|
||||
if( monitor.getXIndex() != 0 )
|
||||
{
|
||||
faces.remove( monitor.getRight()
|
||||
.getOpposite() );
|
||||
}
|
||||
if( monitor.getXIndex() != monitor.getWidth() - 1 )
|
||||
{
|
||||
faces.remove( monitor.getRight() );
|
||||
}
|
||||
if( monitor.getYIndex() != 0 )
|
||||
{
|
||||
faces.remove( monitor.getDown()
|
||||
.getOpposite() );
|
||||
}
|
||||
if( monitor.getYIndex() != monitor.getHeight() - 1 )
|
||||
{
|
||||
faces.remove( monitor.getDown() );
|
||||
}
|
||||
if( monitor.getXIndex() != 0 ) faces.remove( monitor.getRight().getOpposite() );
|
||||
if( monitor.getXIndex() != monitor.getWidth() - 1 ) faces.remove( monitor.getRight() );
|
||||
if( monitor.getYIndex() != 0 ) faces.remove( monitor.getDown().getOpposite() );
|
||||
if( monitor.getYIndex() != monitor.getHeight() - 1 ) faces.remove( monitor.getDown() );
|
||||
|
||||
Vec3 cameraPos = Minecraft.getInstance().gameRenderer.getMainCamera()
|
||||
.getPosition();
|
||||
matrixStack.pushPose();
|
||||
matrixStack.translate( pos.getX() - cameraPos.x(), pos.getY() - cameraPos.y(), pos.getZ() - cameraPos.z() );
|
||||
Vec3 cameraPos = Minecraft.getInstance().gameRenderer.getMainCamera().getPosition();
|
||||
transformStack.pushPose();
|
||||
transformStack.translate( pos.getX() - cameraPos.x(), pos.getY() - cameraPos.y(), pos.getZ() - cameraPos.z() );
|
||||
|
||||
// I wish I could think of a better way to do this
|
||||
Matrix4f transform = matrixStack.last()
|
||||
.pose();
|
||||
Matrix3f normal = matrixStack.last().normal();
|
||||
if( faces.contains( NORTH ) || faces.contains( WEST ) )
|
||||
{
|
||||
line( vertexConsumer, transform, normal, 0, 0, 0, UP );
|
||||
}
|
||||
if( faces.contains( SOUTH ) || faces.contains( WEST ) )
|
||||
{
|
||||
line( vertexConsumer, transform, normal, 0, 0, 1, UP );
|
||||
}
|
||||
if( faces.contains( NORTH ) || faces.contains( EAST ) )
|
||||
{
|
||||
line( vertexConsumer, transform, normal, 1, 0, 0, UP );
|
||||
}
|
||||
if( faces.contains( SOUTH ) || faces.contains( EAST ) )
|
||||
{
|
||||
line( vertexConsumer, transform, normal, 1, 0, 1, UP );
|
||||
}
|
||||
if( faces.contains( NORTH ) || faces.contains( DOWN ) )
|
||||
{
|
||||
line( vertexConsumer, transform, normal, 0, 0, 0, EAST );
|
||||
}
|
||||
if( faces.contains( SOUTH ) || faces.contains( DOWN ) )
|
||||
{
|
||||
line( vertexConsumer, transform, normal, 0, 0, 1, EAST );
|
||||
}
|
||||
if( faces.contains( NORTH ) || faces.contains( UP ) )
|
||||
{
|
||||
line( vertexConsumer, transform, normal, 0, 1, 0, EAST );
|
||||
}
|
||||
if( faces.contains( SOUTH ) || faces.contains( UP ) )
|
||||
{
|
||||
line( vertexConsumer, transform, normal, 0, 1, 1, EAST );
|
||||
}
|
||||
if( faces.contains( WEST ) || faces.contains( DOWN ) )
|
||||
{
|
||||
line( vertexConsumer, transform, normal, 0, 0, 0, SOUTH );
|
||||
}
|
||||
if( faces.contains( EAST ) || faces.contains( DOWN ) )
|
||||
{
|
||||
line( vertexConsumer, transform, normal, 1, 0, 0, SOUTH );
|
||||
}
|
||||
if( faces.contains( WEST ) || faces.contains( UP ) )
|
||||
{
|
||||
line( vertexConsumer, transform, normal, 0, 1, 0, SOUTH );
|
||||
}
|
||||
if( faces.contains( EAST ) || faces.contains( UP ) )
|
||||
{
|
||||
line( vertexConsumer, transform, normal, 1, 1, 0, SOUTH );
|
||||
}
|
||||
|
||||
matrixStack.popPose();
|
||||
Matrix4f transform = transformStack.last().pose();
|
||||
Matrix3f normal = transformStack.last().normal();
|
||||
if( faces.contains( NORTH ) || faces.contains( WEST ) ) line( buffer, transform, normal, 0, 0, 0, UP );
|
||||
if( faces.contains( SOUTH ) || faces.contains( WEST ) ) line( buffer, transform, normal, 0, 0, 1, UP );
|
||||
if( faces.contains( NORTH ) || faces.contains( EAST ) ) line( buffer, transform, normal, 1, 0, 0, UP );
|
||||
if( faces.contains( SOUTH ) || faces.contains( EAST ) ) line( buffer, transform, normal, 1, 0, 1, UP );
|
||||
if( faces.contains( NORTH ) || faces.contains( DOWN ) ) line( buffer, transform, normal, 0, 0, 0, EAST );
|
||||
if( faces.contains( SOUTH ) || faces.contains( DOWN ) ) line( buffer, transform, normal, 0, 0, 1, EAST );
|
||||
if( faces.contains( NORTH ) || faces.contains( UP ) ) line( buffer, transform, normal, 0, 1, 0, EAST );
|
||||
if( faces.contains( SOUTH ) || faces.contains( UP ) ) line( buffer, transform, normal, 0, 1, 1, EAST );
|
||||
if( faces.contains( WEST ) || faces.contains( DOWN ) ) line( buffer, transform, normal, 0, 0, 0, SOUTH );
|
||||
if( faces.contains( EAST ) || faces.contains( DOWN ) ) line( buffer, transform, normal, 1, 0, 0, SOUTH );
|
||||
if( faces.contains( WEST ) || faces.contains( UP ) ) line( buffer, transform, normal, 0, 1, 0, SOUTH );
|
||||
if( faces.contains( EAST ) || faces.contains( UP ) ) line( buffer, transform, normal, 1, 1, 0, SOUTH );
|
||||
|
||||
transformStack.popPose();
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void line( VertexConsumer buffer, Matrix4f transform, Matrix3f normal, float x, float y, float z, Direction direction )
|
||||
{
|
||||
buffer.vertex( transform, x, y, z )
|
||||
buffer
|
||||
.vertex( transform, x, y, z )
|
||||
.color( 0, 0, 0, 0.4f )
|
||||
.normal( normal, direction.getStepX(), direction.getStepY(), direction.getStepZ() )
|
||||
.endVertex();
|
||||
buffer.vertex( transform, x + direction.getStepX(), y + direction.getStepY(), z + direction.getStepZ() )
|
||||
buffer
|
||||
.vertex( transform,
|
||||
x + direction.getStepX(),
|
||||
y + direction.getStepY(),
|
||||
z + direction.getStepZ()
|
||||
)
|
||||
.color( 0, 0, 0, 0.4f )
|
||||
.normal( normal, direction.getStepX(), direction.getStepY(), direction.getStepZ() )
|
||||
.endVertex();
|
||||
|
||||
@@ -29,13 +29,13 @@ public class MonitorTextureBufferShader extends ShaderInstance
|
||||
private final Uniform width;
|
||||
private final Uniform height;
|
||||
|
||||
public MonitorTextureBufferShader( ResourceProvider factory, String name, VertexFormat format ) throws IOException
|
||||
public MonitorTextureBufferShader( ResourceProvider provider, String name, VertexFormat format ) throws IOException
|
||||
{
|
||||
super( factory, name, format );
|
||||
super( provider, name, format );
|
||||
|
||||
width = getUniformChecked( "Width" );
|
||||
height = getUniformChecked( "Height" );
|
||||
palette = new Uniform( "Palette", Uniform.UT_FLOAT3 /* UT_FLOAT3 */, 16 * 3, this );
|
||||
palette = new Uniform( "Palette", Uniform.UT_FLOAT3, 16 * 3, this );
|
||||
updateUniformLocation( palette );
|
||||
|
||||
Uniform tbo = getUniformChecked( "Tbo" );
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client.render;
|
||||
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
@@ -18,31 +17,38 @@ import static dan200.computercraft.shared.media.items.ItemPrintout.LINES_PER_PAG
|
||||
|
||||
public final class PrintoutRenderer
|
||||
{
|
||||
private static final float BG_SIZE = 256.0f;
|
||||
|
||||
/**
|
||||
* Width of a page.
|
||||
*/
|
||||
public static final int X_SIZE = 172;
|
||||
|
||||
/**
|
||||
* Height of a page.
|
||||
*/
|
||||
public static final int Y_SIZE = 209;
|
||||
|
||||
/**
|
||||
* Padding between the left and right of a page and the text.
|
||||
*/
|
||||
public static final int X_TEXT_MARGIN = 13;
|
||||
|
||||
/**
|
||||
* Padding between the top and bottom of a page and the text.
|
||||
*/
|
||||
public static final int Y_TEXT_MARGIN = 11;
|
||||
/**
|
||||
* Size of the leather cover.
|
||||
*/
|
||||
public static final int COVER_SIZE = 12;
|
||||
private static final float BG_SIZE = 256.0f;
|
||||
|
||||
/**
|
||||
* Width of the extra page texture.
|
||||
*/
|
||||
private static final int X_FOLD_SIZE = 12;
|
||||
|
||||
/**
|
||||
* Size of the leather cover.
|
||||
*/
|
||||
public static final int COVER_SIZE = 12;
|
||||
|
||||
private static final int COVER_Y = Y_SIZE;
|
||||
private static final int COVER_X = X_SIZE + 4 * X_FOLD_SIZE;
|
||||
|
||||
@@ -53,18 +59,11 @@ public final class PrintoutRenderer
|
||||
VertexConsumer buffer = renderer.getBuffer( RenderTypes.PRINTOUT_TEXT );
|
||||
for( int line = 0; line < LINES_PER_PAGE && line < text.length; line++ )
|
||||
{
|
||||
FixedWidthFontRenderer.drawString( transform,
|
||||
buffer,
|
||||
x,
|
||||
y + line * FONT_HEIGHT,
|
||||
text[start + line],
|
||||
colours[start + line],
|
||||
null,
|
||||
Palette.DEFAULT,
|
||||
false,
|
||||
0,
|
||||
0,
|
||||
light );
|
||||
FixedWidthFontRenderer.drawString( transform, buffer,
|
||||
x, y + line * FONT_HEIGHT, text[start + line], colours[start + line], null, Palette.DEFAULT,
|
||||
false, 0, 0,
|
||||
light
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,18 +72,12 @@ public final class PrintoutRenderer
|
||||
VertexConsumer buffer = renderer.getBuffer( RenderTypes.PRINTOUT_TEXT );
|
||||
for( int line = 0; line < LINES_PER_PAGE && line < text.length; line++ )
|
||||
{
|
||||
FixedWidthFontRenderer.drawString( transform,
|
||||
buffer,
|
||||
x,
|
||||
y + line * FONT_HEIGHT,
|
||||
new TextBuffer( text[start + line] ),
|
||||
new TextBuffer( colours[start + line] ),
|
||||
null,
|
||||
Palette.DEFAULT,
|
||||
false,
|
||||
0,
|
||||
0,
|
||||
light );
|
||||
FixedWidthFontRenderer.drawString( transform, buffer,
|
||||
x, y + line * FONT_HEIGHT,
|
||||
new TextBuffer( text[start + line] ), new TextBuffer( colours[start + line] ),
|
||||
null, Palette.DEFAULT, false, 0, 0,
|
||||
light
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,18 +100,11 @@ public final class PrintoutRenderer
|
||||
drawTexture( transform, buffer, right, y - 8, z - 0.02f, COVER_X + COVER_SIZE, 0, COVER_SIZE, Y_SIZE + COVER_SIZE * 2, light );
|
||||
|
||||
// Draw centre panel (just stretched texture, sorry).
|
||||
drawTexture( transform,
|
||||
buffer,
|
||||
x - offset,
|
||||
y,
|
||||
z - 0.02f,
|
||||
X_SIZE + offset * 2,
|
||||
Y_SIZE,
|
||||
COVER_X + COVER_SIZE / 2.0f,
|
||||
COVER_SIZE,
|
||||
COVER_SIZE,
|
||||
Y_SIZE,
|
||||
light );
|
||||
drawTexture( transform, buffer,
|
||||
x - offset, y, z - 0.02f, X_SIZE + offset * 2, Y_SIZE,
|
||||
COVER_X + COVER_SIZE / 2.0f, COVER_SIZE, COVER_SIZE, Y_SIZE,
|
||||
light
|
||||
);
|
||||
|
||||
float borderX = left;
|
||||
while( borderX < right )
|
||||
@@ -134,26 +120,27 @@ public final class PrintoutRenderer
|
||||
drawTexture( transform, buffer, x, y, z, X_FOLD_SIZE * 2, 0, X_SIZE / 2.0f, Y_SIZE, light );
|
||||
for( int n = 0; n <= leftPages; n++ )
|
||||
{
|
||||
drawTexture( transform, buffer, x - offsetAt( n ), y, z - 1e-3f * n,
|
||||
drawTexture( transform, buffer,
|
||||
x - offsetAt( n ), y, z - 1e-3f * n,
|
||||
// Use the left "bold" fold for the outermost page
|
||||
n == leftPages ? 0 : X_FOLD_SIZE, 0, X_FOLD_SIZE, Y_SIZE, light );
|
||||
n == leftPages ? 0 : X_FOLD_SIZE, 0,
|
||||
X_FOLD_SIZE, Y_SIZE, light
|
||||
);
|
||||
}
|
||||
|
||||
// Right half
|
||||
drawTexture( transform, buffer, x + X_SIZE / 2.0f, y, z, X_FOLD_SIZE * 2 + X_SIZE / 2.0f, 0, X_SIZE / 2.0f, Y_SIZE, light );
|
||||
for( int n = 0; n <= rightPages; n++ )
|
||||
{
|
||||
drawTexture( transform, buffer, x + (X_SIZE - X_FOLD_SIZE) + offsetAt( n ), y, z - 1e-3f * n,
|
||||
drawTexture( transform, buffer,
|
||||
x + (X_SIZE - X_FOLD_SIZE) + offsetAt( n ), y, z - 1e-3f * n,
|
||||
// Two folds, then the main page. Use the right "bold" fold for the outermost page.
|
||||
X_FOLD_SIZE * 2 + X_SIZE + (n == rightPages ? X_FOLD_SIZE : 0), 0, X_FOLD_SIZE, Y_SIZE, light );
|
||||
X_FOLD_SIZE * 2 + X_SIZE + (n == rightPages ? X_FOLD_SIZE : 0), 0,
|
||||
X_FOLD_SIZE, Y_SIZE, light
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static float offsetAt( int page )
|
||||
{
|
||||
return (float) (32 * (1 - Math.pow( 1.2, -page )));
|
||||
}
|
||||
|
||||
private static void drawTexture( Matrix4f matrix, VertexConsumer buffer, float x, float y, float z, float u, float v, float width, float height, int light )
|
||||
{
|
||||
vertex( buffer, matrix, x, y + height, z, u / BG_SIZE, (v + height) / BG_SIZE, light );
|
||||
@@ -162,8 +149,7 @@ public final class PrintoutRenderer
|
||||
vertex( buffer, matrix, x, y, z, u / BG_SIZE, v / BG_SIZE, light );
|
||||
}
|
||||
|
||||
private static void drawTexture( Matrix4f matrix, VertexConsumer buffer, float x, float y, float z, float width, float height, float u, float v,
|
||||
float tWidth, float tHeight, int light )
|
||||
private static void drawTexture( Matrix4f matrix, VertexConsumer buffer, float x, float y, float z, float width, float height, float u, float v, float tWidth, float tHeight, int light )
|
||||
{
|
||||
vertex( buffer, matrix, x, y + height, z, u / BG_SIZE, (v + tHeight) / BG_SIZE, light );
|
||||
vertex( buffer, matrix, x + width, y + height, z, (u + tWidth) / BG_SIZE, (v + tHeight) / BG_SIZE, light );
|
||||
@@ -175,4 +161,9 @@ public final class PrintoutRenderer
|
||||
{
|
||||
buffer.vertex( matrix, x, y, z ).color( 255, 255, 255, 255 ).uv( u, v ).uv2( light ).endVertex();
|
||||
}
|
||||
|
||||
public static float offsetAt( int page )
|
||||
{
|
||||
return (float) (32 * (1 - Math.pow( 1.2, -page )));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,25 +14,26 @@ import net.minecraft.client.renderer.ShaderInstance;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class RenderTypes
|
||||
{
|
||||
|
||||
public static final int FULL_BRIGHT_LIGHTMAP = (0xF << 4) | (0xF << 20);
|
||||
|
||||
@Nullable
|
||||
public static MonitorTextureBufferShader monitorTboShader;
|
||||
|
||||
@Nullable
|
||||
public static ShaderInstance terminalShader;
|
||||
|
||||
public static final RenderType TERMINAL_WITHOUT_DEPTH = Types.TERMINAL_WITHOUT_DEPTH;
|
||||
public static final RenderType MONITOR_TBO = Types.MONITOR_TBO;
|
||||
public static final RenderType TERMINAL_BLOCKER = Types.BLOCKER;
|
||||
public static final RenderType TERMINAL_BLOCKER = Types.TERMINAL_BLOCKER;
|
||||
public static final RenderType TERMINAL_WITH_DEPTH = Types.TERMINAL_WITH_DEPTH;
|
||||
public static final RenderType MONITOR_TBO = Types.MONITOR_TBO;
|
||||
public static final RenderType PRINTOUT_TEXT = Types.PRINTOUT_TEXT;
|
||||
|
||||
/**
|
||||
* This looks wrong (it should be POSITION_COLOR_TEX_LIGHTMAP surely!) but the fragment/vertex shader for that
|
||||
* appear to entirely ignore the lightmap.
|
||||
*
|
||||
* Note that vanilla maps do the same, so this isn't unreasonable.
|
||||
*/
|
||||
public static final RenderType PRINTOUT_BACKGROUND = RenderType.text( new ResourceLocation( "computercraft", "textures/gui/printout.png" ) );
|
||||
|
||||
public static final RenderType POSITION_COLOR = Types.POSITION_COLOR;
|
||||
@@ -53,24 +54,26 @@ public class RenderTypes
|
||||
|
||||
private static final class Types extends RenderStateShard
|
||||
{
|
||||
private static final VertexFormat.Mode GL_MODE = VertexFormat.Mode.TRIANGLES;
|
||||
private static final VertexFormat FORMAT = DefaultVertexFormat.POSITION_COLOR_TEX;
|
||||
private static final ShaderStateShard TERM_SHADER = new ShaderStateShard( RenderTypes::getTerminalShader );
|
||||
|
||||
private static final RenderStateShard.TextureStateShard TERM_FONT_TEXTURE = new RenderStateShard.TextureStateShard(
|
||||
private static final RenderStateShard.TextureStateShard TERM_FONT_TEXTURE = new TextureStateShard(
|
||||
FixedWidthFontRenderer.FONT,
|
||||
false, false // blur, minimap
|
||||
);
|
||||
private static final VertexFormat TERM_FORMAT = DefaultVertexFormat.POSITION_COLOR_TEX;
|
||||
private static final VertexFormat.Mode TERM_MODE = VertexFormat.Mode.TRIANGLES;
|
||||
private static final ShaderStateShard TERM_SHADER = new ShaderStateShard( RenderTypes::getTerminalShader );
|
||||
|
||||
public static final RenderType MONITOR_TBO = RenderType.create( "monitor_tbo", DefaultVertexFormat.POSITION_TEX, VertexFormat.Mode.TRIANGLE_STRIP, 128, false, false, // useDelegate, needsSorting
|
||||
static final RenderType MONITOR_TBO = RenderType.create(
|
||||
"monitor_tbo", DefaultVertexFormat.POSITION_TEX, VertexFormat.Mode.TRIANGLE_STRIP, 128,
|
||||
false, false, // useDelegate, needsSorting
|
||||
RenderType.CompositeState.builder()
|
||||
.setTextureState( TERM_FONT_TEXTURE ) // blur, minimap
|
||||
.setShaderState( new RenderStateShard.ShaderStateShard( RenderTypes::getMonitorTextureBufferShader ) )
|
||||
.setWriteMaskState( RenderType.COLOR_DEPTH_WRITE )
|
||||
.createCompositeState( false ) );
|
||||
.setTextureState( TERM_FONT_TEXTURE )
|
||||
.setShaderState( new ShaderStateShard( RenderTypes::getMonitorTextureBufferShader ) )
|
||||
.setWriteMaskState( COLOR_WRITE )
|
||||
.createCompositeState( false )
|
||||
);
|
||||
|
||||
static final RenderType TERMINAL_WITHOUT_DEPTH = RenderType.create(
|
||||
"terminal_without_depth", FORMAT, GL_MODE, 1024,
|
||||
"terminal_without_depth", TERM_FORMAT, TERM_MODE, 1024,
|
||||
false, false, // useDelegate, needsSorting
|
||||
RenderType.CompositeState.builder()
|
||||
.setTextureState( TERM_FONT_TEXTURE )
|
||||
@@ -79,15 +82,18 @@ public class RenderTypes
|
||||
.createCompositeState( false )
|
||||
);
|
||||
|
||||
static final RenderType BLOCKER = RenderType.create( "terminal_blocker", FORMAT, GL_MODE, 256, false, false, // useDelegate, needsSorting
|
||||
static final RenderType TERMINAL_BLOCKER = RenderType.create(
|
||||
"terminal_blocker", TERM_FORMAT, TERM_MODE, 256,
|
||||
false, false, // useDelegate, needsSorting
|
||||
RenderType.CompositeState.builder()
|
||||
.setTextureState( TERM_FONT_TEXTURE )
|
||||
.setShaderState( TERM_SHADER )
|
||||
.setWriteMaskState( DEPTH_WRITE )
|
||||
.createCompositeState( false ) );
|
||||
.createCompositeState( false )
|
||||
);
|
||||
|
||||
static final RenderType TERMINAL_WITH_DEPTH = RenderType.create(
|
||||
"terminal_with_depth", FORMAT, GL_MODE, 1024,
|
||||
"terminal_with_depth", TERM_FORMAT, TERM_MODE, 1024,
|
||||
false, false, // useDelegate, needsSorting
|
||||
RenderType.CompositeState.builder()
|
||||
.setTextureState( TERM_FONT_TEXTURE )
|
||||
@@ -95,8 +101,11 @@ public class RenderTypes
|
||||
.createCompositeState( false )
|
||||
);
|
||||
|
||||
/**
|
||||
* A variant of {@link #TERMINAL_WITH_DEPTH} which uses the lightmap rather than rendering fullbright.
|
||||
*/
|
||||
static final RenderType PRINTOUT_TEXT = RenderType.create(
|
||||
"printout_text", DefaultVertexFormat.POSITION_COLOR_TEX_LIGHTMAP, GL_MODE, 1024,
|
||||
"printout_text", DefaultVertexFormat.POSITION_COLOR_TEX_LIGHTMAP, TERM_MODE, 1024,
|
||||
false, false, // useDelegate, needsSorting
|
||||
RenderType.CompositeState.builder()
|
||||
.setTextureState( TERM_FONT_TEXTURE )
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client.render;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.mojang.blaze3d.platform.MemoryTracker;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.*;
|
||||
import com.mojang.math.Matrix4f;
|
||||
@@ -35,27 +35,25 @@ import org.lwjgl.opengl.GL31;
|
||||
import javax.annotation.Nonnull;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import static com.mojang.blaze3d.platform.MemoryTracker.create;
|
||||
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.*;
|
||||
|
||||
public class TileEntityMonitorRenderer implements BlockEntityRenderer<TileMonitor>
|
||||
{
|
||||
/**
|
||||
* {@link TileMonitor#RENDER_MARGIN}, but a tiny bit of additional padding to ensure that there is no space between the monitor frame and contents.
|
||||
* {@link TileMonitor#RENDER_MARGIN}, but a tiny bit of additional padding to ensure that there is no space between
|
||||
* the monitor frame and contents.
|
||||
*/
|
||||
private static final float MARGIN = (float) (TileMonitor.RENDER_MARGIN * 1.1);
|
||||
private static final Matrix4f IDENTITY = Transformation.identity()
|
||||
.getMatrix();
|
||||
private static ByteBuffer tboContents;
|
||||
|
||||
private static final Matrix4f IDENTITY = Transformation.identity().getMatrix();
|
||||
|
||||
public TileEntityMonitorRenderer( BlockEntityRendererProvider.Context context )
|
||||
{
|
||||
// super( context );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render( @Nonnull TileMonitor monitor, float partialTicks, @Nonnull PoseStack transform, @Nonnull MultiBufferSource renderer,
|
||||
int lightmapCoord, int overlayLight )
|
||||
public void render( @Nonnull TileMonitor monitor, float partialTicks, @Nonnull PoseStack transform, @Nonnull MultiBufferSource renderer, int lightmapCoord, int overlayLight )
|
||||
{
|
||||
// Render from the origin monitor
|
||||
ClientMonitor originTerminal = monitor.getClientMonitor();
|
||||
@@ -86,15 +84,19 @@ public class TileEntityMonitorRenderer implements BlockEntityRenderer<TileMonito
|
||||
|
||||
// Setup initial transform
|
||||
transform.pushPose();
|
||||
transform.translate( originPos.getX() - monitorPos.getX() + 0.5,
|
||||
transform.translate(
|
||||
originPos.getX() - monitorPos.getX() + 0.5,
|
||||
originPos.getY() - monitorPos.getY() + 0.5,
|
||||
originPos.getZ() - monitorPos.getZ() + 0.5 );
|
||||
originPos.getZ() - monitorPos.getZ() + 0.5
|
||||
);
|
||||
|
||||
transform.mulPose( Vector3f.YN.rotationDegrees( yaw ) );
|
||||
transform.mulPose( Vector3f.XP.rotationDegrees( pitch ) );
|
||||
transform.translate( -0.5 + TileMonitor.RENDER_BORDER + TileMonitor.RENDER_MARGIN,
|
||||
transform.translate(
|
||||
-0.5 + TileMonitor.RENDER_BORDER + TileMonitor.RENDER_MARGIN,
|
||||
origin.getHeight() - 0.5 - (TileMonitor.RENDER_BORDER + TileMonitor.RENDER_MARGIN) + 0,
|
||||
0.50 );
|
||||
0.5
|
||||
);
|
||||
double xSize = origin.getWidth() - 2.0 * (TileMonitor.RENDER_MARGIN + TileMonitor.RENDER_BORDER);
|
||||
double ySize = origin.getHeight() - 2.0 * (TileMonitor.RENDER_MARGIN + TileMonitor.RENDER_BORDER);
|
||||
|
||||
@@ -116,58 +118,56 @@ public class TileEntityMonitorRenderer implements BlockEntityRenderer<TileMonito
|
||||
|
||||
// We don't draw the cursor with the VBO, as it's dynamic and so we'll end up refreshing far more than is
|
||||
// reasonable.
|
||||
FixedWidthFontRenderer.drawCursor( matrix, renderer.getBuffer( RenderTypes.TERMINAL_WITHOUT_DEPTH ), 0, 0, terminal, !originTerminal.isColour() );
|
||||
FixedWidthFontRenderer.drawCursor(
|
||||
matrix, renderer.getBuffer( RenderTypes.TERMINAL_WITHOUT_DEPTH ),
|
||||
0, 0, terminal, !originTerminal.isColour()
|
||||
);
|
||||
|
||||
transform.popPose();
|
||||
|
||||
// Draw the background blocker
|
||||
FixedWidthFontRenderer.drawBlocker(
|
||||
transform.last().pose(), renderer,
|
||||
-MARGIN, MARGIN,
|
||||
(float) (xSize + 2 * MARGIN), (float) -(ySize + MARGIN * 2)
|
||||
);
|
||||
|
||||
// Force a flush of the blocker. WorldRenderer.updateCameraAndRender will "finish" all the built-in
|
||||
// buffers before calling renderer.finish, which means the blocker isn't actually rendered at that point!
|
||||
renderer.getBuffer( RenderType.solid() );
|
||||
}
|
||||
else
|
||||
{
|
||||
FixedWidthFontRenderer.drawEmptyTerminal( transform.last()
|
||||
.pose(),
|
||||
renderer,
|
||||
-MARGIN,
|
||||
MARGIN,
|
||||
(float) (xSize + 2 * MARGIN),
|
||||
(float) -(ySize + MARGIN * 2) );
|
||||
FixedWidthFontRenderer.drawEmptyTerminal(
|
||||
transform.last().pose(), renderer,
|
||||
-MARGIN, MARGIN,
|
||||
(float) (xSize + 2 * MARGIN), (float) -(ySize + MARGIN * 2)
|
||||
);
|
||||
}
|
||||
|
||||
transform.popPose();
|
||||
}
|
||||
|
||||
private static void renderTerminal( MultiBufferSource renderer, Matrix4f matrix, ClientMonitor monitor, float xMargin, float yMargin )
|
||||
private static void renderTerminal( @Nonnull MultiBufferSource renderer, Matrix4f matrix, ClientMonitor monitor, float xMargin, float yMargin )
|
||||
{
|
||||
Terminal terminal = monitor.getTerminal();
|
||||
|
||||
MonitorRenderer renderType = MonitorRenderer.current();
|
||||
boolean redraw = monitor.pollTerminalChanged();
|
||||
if( monitor.createBuffer( renderType ) )
|
||||
{
|
||||
redraw = true;
|
||||
}
|
||||
if( monitor.createBuffer( renderType ) ) redraw = true;
|
||||
|
||||
switch( renderType )
|
||||
{
|
||||
case TBO:
|
||||
{
|
||||
|
||||
int width = terminal.getWidth(), height = terminal.getHeight();
|
||||
int pixelWidth = width * FONT_WIDTH, pixelHeight = height * FONT_HEIGHT;
|
||||
|
||||
int pixelWidth = width * FONT_WIDTH, pixelHeight = height * FONT_HEIGHT;
|
||||
if( redraw )
|
||||
{
|
||||
int size = width * height * 3;
|
||||
if( tboContents == null || tboContents.capacity() < size )
|
||||
{
|
||||
tboContents = create( size );
|
||||
tboContents = MemoryTracker.create( size );
|
||||
}
|
||||
|
||||
ByteBuffer monitorBuffer = tboContents;
|
||||
@@ -204,37 +204,34 @@ public class TileEntityMonitorRenderer implements BlockEntityRenderer<TileMonito
|
||||
tboVertex( buffer, matrix, pixelWidth + xMargin, -yMargin );
|
||||
tboVertex( buffer, matrix, pixelWidth + xMargin, pixelHeight + yMargin );
|
||||
|
||||
// And force things to flush. We strictly speaking do this later on anyway for the cursor, but nice to
|
||||
// be consistent.
|
||||
renderer.getBuffer( RenderTypes.TERMINAL_WITHOUT_DEPTH );
|
||||
break;
|
||||
}
|
||||
|
||||
case VBO:
|
||||
{
|
||||
VertexBuffer vbo = monitor.buffer;
|
||||
if( redraw )
|
||||
{
|
||||
Tesselator tessellator = Tesselator.getInstance();
|
||||
BufferBuilder builder = tessellator.getBuilder();
|
||||
builder.begin( RenderTypes.TERMINAL_WITHOUT_DEPTH.mode(), RenderTypes.TERMINAL_WITHOUT_DEPTH.format() );
|
||||
FixedWidthFontRenderer.drawTerminalWithoutCursor( IDENTITY,
|
||||
builder,
|
||||
0,
|
||||
0,
|
||||
terminal,
|
||||
!monitor.isColour(),
|
||||
yMargin,
|
||||
yMargin,
|
||||
xMargin,
|
||||
xMargin );
|
||||
FixedWidthFontRenderer.drawTerminalWithoutCursor(
|
||||
IDENTITY, builder, 0, 0,
|
||||
terminal, !monitor.isColour(), yMargin, yMargin, xMargin, xMargin
|
||||
);
|
||||
|
||||
builder.end();
|
||||
vbo.upload( builder );
|
||||
}
|
||||
|
||||
renderer.getBuffer( RenderTypes.TERMINAL_WITHOUT_DEPTH );
|
||||
|
||||
RenderTypes.TERMINAL_WITHOUT_DEPTH.setupRenderState();
|
||||
vbo.drawWithShader( matrix, RenderSystem.getProjectionMatrix(), RenderTypes.getTerminalShader() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ public class TileEntityTurtleRenderer implements BlockEntityRenderer<TileTurtle>
|
||||
|
||||
private final Random random = new Random( 0 );
|
||||
|
||||
BlockEntityRenderDispatcher renderer;
|
||||
private final BlockEntityRenderDispatcher renderer;
|
||||
|
||||
public TileEntityTurtleRenderer( BlockEntityRendererProvider.Context context )
|
||||
{
|
||||
@@ -68,39 +68,28 @@ public class TileEntityTurtleRenderer implements BlockEntityRenderer<TileTurtle>
|
||||
|
||||
public static ModelResourceLocation getTurtleOverlayModel( ResourceLocation overlay, boolean christmas )
|
||||
{
|
||||
if( overlay != null )
|
||||
{
|
||||
return new ModelResourceLocation( overlay, "inventory" );
|
||||
}
|
||||
if( christmas )
|
||||
{
|
||||
return ELF_OVERLAY_MODEL;
|
||||
}
|
||||
if( overlay != null ) return new ModelResourceLocation( overlay, "inventory" );
|
||||
if( christmas ) return ELF_OVERLAY_MODEL;
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render( @Nonnull TileTurtle turtle, float partialTicks, @Nonnull PoseStack transform, @Nonnull MultiBufferSource buffers,
|
||||
int lightmapCoord, int overlayLight )
|
||||
public void render( @Nonnull TileTurtle turtle, float partialTicks, @Nonnull PoseStack transform, @Nonnull MultiBufferSource buffers, int lightmapCoord, int overlayLight )
|
||||
{
|
||||
// Render the label
|
||||
String label = turtle.createProxy()
|
||||
.getLabel();
|
||||
String label = turtle.createProxy().getLabel();
|
||||
HitResult hit = renderer.cameraHitResult;
|
||||
if( label != null && hit.getType() == HitResult.Type.BLOCK && turtle.getBlockPos()
|
||||
.equals( ((BlockHitResult) hit).getBlockPos() ) )
|
||||
if( label != null && hit.getType() == HitResult.Type.BLOCK && turtle.getBlockPos().equals( ((BlockHitResult) hit).getBlockPos() ) )
|
||||
{
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
Font font = mc.font;
|
||||
|
||||
transform.pushPose();
|
||||
transform.translate( 0.5, 1.2, 0.5 );
|
||||
transform.mulPose( mc.getEntityRenderDispatcher()
|
||||
.cameraOrientation() );
|
||||
transform.mulPose( mc.getEntityRenderDispatcher().cameraOrientation() );
|
||||
transform.scale( -0.025f, -0.025f, 0.025f );
|
||||
|
||||
Matrix4f matrix = transform.last()
|
||||
.pose();
|
||||
Matrix4f matrix = transform.last().pose();
|
||||
int opacity = (int) (mc.options.getBackgroundOpacity( 0.25f ) * 255) << 24;
|
||||
float width = -font.width( label ) / 2.0f;
|
||||
font.drawInBatch( label, width, (float) 0, 0x20ffffff, false, matrix, buffers, true, opacity, lightmapCoord );
|
||||
@@ -147,14 +136,10 @@ public class TileEntityTurtleRenderer implements BlockEntityRenderer<TileTurtle>
|
||||
transform.popPose();
|
||||
}
|
||||
|
||||
private void renderUpgrade( @Nonnull PoseStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, TileTurtle turtle,
|
||||
TurtleSide side, float f )
|
||||
private void renderUpgrade( @Nonnull PoseStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, TileTurtle turtle, TurtleSide side, float f )
|
||||
{
|
||||
ITurtleUpgrade upgrade = turtle.getUpgrade( side );
|
||||
if( upgrade == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
if( upgrade == null ) return;
|
||||
transform.pushPose();
|
||||
|
||||
float toolAngle = turtle.getToolRenderAngle( side, f );
|
||||
@@ -170,18 +155,13 @@ public class TileEntityTurtleRenderer implements BlockEntityRenderer<TileTurtle>
|
||||
transform.popPose();
|
||||
}
|
||||
|
||||
private void renderModel( @Nonnull PoseStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight,
|
||||
ModelResourceLocation modelLocation, int[] tints )
|
||||
private void renderModel( @Nonnull PoseStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, ModelResourceLocation modelLocation, int[] tints )
|
||||
{
|
||||
ModelManager modelManager = Minecraft.getInstance()
|
||||
.getItemRenderer()
|
||||
.getItemModelShaper()
|
||||
.getModelManager();
|
||||
ModelManager modelManager = Minecraft.getInstance().getItemRenderer().getItemModelShaper().getModelManager();
|
||||
renderModel( transform, renderer, lightmapCoord, overlayLight, modelManager.getModel( modelLocation ), tints );
|
||||
}
|
||||
|
||||
private void renderModel( @Nonnull PoseStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, BakedModel model,
|
||||
int[] tints )
|
||||
private void renderModel( @Nonnull PoseStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, BakedModel model, int[] tints )
|
||||
{
|
||||
random.setSeed( 0 );
|
||||
renderQuads( transform, renderer, lightmapCoord, overlayLight, model.getQuads( null, null, random ), tints );
|
||||
@@ -191,8 +171,7 @@ public class TileEntityTurtleRenderer implements BlockEntityRenderer<TileTurtle>
|
||||
}
|
||||
}
|
||||
|
||||
private static void renderQuads( @Nonnull PoseStack transform, @Nonnull VertexConsumer buffer, int lightmapCoord, int overlayLight,
|
||||
List<BakedQuad> quads, int[] tints )
|
||||
private static void renderQuads( @Nonnull PoseStack transform, @Nonnull VertexConsumer buffer, int lightmapCoord, int overlayLight, List<BakedQuad> quads, int[] tints )
|
||||
{
|
||||
PoseStack.Pose matrix = transform.last();
|
||||
|
||||
@@ -202,10 +181,7 @@ public class TileEntityTurtleRenderer implements BlockEntityRenderer<TileTurtle>
|
||||
if( tints != null && bakedquad.isTinted() )
|
||||
{
|
||||
int idx = bakedquad.getTintIndex();
|
||||
if( idx >= 0 && idx < tints.length )
|
||||
{
|
||||
tint = tints[bakedquad.getTintIndex()];
|
||||
}
|
||||
if( idx >= 0 && idx < tints.length ) tint = tints[bakedquad.getTintIndex()];
|
||||
}
|
||||
|
||||
float f = (float) (tint >> 16 & 255) / 255.0F;
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client.render;
|
||||
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client.render;
|
||||
|
||||
import com.mojang.math.Transformation;
|
||||
@@ -32,8 +31,7 @@ public class TurtleMultiModel implements BakedModel
|
||||
private List<BakedQuad> generalQuads = null;
|
||||
private final Map<Direction, List<BakedQuad>> faceQuads = new EnumMap<>( Direction.class );
|
||||
|
||||
public TurtleMultiModel( BakedModel baseModel, BakedModel overlayModel, Transformation generalTransform, TransformedModel leftUpgradeModel,
|
||||
TransformedModel rightUpgradeModel )
|
||||
public TurtleMultiModel( BakedModel baseModel, BakedModel overlayModel, Transformation generalTransform, TransformedModel leftUpgradeModel, TransformedModel rightUpgradeModel )
|
||||
{
|
||||
// Get the models
|
||||
this.baseModel = baseModel;
|
||||
@@ -45,22 +43,17 @@ public class TurtleMultiModel implements BakedModel
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@Deprecated
|
||||
public List<BakedQuad> getQuads( BlockState state, Direction side, @Nonnull Random rand )
|
||||
{
|
||||
if( side != null )
|
||||
{
|
||||
if( !faceQuads.containsKey( side ) )
|
||||
{
|
||||
faceQuads.put( side, buildQuads( state, side, rand ) );
|
||||
}
|
||||
if( !faceQuads.containsKey( side ) ) faceQuads.put( side, buildQuads( state, side, rand ) );
|
||||
return faceQuads.get( side );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( generalQuads == null )
|
||||
{
|
||||
generalQuads = buildQuads( state, side, rand );
|
||||
}
|
||||
if( generalQuads == null ) generalQuads = buildQuads( state, side, rand );
|
||||
return generalQuads;
|
||||
}
|
||||
}
|
||||
@@ -70,24 +63,20 @@ public class TurtleMultiModel implements BakedModel
|
||||
ArrayList<BakedQuad> quads = new ArrayList<>();
|
||||
|
||||
|
||||
ModelTransformer.transformQuadsTo( quads, baseModel.getQuads( state, side, rand ), generalTransform.getMatrix() );
|
||||
transformQuadsTo( quads, baseModel.getQuads( state, side, rand ), generalTransform );
|
||||
if( overlayModel != null )
|
||||
{
|
||||
ModelTransformer.transformQuadsTo( quads, overlayModel.getQuads( state, side, rand ), generalTransform.getMatrix() );
|
||||
transformQuadsTo( quads, overlayModel.getQuads( state, side, rand ), generalTransform );
|
||||
}
|
||||
if( leftUpgradeModel != null )
|
||||
{
|
||||
Transformation upgradeTransform = generalTransform.compose( leftUpgradeModel.getMatrix() );
|
||||
ModelTransformer.transformQuadsTo( quads, leftUpgradeModel.getModel()
|
||||
.getQuads( state, side, rand ),
|
||||
upgradeTransform.getMatrix() );
|
||||
transformQuadsTo( quads, leftUpgradeModel.getModel().getQuads( state, side, rand ), upgradeTransform );
|
||||
}
|
||||
if( rightUpgradeModel != null )
|
||||
{
|
||||
Transformation upgradeTransform = generalTransform.compose( rightUpgradeModel.getMatrix() );
|
||||
ModelTransformer.transformQuadsTo( quads, rightUpgradeModel.getModel()
|
||||
.getQuads( state, side, rand ),
|
||||
upgradeTransform.getMatrix() );
|
||||
transformQuadsTo( quads, rightUpgradeModel.getModel().getQuads( state, side, rand ), upgradeTransform );
|
||||
}
|
||||
quads.trimToSize();
|
||||
return quads;
|
||||
@@ -105,18 +94,18 @@ public class TurtleMultiModel implements BakedModel
|
||||
return baseModel.isGui3d();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean usesBlockLight()
|
||||
{
|
||||
return baseModel.usesBlockLight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCustomRenderer()
|
||||
{
|
||||
return baseModel.isCustomRenderer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean usesBlockLight()
|
||||
{
|
||||
return baseModel.usesBlockLight();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@Deprecated
|
||||
@@ -139,4 +128,9 @@ public class TurtleMultiModel implements BakedModel
|
||||
{
|
||||
return ItemOverrides.EMPTY;
|
||||
}
|
||||
|
||||
private void transformQuadsTo( List<BakedQuad> output, List<BakedQuad> quads, Transformation transform )
|
||||
{
|
||||
ModelTransformer.transformQuadsTo( output, quads, transform.getMatrix() );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,16 +15,10 @@ import net.minecraft.resources.ResourceLocation;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class TurtlePlayerRenderer extends EntityRenderer<TurtlePlayer>
|
||||
{ //FIXME Make sure this isn't an issue. Context was EntityRenderDispatcher.
|
||||
public TurtlePlayerRenderer( EntityRendererProvider.Context context )
|
||||
{
|
||||
super( context );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render( @Nonnull TurtlePlayer entityIn, float entityYaw, float partialTicks, @Nonnull PoseStack transform,
|
||||
@Nonnull MultiBufferSource buffer, int packedLightIn )
|
||||
{
|
||||
public TurtlePlayerRenderer( EntityRendererProvider.Context renderManager )
|
||||
{
|
||||
super( renderManager );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@@ -33,4 +27,9 @@ public class TurtlePlayerRenderer extends EntityRenderer<TurtlePlayer>
|
||||
{
|
||||
return ComputerBorderRenderer.BACKGROUND_NORMAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render( @Nonnull TurtlePlayer entityIn, float entityYaw, float partialTicks, @Nonnull PoseStack transform, @Nonnull MultiBufferSource buffer, int packedLightIn )
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
*/
|
||||
package dan200.computercraft.client.render;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.math.Transformation;
|
||||
import dan200.computercraft.api.client.TransformedModel;
|
||||
@@ -50,59 +49,18 @@ public class TurtleSmartItemModel implements BakedModel
|
||||
stack.translate( 0, 0, 1 );
|
||||
|
||||
identity = Transformation.identity();
|
||||
flip = new Transformation( stack.last()
|
||||
.pose() );
|
||||
flip = new Transformation( stack.last().pose() );
|
||||
}
|
||||
|
||||
private static class TurtleModelCombination
|
||||
private static record TurtleModelCombination(
|
||||
boolean colour,
|
||||
ITurtleUpgrade leftUpgrade,
|
||||
ITurtleUpgrade rightUpgrade,
|
||||
ResourceLocation overlay,
|
||||
boolean christmas,
|
||||
boolean flip
|
||||
)
|
||||
{
|
||||
final boolean colour;
|
||||
final ITurtleUpgrade leftUpgrade;
|
||||
final ITurtleUpgrade rightUpgrade;
|
||||
final ResourceLocation overlay;
|
||||
final boolean christmas;
|
||||
final boolean flip;
|
||||
|
||||
TurtleModelCombination( boolean colour, ITurtleUpgrade leftUpgrade, ITurtleUpgrade rightUpgrade, ResourceLocation overlay, boolean christmas,
|
||||
boolean flip )
|
||||
{
|
||||
this.colour = colour;
|
||||
this.leftUpgrade = leftUpgrade;
|
||||
this.rightUpgrade = rightUpgrade;
|
||||
this.overlay = overlay;
|
||||
this.christmas = christmas;
|
||||
this.flip = flip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals( Object other )
|
||||
{
|
||||
if( other == this )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if( !(other instanceof TurtleModelCombination otherCombo) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return otherCombo.colour == colour && otherCombo.leftUpgrade == leftUpgrade && otherCombo.rightUpgrade == rightUpgrade && Objects.equal(
|
||||
otherCombo.overlay, overlay ) && otherCombo.christmas == christmas && otherCombo.flip == flip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
final int prime = 31;
|
||||
int result = 0;
|
||||
result = prime * result + (colour ? 1 : 0);
|
||||
result = prime * result + (leftUpgrade != null ? leftUpgrade.hashCode() : 0);
|
||||
result = prime * result + (rightUpgrade != null ? rightUpgrade.hashCode() : 0);
|
||||
result = prime * result + (overlay != null ? overlay.hashCode() : 0);
|
||||
result = prime * result + (christmas ? 1 : 0);
|
||||
result = prime * result + (flip ? 1 : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private final BakedModel familyModel;
|
||||
@@ -121,7 +79,7 @@ public class TurtleSmartItemModel implements BakedModel
|
||||
{
|
||||
@Nonnull
|
||||
@Override
|
||||
public BakedModel resolve( BakedModel originalModel, ItemStack stack, @Nullable ClientLevel world, @Nullable LivingEntity entity, int seed )
|
||||
public BakedModel resolve( @Nonnull BakedModel originalModel, @Nonnull ItemStack stack, @Nullable ClientLevel world, @Nullable LivingEntity entity, int random )
|
||||
{
|
||||
ItemTurtle turtle = (ItemTurtle) stack.getItem();
|
||||
int colour = turtle.getColour( stack );
|
||||
@@ -134,21 +92,23 @@ public class TurtleSmartItemModel implements BakedModel
|
||||
TurtleModelCombination combo = new TurtleModelCombination( colour != -1, leftUpgrade, rightUpgrade, overlay, christmas, flip );
|
||||
|
||||
BakedModel model = cachedModels.get( combo );
|
||||
if( model == null )
|
||||
{
|
||||
cachedModels.put( combo, model = buildModel( combo ) );
|
||||
}
|
||||
if( model == null ) cachedModels.put( combo, model = buildModel( combo ) );
|
||||
return model;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ItemOverrides getOverrides()
|
||||
{
|
||||
return overrides;
|
||||
}
|
||||
|
||||
private BakedModel buildModel( TurtleModelCombination combo )
|
||||
{
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
ModelManager modelManager = mc.getItemRenderer()
|
||||
.getItemModelShaper()
|
||||
.getModelManager();
|
||||
ModelManager modelManager = mc.getItemRenderer().getItemModelShaper().getModelManager();
|
||||
ModelResourceLocation overlayModelLocation = TileEntityTurtleRenderer.getTurtleOverlayModel( combo.overlay, combo.christmas );
|
||||
|
||||
BakedModel baseModel = combo.colour ? colourModel : familyModel;
|
||||
@@ -179,12 +139,6 @@ public class TurtleSmartItemModel implements BakedModel
|
||||
return familyModel.isGui3d();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean usesBlockLight()
|
||||
{
|
||||
return familyModel.usesBlockLight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCustomRenderer()
|
||||
{
|
||||
@@ -192,17 +146,17 @@ public class TurtleSmartItemModel implements BakedModel
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public TextureAtlasSprite getParticleIcon()
|
||||
public boolean usesBlockLight()
|
||||
{
|
||||
return familyModel.getParticleIcon();
|
||||
return familyModel.usesBlockLight();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ItemOverrides getOverrides()
|
||||
@Deprecated
|
||||
public TextureAtlasSprite getParticleIcon()
|
||||
{
|
||||
return overrides;
|
||||
return familyModel.getParticleIcon();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
|
||||
@@ -484,7 +484,7 @@ public class FSAPI implements ILuaAPI
|
||||
*
|
||||
* This string is formatted like a normal path string, but can include any
|
||||
* number of wildcards ({@code *}) to look for files matching anything.
|
||||
* For example, {@code rom/* /command*} will look for any path starting with
|
||||
* For example, <code>rom/*/command*</code> will look for any path starting with
|
||||
* {@code command} inside any subdirectory of {@code /rom}.
|
||||
*
|
||||
* @param path The wildcard-qualified path to search for.
|
||||
|
||||
@@ -17,6 +17,7 @@ import dan200.computercraft.core.asm.NamedMethod;
|
||||
import dan200.computercraft.core.asm.PeripheralMethod;
|
||||
import dan200.computercraft.core.computer.ComputerSide;
|
||||
import dan200.computercraft.core.tracking.TrackingField;
|
||||
import dan200.computercraft.shared.util.LuaUtil;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
@@ -36,6 +37,7 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
|
||||
private final IPeripheral peripheral;
|
||||
|
||||
private final String type;
|
||||
private final Set<String> additionalTypes;
|
||||
private final Map<String, PeripheralMethod> methodMap;
|
||||
private boolean attached;
|
||||
|
||||
@@ -47,6 +49,7 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
|
||||
attached = false;
|
||||
|
||||
type = Objects.requireNonNull( peripheral.getType(), "Peripheral type cannot be null" );
|
||||
additionalTypes = peripheral.getAdditionalTypes();
|
||||
|
||||
methodMap = PeripheralAPI.getMethods( peripheral );
|
||||
}
|
||||
@@ -61,6 +64,11 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
|
||||
return type;
|
||||
}
|
||||
|
||||
public Set<String> getAdditionalTypes()
|
||||
{
|
||||
return additionalTypes;
|
||||
}
|
||||
|
||||
public Collection<String> getMethods()
|
||||
{
|
||||
return methodMap.keySet();
|
||||
@@ -298,7 +306,23 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
|
||||
synchronized( peripherals )
|
||||
{
|
||||
PeripheralWrapper p = peripherals[side.ordinal()];
|
||||
if( p != null ) return new Object[] { p.getType() };
|
||||
return p == null ? null : LuaUtil.consArray( p.getType(), p.getAdditionalTypes() );
|
||||
}
|
||||
}
|
||||
|
||||
@LuaFunction
|
||||
public final Object[] hasType( String sideName, String type )
|
||||
{
|
||||
ComputerSide side = ComputerSide.valueOfInsensitive( sideName );
|
||||
if( side == null ) return null;
|
||||
|
||||
synchronized( peripherals )
|
||||
{
|
||||
PeripheralWrapper p = peripherals[side.ordinal()];
|
||||
if( p != null )
|
||||
{
|
||||
return new Object[] { p.getType().equals( type ) || p.getAdditionalTypes().contains( type ) };
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ public class BinaryWritableHandle extends HandleGeneric
|
||||
try
|
||||
{
|
||||
// Technically this is not needed
|
||||
if( writer instanceof FileChannel ) ((FileChannel) writer).force( false );
|
||||
if( writer instanceof FileChannel channel ) channel.force( false );
|
||||
}
|
||||
catch( IOException ignored )
|
||||
{
|
||||
|
||||
@@ -153,7 +153,7 @@ public class WebsocketHandle implements Closeable
|
||||
return MethodResult.of();
|
||||
}
|
||||
else if( event.length >= 2 && timeoutId != -1 && Objects.equal( event[0], TIMER_EVENT )
|
||||
&& event[1] instanceof Number && ((Number) event[1]).intValue() == timeoutId )
|
||||
&& event[1] instanceof Number id && id.intValue() == timeoutId )
|
||||
{
|
||||
// If we received a matching timer event then abort.
|
||||
return MethodResult.of();
|
||||
|
||||
@@ -130,8 +130,6 @@ public final class Generator<T>
|
||||
|
||||
private void addMethod( List<NamedMethod<T>> methods, Method method, LuaFunction annotation, PeripheralType genericType, T instance )
|
||||
{
|
||||
if( annotation.mainThread() ) instance = wrap.apply( instance );
|
||||
|
||||
String[] names = annotation.value();
|
||||
boolean isSimple = method.getReturnType() != MethodResult.class && !annotation.mainThread();
|
||||
if( names.length == 0 )
|
||||
@@ -183,6 +181,13 @@ public final class Generator<T>
|
||||
}
|
||||
}
|
||||
|
||||
LuaFunction annotation = method.getAnnotation( LuaFunction.class );
|
||||
if( annotation.unsafe() && annotation.mainThread() )
|
||||
{
|
||||
ComputerCraft.log.error( "Lua Method {} cannot use unsafe and mainThread", name );
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
// We have some rather ugly handling of static methods in both here and the main generate function. Static methods
|
||||
// only come from generic sources, so this should be safe.
|
||||
Class<?> target = Modifier.isStatic( modifiers ) ? method.getParameterTypes()[0] : method.getDeclaringClass();
|
||||
@@ -190,11 +195,13 @@ public final class Generator<T>
|
||||
try
|
||||
{
|
||||
String className = method.getDeclaringClass().getName() + "$cc$" + method.getName() + METHOD_ID.getAndIncrement();
|
||||
byte[] bytes = generate( className, target, method );
|
||||
byte[] bytes = generate( className, target, method, annotation.unsafe() );
|
||||
if( bytes == null ) return Optional.empty();
|
||||
|
||||
Class<?> klass = DeclaringClassLoader.INSTANCE.define( className, bytes, method.getDeclaringClass().getProtectionDomain() );
|
||||
return Optional.of( klass.asSubclass( base ).getDeclaredConstructor().newInstance() );
|
||||
|
||||
T instance = klass.asSubclass( base ).getDeclaredConstructor().newInstance();
|
||||
return Optional.of( annotation.mainThread() ? wrap.apply( instance ) : instance );
|
||||
}
|
||||
catch( ReflectiveOperationException | ClassFormatError | RuntimeException e )
|
||||
{
|
||||
@@ -205,7 +212,7 @@ public final class Generator<T>
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private byte[] generate( String className, Class<?> target, Method method )
|
||||
private byte[] generate( String className, Class<?> target, Method method, boolean unsafe )
|
||||
{
|
||||
String internalName = className.replace( ".", "/" );
|
||||
|
||||
@@ -238,7 +245,7 @@ public final class Generator<T>
|
||||
int argIndex = 0;
|
||||
for( java.lang.reflect.Type genericArg : method.getGenericParameterTypes() )
|
||||
{
|
||||
Boolean loadedArg = loadArg( mw, target, method, genericArg, argIndex );
|
||||
Boolean loadedArg = loadArg( mw, target, method, unsafe, genericArg, argIndex );
|
||||
if( loadedArg == null ) return null;
|
||||
if( loadedArg ) argIndex++;
|
||||
}
|
||||
@@ -285,7 +292,7 @@ public final class Generator<T>
|
||||
return cw.toByteArray();
|
||||
}
|
||||
|
||||
private Boolean loadArg( MethodVisitor mw, Class<?> target, Method method, java.lang.reflect.Type genericArg, int argIndex )
|
||||
private Boolean loadArg( MethodVisitor mw, Class<?> target, Method method, boolean unsafe, java.lang.reflect.Type genericArg, int argIndex )
|
||||
{
|
||||
if( genericArg == target )
|
||||
{
|
||||
@@ -324,7 +331,7 @@ public final class Generator<T>
|
||||
return true;
|
||||
}
|
||||
|
||||
String name = Reflect.getLuaName( Primitives.unwrap( klass ) );
|
||||
String name = Reflect.getLuaName( Primitives.unwrap( klass ), unsafe );
|
||||
if( name != null )
|
||||
{
|
||||
mw.visitVarInsn( ALOAD, 2 + context.size() );
|
||||
@@ -344,7 +351,7 @@ public final class Generator<T>
|
||||
return true;
|
||||
}
|
||||
|
||||
String name = arg == Object.class ? "" : Reflect.getLuaName( arg );
|
||||
String name = arg == Object.class ? "" : Reflect.getLuaName( arg, unsafe );
|
||||
if( name != null )
|
||||
{
|
||||
if( Reflect.getRawType( method, genericArg, false ) == null ) return null;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package dan200.computercraft.core.asm;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.api.lua.LuaTable;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
@@ -25,7 +26,7 @@ final class Reflect
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static String getLuaName( Class<?> klass )
|
||||
static String getLuaName( Class<?> klass, boolean unsafe )
|
||||
{
|
||||
if( klass.isPrimitive() )
|
||||
{
|
||||
@@ -39,6 +40,7 @@ final class Reflect
|
||||
if( klass == Map.class ) return "Table";
|
||||
if( klass == String.class ) return "String";
|
||||
if( klass == ByteBuffer.class ) return "Bytes";
|
||||
if( klass == LuaTable.class && unsafe ) return "TableUnsafe";
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -59,6 +59,10 @@ class BasicFunction extends VarArgFunction
|
||||
}
|
||||
throw new LuaError( "Java Exception Thrown: " + t, 0 );
|
||||
}
|
||||
finally
|
||||
{
|
||||
arguments.releaseImmediate();
|
||||
}
|
||||
|
||||
if( results.getCallback() != null )
|
||||
{
|
||||
|
||||
@@ -15,6 +15,7 @@ import dan200.computercraft.core.tracking.Tracking;
|
||||
import dan200.computercraft.core.tracking.TrackingField;
|
||||
import dan200.computercraft.shared.util.ThreadUtils;
|
||||
import org.squiddev.cobalt.*;
|
||||
import org.squiddev.cobalt.LuaTable;
|
||||
import org.squiddev.cobalt.compiler.CompileException;
|
||||
import org.squiddev.cobalt.compiler.LoadState;
|
||||
import org.squiddev.cobalt.debug.DebugFrame;
|
||||
|
||||
@@ -69,6 +69,10 @@ class ResultInterpreterFunction extends ResumableVarArgFunction<ResultInterprete
|
||||
}
|
||||
throw new LuaError( "Java Exception Thrown: " + t, 0 );
|
||||
}
|
||||
finally
|
||||
{
|
||||
arguments.releaseImmediate();
|
||||
}
|
||||
|
||||
ILuaCallback callback = results.getCallback();
|
||||
Varargs ret = machine.toValues( results.getResult() );
|
||||
|
||||
141
src/main/java/dan200/computercraft/core/lua/TableImpl.java
Normal file
141
src/main/java/dan200/computercraft/core/lua/TableImpl.java
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.core.lua;
|
||||
|
||||
import dan200.computercraft.api.lua.LuaException;
|
||||
import dan200.computercraft.api.lua.LuaValues;
|
||||
import org.squiddev.cobalt.*;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.*;
|
||||
|
||||
import static dan200.computercraft.api.lua.LuaValues.badTableItem;
|
||||
import static dan200.computercraft.api.lua.LuaValues.getNumericType;
|
||||
|
||||
class TableImpl implements dan200.computercraft.api.lua.LuaTable<Object, Object>
|
||||
{
|
||||
private final VarargArguments arguments;
|
||||
private final LuaTable table;
|
||||
private Map<Object, Object> backingMap;
|
||||
|
||||
TableImpl( VarargArguments arguments, LuaTable table )
|
||||
{
|
||||
this.arguments = arguments;
|
||||
this.table = table;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size()
|
||||
{
|
||||
checkValid();
|
||||
try
|
||||
{
|
||||
return table.keyCount();
|
||||
}
|
||||
catch( LuaError e )
|
||||
{
|
||||
throw new IllegalStateException( e );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int length()
|
||||
{
|
||||
return table.length();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong( int index ) throws LuaException
|
||||
{
|
||||
LuaValue value = table.rawget( index );
|
||||
if( !(value instanceof LuaNumber) ) throw LuaValues.badTableItem( index, "number", value.typeName() );
|
||||
if( value instanceof LuaInteger ) return value.toInteger();
|
||||
|
||||
double number = value.toDouble();
|
||||
if( !Double.isFinite( number ) ) throw badTableItem( index, "number", getNumericType( number ) );
|
||||
return (long) number;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty()
|
||||
{
|
||||
checkValid();
|
||||
try
|
||||
{
|
||||
return table.next( Constants.NIL ).first().isNil();
|
||||
}
|
||||
catch( LuaError e )
|
||||
{
|
||||
throw new IllegalStateException( e );
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private LuaValue getImpl( Object o )
|
||||
{
|
||||
checkValid();
|
||||
if( o instanceof String ) return table.rawget( (String) o );
|
||||
if( o instanceof Integer ) return table.rawget( (Integer) o );
|
||||
return Constants.NIL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsKey( Object o )
|
||||
{
|
||||
return !getImpl( o ).isNil();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get( Object o )
|
||||
{
|
||||
return CobaltLuaMachine.toObject( getImpl( o ), null );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private Map<Object, Object> getBackingMap()
|
||||
{
|
||||
checkValid();
|
||||
if( backingMap != null ) return backingMap;
|
||||
return backingMap = Collections.unmodifiableMap(
|
||||
Objects.requireNonNull( (Map<?, ?>) CobaltLuaMachine.toObject( table, null ) )
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsValue( Object o )
|
||||
{
|
||||
return getBackingMap().containsKey( o );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Set<Object> keySet()
|
||||
{
|
||||
return getBackingMap().keySet();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Collection<Object> values()
|
||||
{
|
||||
return getBackingMap().values();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Set<Entry<Object, Object>> entrySet()
|
||||
{
|
||||
return getBackingMap().entrySet();
|
||||
}
|
||||
|
||||
private void checkValid()
|
||||
{
|
||||
if( arguments.released )
|
||||
{
|
||||
throw new IllegalStateException( "Cannot use LuaTable after IArguments has been released" );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ class VarargArguments implements IArguments
|
||||
{
|
||||
static final IArguments EMPTY = new VarargArguments( Constants.NONE );
|
||||
|
||||
boolean released;
|
||||
private final Varargs varargs;
|
||||
private Object[] cache;
|
||||
|
||||
@@ -98,4 +99,39 @@ class VarargArguments implements IArguments
|
||||
LuaString str = ((LuaBaseString) value).strvalue();
|
||||
return Optional.of( ByteBuffer.wrap( str.bytes, str.offset, str.length ).asReadOnlyBuffer() );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public dan200.computercraft.api.lua.LuaTable<?, ?> getTableUnsafe( int index ) throws LuaException
|
||||
{
|
||||
if( released )
|
||||
{
|
||||
throw new IllegalStateException( "Cannot use getTableUnsafe after IArguments has been released" );
|
||||
}
|
||||
|
||||
LuaValue value = varargs.arg( index + 1 );
|
||||
if( !(value instanceof LuaTable) ) throw LuaValues.badArgument( index, "table", value.typeName() );
|
||||
return new TableImpl( this, (LuaTable) value );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Optional<dan200.computercraft.api.lua.LuaTable<?, ?>> optTableUnsafe( int index ) throws LuaException
|
||||
{
|
||||
if( released )
|
||||
{
|
||||
throw new IllegalStateException( "Cannot use optTableUnsafe after IArguments has been released" );
|
||||
}
|
||||
|
||||
LuaValue value = varargs.arg( index + 1 );
|
||||
if( value.isNil() ) return Optional.empty();
|
||||
if( !(value instanceof LuaTable) ) throw LuaValues.badArgument( index, "table", value.typeName() );
|
||||
return Optional.of( new TableImpl( this, (LuaTable) value ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void releaseImmediate()
|
||||
{
|
||||
released = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.fabric.events;
|
||||
|
||||
import net.fabricmc.fabric.api.event.Event;
|
||||
import net.fabricmc.fabric.api.event.EventFactory;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ClientUnloadWorldEvent
|
||||
{
|
||||
Event<ClientUnloadWorldEvent> EVENT = EventFactory.createArrayBacked( ClientUnloadWorldEvent.class,
|
||||
callbacks -> () -> {
|
||||
for( ClientUnloadWorldEvent callback : callbacks )
|
||||
{
|
||||
callback.onClientUnloadWorld();
|
||||
}
|
||||
} );
|
||||
|
||||
void onClientUnloadWorld();
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.fabric.events;
|
||||
|
||||
import net.fabricmc.fabric.api.event.Event;
|
||||
import net.fabricmc.fabric.api.event.EventFactory;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
|
||||
public final class ComputerCraftCustomEvents
|
||||
{
|
||||
public static final Event<ClientUnloadWorld> CLIENT_UNLOAD_WORLD_EVENT = EventFactory.createArrayBacked( ClientUnloadWorld.class,
|
||||
callbacks -> () -> {
|
||||
for( ClientUnloadWorld callback : callbacks )
|
||||
{
|
||||
callback.onClientUnloadWorld();
|
||||
}
|
||||
} );
|
||||
|
||||
public static final Event<ServerPlayerLoadedChunk> SERVER_PLAYER_LOADED_CHUNK_EVENT = EventFactory.createArrayBacked( ServerPlayerLoadedChunk.class,
|
||||
callbacks -> ( serverPlayer, chunkPos ) -> {
|
||||
for( ServerPlayerLoadedChunk callback : callbacks )
|
||||
{
|
||||
callback.onServerPlayerLoadedChunk( serverPlayer, chunkPos );
|
||||
}
|
||||
} );
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ClientUnloadWorld
|
||||
{
|
||||
void onClientUnloadWorld();
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ServerPlayerLoadedChunk
|
||||
{
|
||||
void onServerPlayerLoadedChunk( ServerPlayer player, ChunkPos chunkPos );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.fabric.mixin;
|
||||
|
||||
import dan200.computercraft.shared.peripheral.monitor.MonitorWatcher;
|
||||
import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket;
|
||||
import net.minecraft.server.level.ChunkMap;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import org.apache.commons.lang3.mutable.MutableObject;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin( ChunkMap.class )
|
||||
public class MixinChunkMap
|
||||
{
|
||||
@Final
|
||||
@Shadow
|
||||
ServerLevel level;
|
||||
|
||||
/*
|
||||
* This mixin mimics the logic of Forge's ChunkWatchEvent.Watch but I don't believe it behaves as expected. Instead
|
||||
* of firing once when the player initially come in server view distance of a chunk, it fires every time
|
||||
* the chunk is checked against the player's view distance. This continually happens every tick that the player
|
||||
* moves (or even rotates in place).
|
||||
*/
|
||||
|
||||
// @Inject( method = "updateChunkTracking", at = @At( value = "HEAD" ) )
|
||||
// public void updateChunkTracking( ServerPlayer serverPlayer, ChunkPos chunkPos, MutableObject<ClientboundLevelChunkWithLightPacket> mutableObject, boolean bl, boolean bl2, CallbackInfo ci )
|
||||
// {
|
||||
// if( serverPlayer.level == this.level && bl )
|
||||
// {
|
||||
// ComputerCraftCustomEvents.SERVER_PLAYER_LOADED_CHUNK_EVENT.invoker().onServerPlayerLoadedChunk( serverPlayer, chunkPos );
|
||||
// }
|
||||
// }
|
||||
|
||||
// This version behaves as expected in my testing.
|
||||
@Inject( method = "playerLoadedChunk", at = @At( value = "HEAD" ) )
|
||||
private void playerLoadedChunk( ServerPlayer serverPlayer, MutableObject<ClientboundLevelChunkWithLightPacket> mutableObject, LevelChunk levelChunk, CallbackInfo ci )
|
||||
{
|
||||
MonitorWatcher.onWatch( serverPlayer, levelChunk.getPos() );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.fabric.mixin;
|
||||
|
||||
import dan200.computercraft.shared.common.TileGeneric;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Horrible bodge to ensure a {@link BlockEntity}'s world is always present when setting a TE during another TE's tick.
|
||||
*
|
||||
* Forge does this, this is just a bodge to get Fabric in line with that behaviour.
|
||||
*/
|
||||
@Mixin( Level.class )
|
||||
public class MixinLevel
|
||||
{
|
||||
@Shadow
|
||||
protected boolean tickingBlockEntities;
|
||||
|
||||
@Inject( method = "setBlockEntity", at = @At( "HEAD" ) )
|
||||
public void setBlockEntity( @Nullable BlockEntity entity, CallbackInfo info )
|
||||
{
|
||||
if( entity != null && !entity.isRemoved() && entity.getLevel().isInWorldBounds( entity.getBlockPos() ) && tickingBlockEntities )
|
||||
{
|
||||
setWorld( entity, this );
|
||||
}
|
||||
}
|
||||
|
||||
private static void setWorld( BlockEntity entity, Object world )
|
||||
{
|
||||
if( entity.getLevel() != world && entity instanceof TileGeneric )
|
||||
{
|
||||
entity.setLevel( (Level) world ); //TODO why?
|
||||
}
|
||||
}
|
||||
|
||||
// @Inject( method = "addBlockEntities", at = @At( "HEAD" ) )
|
||||
public void addBlockEntities( Collection<BlockEntity> entities, CallbackInfo info )
|
||||
{
|
||||
if( tickingBlockEntities )
|
||||
{
|
||||
for( BlockEntity entity : entities )
|
||||
{
|
||||
setWorld( entity, this );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
package dan200.computercraft.fabric.mixin;
|
||||
|
||||
import dan200.computercraft.client.FrameInfo;
|
||||
import dan200.computercraft.fabric.events.ClientUnloadWorldEvent;
|
||||
import dan200.computercraft.fabric.events.ComputerCraftCustomEvents;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
@@ -27,12 +27,12 @@ public abstract class MixinMinecraft
|
||||
@Inject( method = "clearLevel(Lnet/minecraft/client/gui/screens/Screen;)V", at = @At( "RETURN" ) )
|
||||
private void disconnectAfter( Screen screen, CallbackInfo info )
|
||||
{
|
||||
ClientUnloadWorldEvent.EVENT.invoker().onClientUnloadWorld();
|
||||
ComputerCraftCustomEvents.CLIENT_UNLOAD_WORLD_EVENT.invoker().onClientUnloadWorld();
|
||||
}
|
||||
|
||||
@Inject( method = "setLevel", at = @At( "RETURN" ) )
|
||||
private void setLevel( ClientLevel world, CallbackInfo info )
|
||||
{
|
||||
ClientUnloadWorldEvent.EVENT.invoker().onClientUnloadWorld();
|
||||
ComputerCraftCustomEvents.CLIENT_UNLOAD_WORLD_EVENT.invoker().onClientUnloadWorld();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
package dan200.computercraft.fabric.mixin;
|
||||
|
||||
import dan200.computercraft.shared.ComputerCraftRegistry;
|
||||
import dan200.computercraft.shared.Registry;
|
||||
import net.minecraft.advancements.CriteriaTriggers;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
@@ -33,7 +33,7 @@ public class MixinServerPlayerGameMode
|
||||
{
|
||||
BlockPos pos = hitResult.getBlockPos();
|
||||
BlockState state = world.getBlockState( pos );
|
||||
if( player.getMainHandItem().getItem() == ComputerCraftRegistry.ModItems.DISK && state.getBlock() == ComputerCraftRegistry.ModBlocks.DISK_DRIVE )
|
||||
if( player.getMainHandItem().getItem() == Registry.ModItems.DISK && state.getBlock() == Registry.ModBlocks.DISK_DRIVE )
|
||||
{
|
||||
InteractionResult actionResult = state.use( world, player, hand, hitResult );
|
||||
if( actionResult.consumesAction() )
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
@@ -34,18 +33,9 @@ public final class BundledRedstone
|
||||
return world.isInWorldBounds( pos ) ? DefaultBundledRedstoneProvider.getDefaultBundledRedstoneOutput( world, pos, side ) : -1;
|
||||
}
|
||||
|
||||
public static int getOutput( Level world, BlockPos pos, Direction side )
|
||||
{
|
||||
int signal = getUnmaskedOutput( world, pos, side );
|
||||
return signal >= 0 ? signal : 0;
|
||||
}
|
||||
|
||||
private static int getUnmaskedOutput( Level world, BlockPos pos, Direction side )
|
||||
{
|
||||
if( !world.isInWorldBounds( pos ) )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if( !world.isInWorldBounds( pos ) ) return -1;
|
||||
|
||||
// Try the providers in order:
|
||||
int combinedSignal = -1;
|
||||
@@ -67,4 +57,10 @@ public final class BundledRedstone
|
||||
|
||||
return combinedSignal;
|
||||
}
|
||||
|
||||
public static int getOutput( Level world, BlockPos pos, Direction side )
|
||||
{
|
||||
int signal = getUnmaskedOutput( world, pos, side );
|
||||
return signal >= 0 ? signal : 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,330 +0,0 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.api.ComputerCraftAPI;
|
||||
import dan200.computercraft.shared.common.ContainerHeldItem;
|
||||
import dan200.computercraft.shared.computer.blocks.BlockComputer;
|
||||
import dan200.computercraft.shared.computer.blocks.TileCommandComputer;
|
||||
import dan200.computercraft.shared.computer.blocks.TileComputer;
|
||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||
import dan200.computercraft.shared.computer.inventory.ComputerMenuWithoutInventory;
|
||||
import dan200.computercraft.shared.computer.inventory.ContainerComputerBase;
|
||||
import dan200.computercraft.shared.computer.inventory.ContainerViewComputer;
|
||||
import dan200.computercraft.shared.computer.items.ItemComputer;
|
||||
import dan200.computercraft.shared.media.items.ItemDisk;
|
||||
import dan200.computercraft.shared.media.items.ItemPrintout;
|
||||
import dan200.computercraft.shared.media.items.ItemTreasureDisk;
|
||||
import dan200.computercraft.shared.network.container.ComputerContainerData;
|
||||
import dan200.computercraft.shared.network.container.ContainerData;
|
||||
import dan200.computercraft.shared.network.container.HeldItemContainerData;
|
||||
import dan200.computercraft.shared.network.container.ViewComputerContainerData;
|
||||
import dan200.computercraft.shared.peripheral.diskdrive.BlockDiskDrive;
|
||||
import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive;
|
||||
import dan200.computercraft.shared.peripheral.diskdrive.TileDiskDrive;
|
||||
import dan200.computercraft.shared.peripheral.modem.wired.*;
|
||||
import dan200.computercraft.shared.peripheral.modem.wireless.BlockWirelessModem;
|
||||
import dan200.computercraft.shared.peripheral.modem.wireless.TileWirelessModem;
|
||||
import dan200.computercraft.shared.peripheral.monitor.BlockMonitor;
|
||||
import dan200.computercraft.shared.peripheral.monitor.TileMonitor;
|
||||
import dan200.computercraft.shared.peripheral.printer.BlockPrinter;
|
||||
import dan200.computercraft.shared.peripheral.printer.ContainerPrinter;
|
||||
import dan200.computercraft.shared.peripheral.printer.TilePrinter;
|
||||
import dan200.computercraft.shared.peripheral.speaker.BlockSpeaker;
|
||||
import dan200.computercraft.shared.peripheral.speaker.TileSpeaker;
|
||||
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
|
||||
import dan200.computercraft.shared.pocket.peripherals.PocketModem;
|
||||
import dan200.computercraft.shared.pocket.peripherals.PocketSpeaker;
|
||||
import dan200.computercraft.shared.turtle.blocks.BlockTurtle;
|
||||
import dan200.computercraft.shared.turtle.blocks.TileTurtle;
|
||||
import dan200.computercraft.shared.turtle.core.TurtlePlayer;
|
||||
import dan200.computercraft.shared.turtle.inventory.ContainerTurtle;
|
||||
import dan200.computercraft.shared.turtle.items.ItemTurtle;
|
||||
import dan200.computercraft.shared.turtle.upgrades.*;
|
||||
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
|
||||
import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder;
|
||||
import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry;
|
||||
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.MobCategory;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraft.world.inventory.MenuType;
|
||||
import net.minecraft.world.item.BlockItem;
|
||||
import net.minecraft.world.item.CreativeModeTab;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.SoundType;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockBehaviour;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.material.Material;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import static net.minecraft.core.Registry.BLOCK_ENTITY_TYPE;
|
||||
|
||||
public final class ComputerCraftRegistry
|
||||
{
|
||||
public static final String MOD_ID = ComputerCraft.MOD_ID;
|
||||
|
||||
public static void init()
|
||||
{
|
||||
Object[] o = {
|
||||
ModTiles.CABLE,
|
||||
ModBlocks.CABLE,
|
||||
ModItems.CABLE,
|
||||
ModEntities.TURTLE_PLAYER,
|
||||
ModContainers.COMPUTER,
|
||||
};
|
||||
|
||||
TurtleUpgrades.registerTurtleUpgrades();
|
||||
PocketUpgrades.registerPocketUpgrades();
|
||||
}
|
||||
|
||||
public static final class ModBlocks
|
||||
{
|
||||
public static final BlockComputer COMPUTER_NORMAL = register( "computer_normal",
|
||||
new BlockComputer( properties(), ComputerFamily.NORMAL, ComputerCraftRegistry.ModTiles.COMPUTER_NORMAL ) );
|
||||
public static final BlockComputer COMPUTER_ADVANCED = register( "computer_advanced",
|
||||
new BlockComputer( properties(),
|
||||
ComputerFamily.ADVANCED,
|
||||
ComputerCraftRegistry.ModTiles.COMPUTER_ADVANCED ) );
|
||||
public static final BlockComputer COMPUTER_COMMAND = register( "computer_command",
|
||||
new BlockComputer( FabricBlockSettings.copyOf( Blocks.STONE )
|
||||
.strength( -1, 6000000.0F ),
|
||||
ComputerFamily.COMMAND,
|
||||
ComputerCraftRegistry.ModTiles.COMPUTER_COMMAND ) );
|
||||
public static final BlockTurtle TURTLE_NORMAL = register( "turtle_normal",
|
||||
new BlockTurtle( turtleProperties(), ComputerFamily.NORMAL, ComputerCraftRegistry.ModTiles.TURTLE_NORMAL ) );
|
||||
public static final BlockTurtle TURTLE_ADVANCED = register( "turtle_advanced",
|
||||
new BlockTurtle( turtleProperties(), ComputerFamily.ADVANCED, ComputerCraftRegistry.ModTiles.TURTLE_ADVANCED ) );
|
||||
public static final BlockSpeaker SPEAKER = register( "speaker", new BlockSpeaker( properties() ) );
|
||||
public static final BlockDiskDrive DISK_DRIVE = register( "disk_drive", new BlockDiskDrive( properties() ) );
|
||||
public static final BlockPrinter PRINTER = register( "printer", new BlockPrinter( properties() ) );
|
||||
public static final BlockMonitor MONITOR_NORMAL = register( "monitor_normal", new BlockMonitor( properties(), ModTiles.MONITOR_NORMAL, false ) );
|
||||
public static final BlockMonitor MONITOR_ADVANCED = register( "monitor_advanced", new BlockMonitor( properties(), ModTiles.MONITOR_ADVANCED, true ) );
|
||||
public static final BlockWirelessModem WIRELESS_MODEM_NORMAL = register( "wireless_modem_normal",
|
||||
new BlockWirelessModem( properties(), ComputerCraftRegistry.ModTiles.WIRELESS_MODEM_NORMAL, ComputerFamily.NORMAL ) );
|
||||
public static final BlockWirelessModem WIRELESS_MODEM_ADVANCED = register( "wireless_modem_advanced",
|
||||
new BlockWirelessModem( properties(), ComputerCraftRegistry.ModTiles.WIRELESS_MODEM_ADVANCED, ComputerFamily.ADVANCED ) );
|
||||
public static final BlockWiredModemFull WIRED_MODEM_FULL = register( "wired_modem_full",
|
||||
new BlockWiredModemFull( modemProperties(), ComputerCraftRegistry.ModTiles.WIRED_MODEM_FULL ) );
|
||||
public static final BlockCable CABLE = register( "cable", new BlockCable( modemProperties() ) );
|
||||
|
||||
private static BlockBehaviour.Properties properties()
|
||||
{
|
||||
//return FabricBlockSettings.copyOf(Blocks.GLASS)
|
||||
// .strength(2);
|
||||
return BlockBehaviour.Properties.of( Material.GLASS )
|
||||
.strength( 2F )
|
||||
.sound( SoundType.STONE )
|
||||
.noOcclusion();
|
||||
}
|
||||
|
||||
private static BlockBehaviour.Properties turtleProperties()
|
||||
{
|
||||
return FabricBlockSettings.copyOf( Blocks.STONE )
|
||||
.strength( 2.5f );
|
||||
}
|
||||
|
||||
private static BlockBehaviour.Properties modemProperties()
|
||||
{
|
||||
return FabricBlockSettings.copyOf( Blocks.STONE )
|
||||
.breakByHand( true )
|
||||
.breakByTool( FabricToolTags.PICKAXES )
|
||||
.strength( 1.5f );
|
||||
}
|
||||
|
||||
public static <T extends Block> T register( String id, T value )
|
||||
{
|
||||
return Registry.register( Registry.BLOCK, new ResourceLocation( MOD_ID, id ), value );
|
||||
}
|
||||
}
|
||||
|
||||
public static class ModTiles
|
||||
{
|
||||
|
||||
public static final BlockEntityType<TileMonitor> MONITOR_NORMAL = ofBlock( ModBlocks.MONITOR_NORMAL,
|
||||
"monitor_normal",
|
||||
( blockPos, blockState ) -> new TileMonitor( ModTiles.MONITOR_NORMAL, false, blockPos, blockState ) );
|
||||
public static final BlockEntityType<TileMonitor> MONITOR_ADVANCED = ofBlock( ModBlocks.MONITOR_ADVANCED,
|
||||
"monitor_advanced",
|
||||
( blockPos, blockState ) -> new TileMonitor( ModTiles.MONITOR_ADVANCED, true, blockPos, blockState ) );
|
||||
public static final BlockEntityType<TileComputer> COMPUTER_NORMAL = ofBlock( ModBlocks.COMPUTER_NORMAL,
|
||||
"computer_normal",
|
||||
( blockPos, blockState ) -> new TileComputer( ComputerFamily.NORMAL, ModTiles.COMPUTER_NORMAL, blockPos, blockState ) );
|
||||
public static final BlockEntityType<TileComputer> COMPUTER_ADVANCED = ofBlock( ModBlocks.COMPUTER_ADVANCED,
|
||||
"computer_advanced",
|
||||
( blockPos, blockState ) -> new TileComputer( ComputerFamily.ADVANCED, ModTiles.COMPUTER_ADVANCED, blockPos, blockState ) );
|
||||
public static final BlockEntityType<TileCommandComputer> COMPUTER_COMMAND = ofBlock( ModBlocks.COMPUTER_COMMAND,
|
||||
"computer_command",
|
||||
( blockPos, blockState ) -> new TileCommandComputer( ComputerFamily.COMMAND, ModTiles.COMPUTER_COMMAND, blockPos, blockState ) );
|
||||
public static final BlockEntityType<TileTurtle> TURTLE_NORMAL = ofBlock( ModBlocks.TURTLE_NORMAL,
|
||||
"turtle_normal",
|
||||
( blockPos, blockState ) -> new TileTurtle( ModTiles.TURTLE_NORMAL, blockPos, blockState, ComputerFamily.NORMAL ) );
|
||||
public static final BlockEntityType<TileTurtle> TURTLE_ADVANCED = ofBlock( ModBlocks.TURTLE_ADVANCED,
|
||||
"turtle_advanced",
|
||||
( blockPos, blockState ) -> new TileTurtle( ModTiles.TURTLE_ADVANCED, blockPos, blockState, ComputerFamily.ADVANCED ) );
|
||||
public static final BlockEntityType<TileSpeaker> SPEAKER = ofBlock( ModBlocks.SPEAKER, "speaker",
|
||||
( blockPos, blockState ) -> new TileSpeaker( ModTiles.SPEAKER, blockPos, blockState ) );
|
||||
public static final BlockEntityType<TileDiskDrive> DISK_DRIVE = ofBlock( ModBlocks.DISK_DRIVE, "disk_drive",
|
||||
( blockPos, blockState ) -> new TileDiskDrive( ModTiles.DISK_DRIVE, blockPos, blockState ) );
|
||||
public static final BlockEntityType<TilePrinter> PRINTER = ofBlock( ModBlocks.PRINTER, "printer",
|
||||
( blockPos, blockState ) -> new TilePrinter( ModTiles.PRINTER, blockPos, blockState ) );
|
||||
public static final BlockEntityType<TileWiredModemFull> WIRED_MODEM_FULL = ofBlock( ModBlocks.WIRED_MODEM_FULL,
|
||||
"wired_modem_full",
|
||||
( blockPos, blockState ) -> new TileWiredModemFull( ModTiles.WIRED_MODEM_FULL, blockPos, blockState ) );
|
||||
public static final BlockEntityType<TileCable> CABLE = ofBlock( ModBlocks.CABLE, "cable",
|
||||
( blockPos, blockState ) -> new TileCable( ModTiles.CABLE, blockPos, blockState ) );
|
||||
public static final BlockEntityType<TileWirelessModem> WIRELESS_MODEM_NORMAL = ofBlock( ModBlocks.WIRELESS_MODEM_NORMAL,
|
||||
"wireless_modem_normal",
|
||||
( blockPos, blockState ) -> new TileWirelessModem( ModTiles.WIRELESS_MODEM_NORMAL, false, blockPos, blockState ) );
|
||||
public static final BlockEntityType<TileWirelessModem> WIRELESS_MODEM_ADVANCED = ofBlock( ModBlocks.WIRELESS_MODEM_ADVANCED,
|
||||
"wireless_modem_advanced",
|
||||
( blockPos, blockState ) -> new TileWirelessModem( ModTiles.WIRELESS_MODEM_ADVANCED, true, blockPos, blockState ) );
|
||||
|
||||
private static <T extends BlockEntity> BlockEntityType<T> ofBlock( Block block, String id, BiFunction<BlockPos, BlockState, T> factory )
|
||||
{
|
||||
BlockEntityType<T> blockEntityType = FabricBlockEntityTypeBuilder.create( factory::apply, block ).build();
|
||||
return Registry.register( BLOCK_ENTITY_TYPE,
|
||||
new ResourceLocation( MOD_ID, id ),
|
||||
blockEntityType
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ModItems
|
||||
{
|
||||
private static final CreativeModeTab mainItemGroup = ComputerCraft.MAIN_GROUP;
|
||||
public static final ItemComputer COMPUTER_NORMAL = ofBlock( ModBlocks.COMPUTER_NORMAL, ItemComputer::new );
|
||||
public static final ItemComputer COMPUTER_ADVANCED = ofBlock( ModBlocks.COMPUTER_ADVANCED, ItemComputer::new );
|
||||
public static final ItemComputer COMPUTER_COMMAND = ofBlock( ModBlocks.COMPUTER_COMMAND, ItemComputer::new );
|
||||
public static final ItemPocketComputer POCKET_COMPUTER_NORMAL = register( "pocket_computer_normal",
|
||||
new ItemPocketComputer( properties().stacksTo( 1 ), ComputerFamily.NORMAL ) );
|
||||
public static final ItemPocketComputer POCKET_COMPUTER_ADVANCED = register( "pocket_computer_advanced",
|
||||
new ItemPocketComputer( properties().stacksTo( 1 ),
|
||||
ComputerFamily.ADVANCED ) );
|
||||
public static final ItemTurtle TURTLE_NORMAL = ofBlock( ModBlocks.TURTLE_NORMAL, ItemTurtle::new );
|
||||
public static final ItemTurtle TURTLE_ADVANCED = ofBlock( ModBlocks.TURTLE_ADVANCED, ItemTurtle::new );
|
||||
public static final ItemDisk DISK = register( "disk", new ItemDisk( properties().stacksTo( 1 ) ) );
|
||||
public static final ItemTreasureDisk TREASURE_DISK = register( "treasure_disk", new ItemTreasureDisk( properties().stacksTo( 1 ) ) );
|
||||
public static final ItemPrintout PRINTED_PAGE = register( "printed_page", new ItemPrintout( properties().stacksTo( 1 ), ItemPrintout.Type.PAGE ) );
|
||||
public static final ItemPrintout PRINTED_PAGES = register( "printed_pages", new ItemPrintout( properties().stacksTo( 1 ), ItemPrintout.Type.PAGES ) );
|
||||
public static final ItemPrintout PRINTED_BOOK = register( "printed_book", new ItemPrintout( properties().stacksTo( 1 ), ItemPrintout.Type.BOOK ) );
|
||||
public static final BlockItem SPEAKER = ofBlock( ModBlocks.SPEAKER, BlockItem::new );
|
||||
public static final BlockItem DISK_DRIVE = ofBlock( ModBlocks.DISK_DRIVE, BlockItem::new );
|
||||
public static final BlockItem PRINTER = ofBlock( ModBlocks.PRINTER, BlockItem::new );
|
||||
public static final BlockItem MONITOR_NORMAL = ofBlock( ModBlocks.MONITOR_NORMAL, BlockItem::new );
|
||||
public static final BlockItem MONITOR_ADVANCED = ofBlock( ModBlocks.MONITOR_ADVANCED, BlockItem::new );
|
||||
public static final BlockItem WIRELESS_MODEM_NORMAL = ofBlock( ModBlocks.WIRELESS_MODEM_NORMAL, BlockItem::new );
|
||||
public static final BlockItem WIRELESS_MODEM_ADVANCED = ofBlock( ModBlocks.WIRELESS_MODEM_ADVANCED, BlockItem::new );
|
||||
public static final BlockItem WIRED_MODEM_FULL = ofBlock( ModBlocks.WIRED_MODEM_FULL, BlockItem::new );
|
||||
public static final ItemBlockCable.Cable CABLE = register( "cable", new ItemBlockCable.Cable( ModBlocks.CABLE, properties() ) );
|
||||
public static final ItemBlockCable.WiredModem WIRED_MODEM = register( "wired_modem", new ItemBlockCable.WiredModem( ModBlocks.CABLE, properties() ) );
|
||||
|
||||
private static <B extends Block, I extends Item> I ofBlock( B parent, BiFunction<B, Item.Properties, I> supplier )
|
||||
{
|
||||
return Registry.register( Registry.ITEM, Registry.BLOCK.getKey( parent ), supplier.apply( parent, properties() ) );
|
||||
}
|
||||
|
||||
private static Item.Properties properties()
|
||||
{
|
||||
return new Item.Properties().tab( mainItemGroup );
|
||||
}
|
||||
|
||||
private static <T extends Item> T register( String id, T item )
|
||||
{
|
||||
return Registry.register( Registry.ITEM, new ResourceLocation( MOD_ID, id ), item );
|
||||
}
|
||||
}
|
||||
|
||||
public static class ModEntities
|
||||
{
|
||||
public static final EntityType<TurtlePlayer> TURTLE_PLAYER = Registry.register( Registry.ENTITY_TYPE,
|
||||
new ResourceLocation( MOD_ID, "turtle_player" ),
|
||||
EntityType.Builder.<TurtlePlayer>createNothing( MobCategory.MISC ).noSave()
|
||||
.noSummon()
|
||||
.sized(
|
||||
0,
|
||||
0 )
|
||||
.build(
|
||||
ComputerCraft.MOD_ID + ":turtle_player" ) );
|
||||
}
|
||||
|
||||
public static class ModContainers
|
||||
{
|
||||
public static final MenuType<ContainerComputerBase> COMPUTER = ContainerData.toType( new ResourceLocation( MOD_ID, "computer" ), ModContainers.COMPUTER, ComputerContainerData::new, ComputerMenuWithoutInventory::new );
|
||||
public static final MenuType<ContainerComputerBase> POCKET_COMPUTER = ContainerData.toType( new ResourceLocation( MOD_ID, "pocket_computer" ), ModContainers.POCKET_COMPUTER, ComputerContainerData::new, ComputerMenuWithoutInventory::new );
|
||||
public static final MenuType<ContainerComputerBase> POCKET_COMPUTER_NO_TERM = ContainerData.toType( new ResourceLocation( MOD_ID, "pocket_computer_no_term" ), ModContainers.POCKET_COMPUTER_NO_TERM, ComputerContainerData::new, ComputerMenuWithoutInventory::new );
|
||||
public static final MenuType<ContainerTurtle> TURTLE = ContainerData.toType( new ResourceLocation( MOD_ID, "turtle" ), ComputerContainerData::new, ContainerTurtle::new );
|
||||
public static final MenuType<ContainerDiskDrive> DISK_DRIVE = registerSimple( "disk_drive", ContainerDiskDrive::new );
|
||||
public static final MenuType<ContainerPrinter> PRINTER = registerSimple( "printer", ContainerPrinter::new );
|
||||
public static final MenuType<ContainerHeldItem> PRINTOUT = ContainerData.toType( new ResourceLocation( MOD_ID, "printout" ), HeldItemContainerData::new, ContainerHeldItem::createPrintout );
|
||||
public static final MenuType<ContainerViewComputer> VIEW_COMPUTER = ContainerData.toType( new ResourceLocation( MOD_ID, "view_computer" ), ViewComputerContainerData::new, ContainerViewComputer::new );
|
||||
|
||||
private static <T extends AbstractContainerMenu> MenuType<T> registerSimple( String id,
|
||||
ScreenHandlerRegistry.SimpleClientHandlerFactory<T> function )
|
||||
{
|
||||
return ScreenHandlerRegistry.registerSimple( new ResourceLocation( MOD_ID, id ), function );
|
||||
}
|
||||
}
|
||||
|
||||
public static final class TurtleUpgrades
|
||||
{
|
||||
public static TurtleModem wirelessModemNormal = new TurtleModem( false, new ResourceLocation( ComputerCraft.MOD_ID, "wireless_modem_normal" ) );
|
||||
public static TurtleModem wirelessModemAdvanced = new TurtleModem( true, new ResourceLocation( ComputerCraft.MOD_ID, "wireless_modem_advanced" ) );
|
||||
public static TurtleSpeaker speaker = new TurtleSpeaker( new ResourceLocation( ComputerCraft.MOD_ID, "speaker" ) );
|
||||
|
||||
public static TurtleCraftingTable craftingTable = new TurtleCraftingTable( new ResourceLocation( "minecraft", "crafting_table" ) );
|
||||
public static TurtleSword diamondSword = new TurtleSword( new ResourceLocation( "minecraft", "diamond_sword" ), Items.DIAMOND_SWORD );
|
||||
public static TurtleShovel diamondShovel = new TurtleShovel( new ResourceLocation( "minecraft", "diamond_shovel" ), Items.DIAMOND_SHOVEL );
|
||||
public static TurtleTool diamondPickaxe = new TurtleTool( new ResourceLocation( "minecraft", "diamond_pickaxe" ), Items.DIAMOND_PICKAXE );
|
||||
public static TurtleAxe diamondAxe = new TurtleAxe( new ResourceLocation( "minecraft", "diamond_axe" ), Items.DIAMOND_AXE );
|
||||
public static TurtleHoe diamondHoe = new TurtleHoe( new ResourceLocation( "minecraft", "diamond_hoe" ), Items.DIAMOND_HOE );
|
||||
|
||||
public static TurtleTool netheritePickaxe = new TurtleTool( new ResourceLocation( "minecraft", "netherite_pickaxe" ), Items.NETHERITE_PICKAXE );
|
||||
|
||||
public static void registerTurtleUpgrades()
|
||||
{
|
||||
ComputerCraftAPI.registerTurtleUpgrade( wirelessModemNormal );
|
||||
ComputerCraftAPI.registerTurtleUpgrade( wirelessModemAdvanced );
|
||||
ComputerCraftAPI.registerTurtleUpgrade( speaker );
|
||||
|
||||
ComputerCraftAPI.registerTurtleUpgrade( craftingTable );
|
||||
ComputerCraftAPI.registerTurtleUpgrade( diamondSword );
|
||||
ComputerCraftAPI.registerTurtleUpgrade( diamondShovel );
|
||||
ComputerCraftAPI.registerTurtleUpgrade( diamondPickaxe );
|
||||
ComputerCraftAPI.registerTurtleUpgrade( diamondAxe );
|
||||
ComputerCraftAPI.registerTurtleUpgrade( diamondHoe );
|
||||
|
||||
ComputerCraftAPI.registerTurtleUpgrade( netheritePickaxe );
|
||||
}
|
||||
}
|
||||
|
||||
public static final class PocketUpgrades
|
||||
{
|
||||
public static PocketModem wirelessModemNormal = new PocketModem( false );
|
||||
public static PocketModem wirelessModemAdvanced = new PocketModem( true );
|
||||
public static PocketSpeaker speaker = new PocketSpeaker();
|
||||
|
||||
public static void registerPocketUpgrades()
|
||||
{
|
||||
ComputerCraftAPI.registerPocketUpgrade( wirelessModemNormal );
|
||||
ComputerCraftAPI.registerPocketUpgrade( wirelessModemAdvanced );
|
||||
ComputerCraftAPI.registerPocketUpgrade( speaker );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
@@ -30,10 +29,7 @@ public final class MediaProviders
|
||||
|
||||
public static IMedia get( @Nonnull ItemStack stack )
|
||||
{
|
||||
if( stack.isEmpty() )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if( stack.isEmpty() ) return null;
|
||||
|
||||
// Try the handlers in order:
|
||||
for( IMediaProvider mediaProvider : providers )
|
||||
@@ -41,10 +37,7 @@ public final class MediaProviders
|
||||
try
|
||||
{
|
||||
IMedia media = mediaProvider.getMedia( stack );
|
||||
if( media != null )
|
||||
{
|
||||
return media;
|
||||
}
|
||||
if( media != null ) return media;
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
@@ -47,10 +46,7 @@ public final class Peripherals
|
||||
try
|
||||
{
|
||||
IPeripheral peripheral = peripheralProvider.getPeripheral( world, pos, side );
|
||||
if( peripheral != null )
|
||||
{
|
||||
return peripheral;
|
||||
}
|
||||
if( peripheral != null ) return peripheral;
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
|
||||
@@ -15,6 +15,7 @@ import net.minecraft.world.item.ItemStack;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.*;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public final class PocketUpgrades
|
||||
{
|
||||
@@ -72,17 +73,18 @@ public final class PocketUpgrades
|
||||
return upgradeOwners.get( upgrade );
|
||||
}
|
||||
|
||||
public static Iterable<IPocketUpgrade> getVanillaUpgrades()
|
||||
{
|
||||
List<IPocketUpgrade> vanilla = new ArrayList<>();
|
||||
vanilla.add( ComputerCraftRegistry.PocketUpgrades.wirelessModemNormal );
|
||||
vanilla.add( ComputerCraftRegistry.PocketUpgrades.wirelessModemAdvanced );
|
||||
vanilla.add( ComputerCraftRegistry.PocketUpgrades.speaker );
|
||||
return vanilla;
|
||||
}
|
||||
|
||||
public static Iterable<IPocketUpgrade> getUpgrades()
|
||||
{
|
||||
return Collections.unmodifiableCollection( upgrades.values() );
|
||||
}
|
||||
|
||||
public static Stream<IPocketUpgrade> getVanillaUpgrades()
|
||||
{
|
||||
List<IPocketUpgrade> vanilla = Arrays.asList(
|
||||
Registry.PocketUpgrades.wirelessModemNormal,
|
||||
Registry.PocketUpgrades.wirelessModemAdvanced,
|
||||
Registry.PocketUpgrades.speaker
|
||||
);
|
||||
return vanilla.stream();
|
||||
}
|
||||
}
|
||||
|
||||
404
src/main/java/dan200/computercraft/shared/Registry.java
Normal file
404
src/main/java/dan200/computercraft/shared/Registry.java
Normal file
@@ -0,0 +1,404 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.shared;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.api.ComputerCraftAPI;
|
||||
import dan200.computercraft.api.ComputerCraftTags;
|
||||
import dan200.computercraft.shared.common.ContainerHeldItem;
|
||||
import dan200.computercraft.shared.computer.blocks.BlockComputer;
|
||||
import dan200.computercraft.shared.computer.blocks.TileCommandComputer;
|
||||
import dan200.computercraft.shared.computer.blocks.TileComputer;
|
||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||
import dan200.computercraft.shared.computer.inventory.ComputerMenuWithoutInventory;
|
||||
import dan200.computercraft.shared.computer.inventory.ContainerComputerBase;
|
||||
import dan200.computercraft.shared.computer.inventory.ContainerViewComputer;
|
||||
import dan200.computercraft.shared.computer.items.ItemComputer;
|
||||
import dan200.computercraft.shared.media.items.ItemDisk;
|
||||
import dan200.computercraft.shared.media.items.ItemPrintout;
|
||||
import dan200.computercraft.shared.media.items.ItemTreasureDisk;
|
||||
import dan200.computercraft.shared.network.container.ComputerContainerData;
|
||||
import dan200.computercraft.shared.network.container.ContainerData;
|
||||
import dan200.computercraft.shared.network.container.HeldItemContainerData;
|
||||
import dan200.computercraft.shared.network.container.ViewComputerContainerData;
|
||||
import dan200.computercraft.shared.peripheral.diskdrive.BlockDiskDrive;
|
||||
import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive;
|
||||
import dan200.computercraft.shared.peripheral.diskdrive.TileDiskDrive;
|
||||
import dan200.computercraft.shared.peripheral.modem.wired.*;
|
||||
import dan200.computercraft.shared.peripheral.modem.wireless.BlockWirelessModem;
|
||||
import dan200.computercraft.shared.peripheral.modem.wireless.TileWirelessModem;
|
||||
import dan200.computercraft.shared.peripheral.monitor.BlockMonitor;
|
||||
import dan200.computercraft.shared.peripheral.monitor.TileMonitor;
|
||||
import dan200.computercraft.shared.peripheral.printer.BlockPrinter;
|
||||
import dan200.computercraft.shared.peripheral.printer.ContainerPrinter;
|
||||
import dan200.computercraft.shared.peripheral.printer.TilePrinter;
|
||||
import dan200.computercraft.shared.peripheral.speaker.BlockSpeaker;
|
||||
import dan200.computercraft.shared.peripheral.speaker.TileSpeaker;
|
||||
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
|
||||
import dan200.computercraft.shared.pocket.peripherals.PocketModem;
|
||||
import dan200.computercraft.shared.pocket.peripherals.PocketSpeaker;
|
||||
import dan200.computercraft.shared.turtle.blocks.BlockTurtle;
|
||||
import dan200.computercraft.shared.turtle.blocks.TileTurtle;
|
||||
import dan200.computercraft.shared.turtle.core.TurtlePlayer;
|
||||
import dan200.computercraft.shared.turtle.inventory.ContainerTurtle;
|
||||
import dan200.computercraft.shared.turtle.items.ItemTurtle;
|
||||
import dan200.computercraft.shared.turtle.upgrades.*;
|
||||
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
|
||||
import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder;
|
||||
import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry;
|
||||
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.cauldron.CauldronInteraction;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.MobCategory;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraft.world.inventory.MenuType;
|
||||
import net.minecraft.world.item.*;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.SoundType;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockBehaviour;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.material.Material;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import static net.minecraft.core.Registry.BLOCK_ENTITY_TYPE;
|
||||
|
||||
public final class Registry
|
||||
{
|
||||
public static final String MOD_ID = ComputerCraft.MOD_ID;
|
||||
|
||||
public static void init()
|
||||
{
|
||||
// Touch each static class to force static initializers to run
|
||||
// Maybe there's a better way to do this :/
|
||||
Object[] o = {
|
||||
ModBlockEntities.CABLE,
|
||||
ModBlocks.CABLE,
|
||||
ModItems.CABLE,
|
||||
ModEntities.TURTLE_PLAYER,
|
||||
ModContainers.COMPUTER,
|
||||
};
|
||||
|
||||
TurtleUpgrades.registerTurtleUpgrades();
|
||||
PocketUpgrades.registerPocketUpgrades();
|
||||
|
||||
CauldronInteraction.WATER.put( ModItems.TURTLE_NORMAL, ItemTurtle.CAULDRON_INTERACTION );
|
||||
CauldronInteraction.WATER.put( ModItems.TURTLE_ADVANCED, ItemTurtle.CAULDRON_INTERACTION );
|
||||
}
|
||||
|
||||
public static final class ModBlocks
|
||||
{
|
||||
public static <T extends Block> T register( String id, T value )
|
||||
{
|
||||
return net.minecraft.core.Registry.register( net.minecraft.core.Registry.BLOCK, new ResourceLocation( MOD_ID, id ), value );
|
||||
}
|
||||
|
||||
public static final BlockMonitor MONITOR_NORMAL =
|
||||
register( "monitor_normal", new BlockMonitor( properties(), () -> ModBlockEntities.MONITOR_NORMAL ) );
|
||||
|
||||
public static final BlockMonitor MONITOR_ADVANCED =
|
||||
register( "monitor_advanced", new BlockMonitor( properties(), () -> ModBlockEntities.MONITOR_ADVANCED ) );
|
||||
|
||||
public static final BlockComputer COMPUTER_NORMAL =
|
||||
register( "computer_normal", new BlockComputer( properties(), ComputerFamily.NORMAL, () -> ModBlockEntities.COMPUTER_NORMAL ) );
|
||||
|
||||
public static final BlockComputer COMPUTER_ADVANCED =
|
||||
register( "computer_advanced", new BlockComputer( properties(), ComputerFamily.ADVANCED, () -> ModBlockEntities.COMPUTER_ADVANCED ) );
|
||||
|
||||
public static final BlockComputer COMPUTER_COMMAND =
|
||||
register( "computer_command", new BlockComputer( FabricBlockSettings.copyOf( Blocks.STONE ).strength( -1, 6000000.0F ), ComputerFamily.COMMAND, () -> ModBlockEntities.COMPUTER_COMMAND ) );
|
||||
|
||||
public static final BlockTurtle TURTLE_NORMAL =
|
||||
register( "turtle_normal", new BlockTurtle( turtleProperties(), ComputerFamily.NORMAL, () -> ModBlockEntities.TURTLE_NORMAL ) );
|
||||
|
||||
public static final BlockTurtle TURTLE_ADVANCED =
|
||||
register( "turtle_advanced", new BlockTurtle( turtleProperties(), ComputerFamily.ADVANCED, () -> ModBlockEntities.TURTLE_ADVANCED ) );
|
||||
|
||||
public static final BlockSpeaker SPEAKER =
|
||||
register( "speaker", new BlockSpeaker( properties() ) );
|
||||
|
||||
public static final BlockDiskDrive DISK_DRIVE =
|
||||
register( "disk_drive", new BlockDiskDrive( properties() ) );
|
||||
|
||||
public static final BlockPrinter PRINTER =
|
||||
register( "printer", new BlockPrinter( properties() ) );
|
||||
|
||||
public static final BlockWirelessModem WIRELESS_MODEM_NORMAL =
|
||||
register( "wireless_modem_normal", new BlockWirelessModem( properties(), () -> ModBlockEntities.WIRELESS_MODEM_NORMAL ) );
|
||||
|
||||
public static final BlockWirelessModem WIRELESS_MODEM_ADVANCED =
|
||||
register( "wireless_modem_advanced", new BlockWirelessModem( properties(), () -> ModBlockEntities.WIRELESS_MODEM_ADVANCED ) );
|
||||
|
||||
public static final BlockWiredModemFull WIRED_MODEM_FULL =
|
||||
register( "wired_modem_full", new BlockWiredModemFull( modemProperties() ) );
|
||||
|
||||
public static final BlockCable CABLE =
|
||||
register( "cable", new BlockCable( modemProperties() ) );
|
||||
|
||||
private static BlockBehaviour.Properties properties()
|
||||
{
|
||||
return BlockBehaviour.Properties.of( Material.GLASS ).strength( 2F ).sound( SoundType.STONE ).noOcclusion();
|
||||
}
|
||||
|
||||
private static BlockBehaviour.Properties turtleProperties()
|
||||
{
|
||||
return FabricBlockSettings.copyOf( Blocks.STONE ).strength( 2.5f );
|
||||
}
|
||||
|
||||
private static BlockBehaviour.Properties modemProperties()
|
||||
{
|
||||
return FabricBlockSettings.copyOf( Blocks.STONE ).breakByHand( true ).breakByTool( FabricToolTags.PICKAXES ).strength( 1.5f );
|
||||
}
|
||||
}
|
||||
|
||||
public static class ModBlockEntities
|
||||
{
|
||||
private static <T extends BlockEntity> BlockEntityType<T> ofBlock( Block block, String id, BiFunction<BlockPos, BlockState, T> factory )
|
||||
{
|
||||
BlockEntityType<T> blockEntityType = FabricBlockEntityTypeBuilder.create( factory::apply, block ).build();
|
||||
return net.minecraft.core.Registry.register( BLOCK_ENTITY_TYPE, new ResourceLocation( MOD_ID, id ), blockEntityType );
|
||||
}
|
||||
|
||||
public static final BlockEntityType<TileMonitor> MONITOR_NORMAL =
|
||||
ofBlock( ModBlocks.MONITOR_NORMAL, "monitor_normal", ( blockPos, blockState ) -> new TileMonitor( ModBlockEntities.MONITOR_NORMAL, blockPos, blockState, false ) );
|
||||
|
||||
public static final BlockEntityType<TileMonitor> MONITOR_ADVANCED =
|
||||
ofBlock( ModBlocks.MONITOR_ADVANCED, "monitor_advanced", ( blockPos, blockState ) -> new TileMonitor( ModBlockEntities.MONITOR_ADVANCED, blockPos, blockState, true ) );
|
||||
|
||||
public static final BlockEntityType<TileComputer> COMPUTER_NORMAL =
|
||||
ofBlock( ModBlocks.COMPUTER_NORMAL, "computer_normal", ( blockPos, blockState ) -> new TileComputer( ModBlockEntities.COMPUTER_NORMAL, blockPos, blockState, ComputerFamily.NORMAL ) );
|
||||
|
||||
public static final BlockEntityType<TileComputer> COMPUTER_ADVANCED =
|
||||
ofBlock( ModBlocks.COMPUTER_ADVANCED, "computer_advanced", ( blockPos, blockState ) -> new TileComputer( ModBlockEntities.COMPUTER_ADVANCED, blockPos, blockState, ComputerFamily.ADVANCED ) );
|
||||
|
||||
public static final BlockEntityType<TileCommandComputer> COMPUTER_COMMAND =
|
||||
ofBlock( ModBlocks.COMPUTER_COMMAND, "computer_command", ( blockPos, blockState ) -> new TileCommandComputer( ModBlockEntities.COMPUTER_COMMAND, blockPos, blockState ) );
|
||||
|
||||
public static final BlockEntityType<TileTurtle> TURTLE_NORMAL =
|
||||
ofBlock( ModBlocks.TURTLE_NORMAL, "turtle_normal", ( blockPos, blockState ) -> new TileTurtle( ModBlockEntities.TURTLE_NORMAL, blockPos, blockState, ComputerFamily.NORMAL ) );
|
||||
|
||||
public static final BlockEntityType<TileTurtle> TURTLE_ADVANCED =
|
||||
ofBlock( ModBlocks.TURTLE_ADVANCED, "turtle_advanced", ( blockPos, blockState ) -> new TileTurtle( ModBlockEntities.TURTLE_ADVANCED, blockPos, blockState, ComputerFamily.ADVANCED ) );
|
||||
|
||||
public static final BlockEntityType<TileSpeaker> SPEAKER =
|
||||
ofBlock( ModBlocks.SPEAKER, "speaker", ( blockPos, blockState ) -> new TileSpeaker( ModBlockEntities.SPEAKER, blockPos, blockState ) );
|
||||
|
||||
public static final BlockEntityType<TileDiskDrive> DISK_DRIVE =
|
||||
ofBlock( ModBlocks.DISK_DRIVE, "disk_drive", ( blockPos, blockState ) -> new TileDiskDrive( ModBlockEntities.DISK_DRIVE, blockPos, blockState ) );
|
||||
|
||||
public static final BlockEntityType<TilePrinter> PRINTER =
|
||||
ofBlock( ModBlocks.PRINTER, "printer", ( blockPos, blockState ) -> new TilePrinter( ModBlockEntities.PRINTER, blockPos, blockState ) );
|
||||
|
||||
public static final BlockEntityType<TileWiredModemFull> WIRED_MODEM_FULL =
|
||||
ofBlock( ModBlocks.WIRED_MODEM_FULL, "wired_modem_full", ( blockPos, blockState ) -> new TileWiredModemFull( ModBlockEntities.WIRED_MODEM_FULL, blockPos, blockState ) );
|
||||
|
||||
public static final BlockEntityType<TileCable> CABLE =
|
||||
ofBlock( ModBlocks.CABLE, "cable", ( blockPos, blockState ) -> new TileCable( ModBlockEntities.CABLE, blockPos, blockState ) );
|
||||
|
||||
public static final BlockEntityType<TileWirelessModem> WIRELESS_MODEM_NORMAL =
|
||||
ofBlock( ModBlocks.WIRELESS_MODEM_NORMAL, "wireless_modem_normal", ( blockPos, blockState ) -> new TileWirelessModem( ModBlockEntities.WIRELESS_MODEM_NORMAL, blockPos, blockState, false ) );
|
||||
|
||||
public static final BlockEntityType<TileWirelessModem> WIRELESS_MODEM_ADVANCED =
|
||||
ofBlock( ModBlocks.WIRELESS_MODEM_ADVANCED, "wireless_modem_advanced", ( blockPos, blockState ) -> new TileWirelessModem( ModBlockEntities.WIRELESS_MODEM_ADVANCED, blockPos, blockState, true ) );
|
||||
}
|
||||
|
||||
public static final class ModItems
|
||||
{
|
||||
private static final CreativeModeTab mainItemGroup = ComputerCraft.MAIN_GROUP;
|
||||
|
||||
public static final ItemComputer COMPUTER_NORMAL =
|
||||
ofBlock( ModBlocks.COMPUTER_NORMAL, ItemComputer::new );
|
||||
|
||||
public static final ItemComputer COMPUTER_ADVANCED =
|
||||
ofBlock( ModBlocks.COMPUTER_ADVANCED, ItemComputer::new );
|
||||
|
||||
public static final ItemComputer COMPUTER_COMMAND =
|
||||
ofBlock( ModBlocks.COMPUTER_COMMAND, ItemComputer::new );
|
||||
|
||||
public static final ItemPocketComputer POCKET_COMPUTER_NORMAL =
|
||||
register( "pocket_computer_normal", new ItemPocketComputer( properties().stacksTo( 1 ), ComputerFamily.NORMAL ) );
|
||||
|
||||
public static final ItemPocketComputer POCKET_COMPUTER_ADVANCED =
|
||||
register( "pocket_computer_advanced", new ItemPocketComputer( properties().stacksTo( 1 ), ComputerFamily.ADVANCED ) );
|
||||
|
||||
public static final ItemTurtle TURTLE_NORMAL =
|
||||
ofBlock( ModBlocks.TURTLE_NORMAL, ItemTurtle::new );
|
||||
|
||||
public static final ItemTurtle TURTLE_ADVANCED =
|
||||
ofBlock( ModBlocks.TURTLE_ADVANCED, ItemTurtle::new );
|
||||
|
||||
public static final ItemDisk DISK =
|
||||
register( "disk", new ItemDisk( properties().stacksTo( 1 ) ) );
|
||||
|
||||
public static final ItemTreasureDisk TREASURE_DISK =
|
||||
register( "treasure_disk", new ItemTreasureDisk( properties().stacksTo( 1 ) ) );
|
||||
|
||||
public static final ItemPrintout PRINTED_PAGE =
|
||||
register( "printed_page", new ItemPrintout( properties().stacksTo( 1 ), ItemPrintout.Type.PAGE ) );
|
||||
|
||||
public static final ItemPrintout PRINTED_PAGES =
|
||||
register( "printed_pages", new ItemPrintout( properties().stacksTo( 1 ), ItemPrintout.Type.PAGES ) );
|
||||
|
||||
public static final ItemPrintout PRINTED_BOOK =
|
||||
register( "printed_book", new ItemPrintout( properties().stacksTo( 1 ), ItemPrintout.Type.BOOK ) );
|
||||
|
||||
public static final BlockItem SPEAKER =
|
||||
ofBlock( ModBlocks.SPEAKER, BlockItem::new );
|
||||
|
||||
public static final BlockItem DISK_DRIVE =
|
||||
ofBlock( ModBlocks.DISK_DRIVE, BlockItem::new );
|
||||
|
||||
public static final BlockItem PRINTER =
|
||||
ofBlock( ModBlocks.PRINTER, BlockItem::new );
|
||||
|
||||
public static final BlockItem MONITOR_NORMAL =
|
||||
ofBlock( ModBlocks.MONITOR_NORMAL, BlockItem::new );
|
||||
|
||||
public static final BlockItem MONITOR_ADVANCED =
|
||||
ofBlock( ModBlocks.MONITOR_ADVANCED, BlockItem::new );
|
||||
|
||||
public static final BlockItem WIRELESS_MODEM_NORMAL =
|
||||
ofBlock( ModBlocks.WIRELESS_MODEM_NORMAL, BlockItem::new );
|
||||
|
||||
public static final BlockItem WIRELESS_MODEM_ADVANCED =
|
||||
ofBlock( ModBlocks.WIRELESS_MODEM_ADVANCED, BlockItem::new );
|
||||
|
||||
public static final BlockItem WIRED_MODEM_FULL =
|
||||
ofBlock( ModBlocks.WIRED_MODEM_FULL, BlockItem::new );
|
||||
|
||||
public static final ItemBlockCable.Cable CABLE =
|
||||
register( "cable", new ItemBlockCable.Cable( ModBlocks.CABLE, properties() ) );
|
||||
|
||||
public static final ItemBlockCable.WiredModem WIRED_MODEM =
|
||||
register( "wired_modem", new ItemBlockCable.WiredModem( ModBlocks.CABLE, properties() ) );
|
||||
|
||||
|
||||
private static <B extends Block, I extends Item> I ofBlock( B parent, BiFunction<B, Item.Properties, I> supplier )
|
||||
{
|
||||
return net.minecraft.core.Registry.register( net.minecraft.core.Registry.ITEM, net.minecraft.core.Registry.BLOCK.getKey( parent ), supplier.apply( parent, properties() ) );
|
||||
}
|
||||
|
||||
private static Item.Properties properties()
|
||||
{
|
||||
return new Item.Properties().tab( mainItemGroup );
|
||||
}
|
||||
|
||||
private static <T extends Item> T register( String id, T item )
|
||||
{
|
||||
return net.minecraft.core.Registry.register( net.minecraft.core.Registry.ITEM, new ResourceLocation( MOD_ID, id ), item );
|
||||
}
|
||||
}
|
||||
|
||||
public static class ModEntities
|
||||
{
|
||||
public static final EntityType<TurtlePlayer> TURTLE_PLAYER =
|
||||
net.minecraft.core.Registry.register( net.minecraft.core.Registry.ENTITY_TYPE, new ResourceLocation( MOD_ID, "turtle_player" ),
|
||||
EntityType.Builder.<TurtlePlayer>createNothing( MobCategory.MISC ).noSave().noSummon().sized( 0, 0 ).build( ComputerCraft.MOD_ID + ":turtle_player" ) );
|
||||
}
|
||||
|
||||
public static class ModContainers
|
||||
{
|
||||
public static final MenuType<ContainerComputerBase> COMPUTER =
|
||||
ContainerData.toType( new ResourceLocation( MOD_ID, "computer" ), ModContainers.COMPUTER, ComputerContainerData::new, ComputerMenuWithoutInventory::new );
|
||||
|
||||
public static final MenuType<ContainerComputerBase> POCKET_COMPUTER =
|
||||
ContainerData.toType( new ResourceLocation( MOD_ID, "pocket_computer" ), ModContainers.POCKET_COMPUTER, ComputerContainerData::new, ComputerMenuWithoutInventory::new );
|
||||
|
||||
public static final MenuType<ContainerComputerBase> POCKET_COMPUTER_NO_TERM =
|
||||
ContainerData.toType( new ResourceLocation( MOD_ID, "pocket_computer_no_term" ), ModContainers.POCKET_COMPUTER_NO_TERM, ComputerContainerData::new, ComputerMenuWithoutInventory::new );
|
||||
|
||||
public static final MenuType<ContainerTurtle> TURTLE =
|
||||
ContainerData.toType( new ResourceLocation( MOD_ID, "turtle" ), ComputerContainerData::new, ContainerTurtle::new );
|
||||
|
||||
public static final MenuType<ContainerDiskDrive> DISK_DRIVE =
|
||||
registerSimple( "disk_drive", ContainerDiskDrive::new );
|
||||
|
||||
public static final MenuType<ContainerPrinter> PRINTER =
|
||||
registerSimple( "printer", ContainerPrinter::new );
|
||||
|
||||
public static final MenuType<ContainerHeldItem> PRINTOUT =
|
||||
ContainerData.toType( new ResourceLocation( MOD_ID, "printout" ), HeldItemContainerData::new, ContainerHeldItem::createPrintout );
|
||||
|
||||
public static final MenuType<ContainerViewComputer> VIEW_COMPUTER =
|
||||
ContainerData.toType( new ResourceLocation( MOD_ID, "view_computer" ), ViewComputerContainerData::new, ContainerViewComputer::new );
|
||||
|
||||
private static <T extends AbstractContainerMenu> MenuType<T> registerSimple( String id, ScreenHandlerRegistry.SimpleClientHandlerFactory<T> function )
|
||||
{
|
||||
return ScreenHandlerRegistry.registerSimple( new ResourceLocation( MOD_ID, id ), function );
|
||||
}
|
||||
}
|
||||
|
||||
public static final class TurtleUpgrades
|
||||
{
|
||||
public static TurtleModem wirelessModemNormal =
|
||||
new TurtleModem( new ResourceLocation( ComputerCraft.MOD_ID, "wireless_modem_normal" ), new ItemStack( ModItems.WIRELESS_MODEM_NORMAL ), false );
|
||||
|
||||
public static TurtleModem wirelessModemAdvanced =
|
||||
new TurtleModem( new ResourceLocation( ComputerCraft.MOD_ID, "wireless_modem_advanced" ), new ItemStack( ModItems.WIRELESS_MODEM_ADVANCED ), true );
|
||||
|
||||
public static TurtleSpeaker speaker =
|
||||
new TurtleSpeaker( new ResourceLocation( ComputerCraft.MOD_ID, "speaker" ), new ItemStack( ModItems.SPEAKER ) );
|
||||
|
||||
public static TurtleCraftingTable craftingTable =
|
||||
new TurtleCraftingTable( new ResourceLocation( "minecraft", "crafting_table" ), new ItemStack( Items.CRAFTING_TABLE ) );
|
||||
|
||||
public static TurtleTool diamondSword =
|
||||
new TurtleTool( new ResourceLocation( "minecraft", "diamond_sword" ), Items.DIAMOND_SWORD, 9.0f, ComputerCraftTags.Blocks.TURTLE_SWORD_BREAKABLE );
|
||||
|
||||
public static TurtleTool diamondShovel =
|
||||
new TurtleTool( new ResourceLocation( "minecraft", "diamond_shovel" ), Items.DIAMOND_SHOVEL, 1.0f, ComputerCraftTags.Blocks.TURTLE_SHOVEL_BREAKABLE );
|
||||
|
||||
public static TurtleTool diamondPickaxe =
|
||||
new TurtleTool( new ResourceLocation( "minecraft", "diamond_pickaxe" ), Items.DIAMOND_PICKAXE, 1.0f, null );
|
||||
|
||||
public static TurtleTool diamondAxe =
|
||||
new TurtleTool( new ResourceLocation( "minecraft", "diamond_axe" ), Items.DIAMOND_AXE, 6.0f, null );
|
||||
|
||||
public static TurtleTool diamondHoe =
|
||||
new TurtleTool( new ResourceLocation( "minecraft", "diamond_hoe" ), Items.DIAMOND_HOE, 1.0f, ComputerCraftTags.Blocks.TURTLE_HOE_BREAKABLE );
|
||||
|
||||
public static TurtleTool netheritePickaxe =
|
||||
new TurtleTool( new ResourceLocation( "minecraft", "netherite_pickaxe" ), Items.NETHERITE_PICKAXE, 1.0f, null );
|
||||
|
||||
public static void registerTurtleUpgrades()
|
||||
{
|
||||
ComputerCraftAPI.registerTurtleUpgrade( wirelessModemNormal );
|
||||
ComputerCraftAPI.registerTurtleUpgrade( wirelessModemAdvanced );
|
||||
ComputerCraftAPI.registerTurtleUpgrade( speaker );
|
||||
ComputerCraftAPI.registerTurtleUpgrade( craftingTable );
|
||||
|
||||
ComputerCraftAPI.registerTurtleUpgrade( diamondSword );
|
||||
ComputerCraftAPI.registerTurtleUpgrade( diamondShovel );
|
||||
ComputerCraftAPI.registerTurtleUpgrade( diamondPickaxe );
|
||||
ComputerCraftAPI.registerTurtleUpgrade( diamondAxe );
|
||||
ComputerCraftAPI.registerTurtleUpgrade( diamondHoe );
|
||||
ComputerCraftAPI.registerTurtleUpgrade( netheritePickaxe );
|
||||
}
|
||||
}
|
||||
|
||||
public static final class PocketUpgrades
|
||||
{
|
||||
public static PocketModem wirelessModemNormal = new PocketModem( new ResourceLocation( ComputerCraft.MOD_ID, "wireless_modem_normal" ), new ItemStack( ModItems.WIRELESS_MODEM_NORMAL ), false );
|
||||
|
||||
public static PocketModem wirelessModemAdvanced = new PocketModem( new ResourceLocation( ComputerCraft.MOD_ID, "wireless_modem_advanced" ), new ItemStack( ModItems.WIRELESS_MODEM_ADVANCED ), true );
|
||||
|
||||
public static PocketSpeaker speaker = new PocketSpeaker( new ResourceLocation( ComputerCraft.MOD_ID, "speaker" ), new ItemStack( ModItems.SPEAKER ) );
|
||||
|
||||
public static void registerPocketUpgrades()
|
||||
{
|
||||
ComputerCraftAPI.registerPocketUpgrade( wirelessModemNormal );
|
||||
ComputerCraftAPI.registerPocketUpgrade( wirelessModemAdvanced );
|
||||
ComputerCraftAPI.registerPocketUpgrade( speaker );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -98,17 +98,17 @@ public final class TurtleUpgrades
|
||||
{
|
||||
vanilla = new ITurtleUpgrade[] {
|
||||
// ComputerCraft upgrades
|
||||
ComputerCraftRegistry.TurtleUpgrades.wirelessModemNormal,
|
||||
ComputerCraftRegistry.TurtleUpgrades.wirelessModemAdvanced,
|
||||
ComputerCraftRegistry.TurtleUpgrades.speaker,
|
||||
Registry.TurtleUpgrades.wirelessModemNormal,
|
||||
Registry.TurtleUpgrades.wirelessModemAdvanced,
|
||||
Registry.TurtleUpgrades.speaker,
|
||||
|
||||
// Vanilla Minecraft upgrades
|
||||
ComputerCraftRegistry.TurtleUpgrades.diamondPickaxe,
|
||||
ComputerCraftRegistry.TurtleUpgrades.diamondAxe,
|
||||
ComputerCraftRegistry.TurtleUpgrades.diamondSword,
|
||||
ComputerCraftRegistry.TurtleUpgrades.diamondShovel,
|
||||
ComputerCraftRegistry.TurtleUpgrades.diamondHoe,
|
||||
ComputerCraftRegistry.TurtleUpgrades.craftingTable,
|
||||
Registry.TurtleUpgrades.diamondPickaxe,
|
||||
Registry.TurtleUpgrades.diamondAxe,
|
||||
Registry.TurtleUpgrades.diamondSword,
|
||||
Registry.TurtleUpgrades.diamondShovel,
|
||||
Registry.TurtleUpgrades.diamondHoe,
|
||||
Registry.TurtleUpgrades.craftingTable,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
package dan200.computercraft.shared.command;
|
||||
|
||||
import dan200.computercraft.shared.util.IDAssigner;
|
||||
import me.shedaniel.cloth.api.utils.v1.GameInstanceUtils;
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@@ -28,6 +30,9 @@ public final class ClientCommands
|
||||
// Emulate the command on the client side
|
||||
if( message.startsWith( OPEN_COMPUTER ) )
|
||||
{
|
||||
MinecraftServer server = GameInstanceUtils.getServer();
|
||||
if( server == null || server.isDedicatedServer() ) return false;
|
||||
|
||||
String idStr = message.substring( OPEN_COMPUTER.length() ).trim();
|
||||
int id;
|
||||
try
|
||||
@@ -36,7 +41,7 @@ public final class ClientCommands
|
||||
}
|
||||
catch( NumberFormatException ignore )
|
||||
{
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
File file = new File( IDAssigner.getDir(), "computer/" + id );
|
||||
|
||||
@@ -26,6 +26,7 @@ import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraft.network.chat.TranslatableComponent;
|
||||
@@ -82,15 +83,15 @@ public final class CommandComputerCraft
|
||||
BlockPos pos = new BlockPos( source.getPosition() );
|
||||
|
||||
computers.sort( ( a, b ) -> {
|
||||
if( a.getWorld() == b.getWorld() && a.getWorld() == world )
|
||||
if( a.getLevel() == b.getLevel() && a.getLevel() == world )
|
||||
{
|
||||
return Double.compare( a.getPosition().distSqr( pos ), b.getPosition().distSqr( pos ) );
|
||||
}
|
||||
else if( a.getWorld() == world )
|
||||
else if( a.getLevel() == world )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if( b.getWorld() == world )
|
||||
else if( b.getLevel() == world )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@@ -171,15 +172,14 @@ public final class CommandComputerCraft
|
||||
.arg( "computer", oneComputer() )
|
||||
.executes( context -> {
|
||||
ServerComputer computer = getComputerArgument( context, "computer" );
|
||||
Level world = computer.getWorld();
|
||||
Level world = computer.getLevel();
|
||||
BlockPos pos = computer.getPosition();
|
||||
|
||||
if( world == null || pos == null ) throw TP_NOT_THERE.create();
|
||||
|
||||
Entity entity = context.getSource().getEntityOrException();
|
||||
if( !(entity instanceof ServerPlayer) ) throw TP_NOT_PLAYER.create();
|
||||
if( !(entity instanceof ServerPlayer player) ) throw TP_NOT_PLAYER.create();
|
||||
|
||||
ServerPlayer player = (ServerPlayer) entity;
|
||||
if( player.getCommandSenderWorld() == world )
|
||||
{
|
||||
player.connection.teleport(
|
||||
@@ -236,7 +236,7 @@ public final class CommandComputerCraft
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public MutableComponent getDisplayName()
|
||||
public Component getDisplayName()
|
||||
{
|
||||
return new TranslatableComponent( "gui.computercraft.view_computer" );
|
||||
}
|
||||
@@ -292,7 +292,7 @@ public final class CommandComputerCraft
|
||||
);
|
||||
}
|
||||
|
||||
private static MutableComponent linkComputer( CommandSourceStack source, ServerComputer serverComputer, int computerId )
|
||||
private static Component linkComputer( CommandSourceStack source, ServerComputer serverComputer, int computerId )
|
||||
{
|
||||
MutableComponent out = new TextComponent( "" );
|
||||
|
||||
@@ -333,14 +333,14 @@ public final class CommandComputerCraft
|
||||
|
||||
if( UserLevel.OWNER.test( source ) && isPlayer( source ) )
|
||||
{
|
||||
MutableComponent linkPath = linkStorage( computerId );
|
||||
Component linkPath = linkStorage( computerId );
|
||||
if( linkPath != null ) out.append( " " ).append( linkPath );
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
private static MutableComponent linkPosition( CommandSourceStack context, ServerComputer computer )
|
||||
private static Component linkPosition( CommandSourceStack context, ServerComputer computer )
|
||||
{
|
||||
if( UserLevel.OP.test( context ) )
|
||||
{
|
||||
@@ -356,7 +356,7 @@ public final class CommandComputerCraft
|
||||
}
|
||||
}
|
||||
|
||||
private static MutableComponent linkStorage( int id )
|
||||
private static Component linkStorage( int id )
|
||||
{
|
||||
File file = new File( IDAssigner.getDir(), "computer/" + id );
|
||||
if( !file.isDirectory() ) return null;
|
||||
@@ -398,7 +398,7 @@ public final class CommandComputerCraft
|
||||
|
||||
timings.sort( Comparator.<ComputerTracker, Long>comparing( x -> x.get( sortField ) ).reversed() );
|
||||
|
||||
MutableComponent[] headers = new MutableComponent[1 + fields.size()];
|
||||
Component[] headers = new Component[1 + fields.size()];
|
||||
headers[0] = translate( "commands.computercraft.track.dump.computer" );
|
||||
for( int i = 0; i < fields.size(); i++ ) headers[i + 1] = translate( fields.get( i ).translationKey() );
|
||||
TableBuilder table = new TableBuilder( TRACK_ID, headers );
|
||||
@@ -408,9 +408,9 @@ public final class CommandComputerCraft
|
||||
Computer computer = entry.getComputer();
|
||||
ServerComputer serverComputer = computer == null ? null : lookup.get( computer );
|
||||
|
||||
MutableComponent computerComponent = linkComputer( source, serverComputer, entry.getComputerId() );
|
||||
Component computerComponent = linkComputer( source, serverComputer, entry.getComputerId() );
|
||||
|
||||
MutableComponent[] row = new MutableComponent[1 + fields.size()];
|
||||
Component[] row = new Component[1 + fields.size()];
|
||||
row[0] = computerComponent;
|
||||
for( int i = 0; i < fields.size(); i++ ) row[i + 1] = text( entry.getFormatted( fields.get( i ) ) );
|
||||
table.row( row );
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.command;
|
||||
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
@@ -27,12 +26,13 @@ public final class CommandUtils
|
||||
public static boolean isPlayer( CommandSourceStack output )
|
||||
{
|
||||
Entity sender = output.getEntity();
|
||||
return sender instanceof ServerPlayer && !(sender instanceof FakePlayer) && ((ServerPlayer) sender).connection != null;
|
||||
return sender instanceof ServerPlayer
|
||||
&& !(sender instanceof FakePlayer)
|
||||
&& ((ServerPlayer) sender).connection != null;
|
||||
}
|
||||
|
||||
@SuppressWarnings( "unchecked" )
|
||||
public static CompletableFuture<Suggestions> suggestOnServer( CommandContext<?> context, SuggestionsBuilder builder,
|
||||
Function<CommandContext<CommandSourceStack>, CompletableFuture<Suggestions>> supplier )
|
||||
public static CompletableFuture<Suggestions> suggestOnServer( CommandContext<?> context, SuggestionsBuilder builder, Function<CommandContext<CommandSourceStack>, CompletableFuture<Suggestions>> supplier )
|
||||
{
|
||||
Object source = context.getSource();
|
||||
if( !(source instanceof SharedSuggestionProvider) )
|
||||
@@ -49,26 +49,21 @@ public final class CommandUtils
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> CompletableFuture<Suggestions> suggest( SuggestionsBuilder builder, T[] candidates, Function<T, String> toString )
|
||||
{
|
||||
return suggest( builder, Arrays.asList( candidates ), toString );
|
||||
}
|
||||
|
||||
public static <T> CompletableFuture<Suggestions> suggest( SuggestionsBuilder builder, Iterable<T> candidates, Function<T, String> toString )
|
||||
{
|
||||
String remaining = builder.getRemaining()
|
||||
.toLowerCase( Locale.ROOT );
|
||||
String remaining = builder.getRemaining().toLowerCase( Locale.ROOT );
|
||||
for( T choice : candidates )
|
||||
{
|
||||
String name = toString.apply( choice );
|
||||
if( !name.toLowerCase( Locale.ROOT )
|
||||
.startsWith( remaining ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if( !name.toLowerCase( Locale.ROOT ).startsWith( remaining ) ) continue;
|
||||
builder.suggest( name );
|
||||
}
|
||||
|
||||
return builder.buildFuture();
|
||||
}
|
||||
|
||||
public static <T> CompletableFuture<Suggestions> suggest( SuggestionsBuilder builder, T[] candidates, Function<T, String> toString )
|
||||
{
|
||||
return suggest( builder, Arrays.asList( candidates ), toString );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.command;
|
||||
|
||||
import com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType;
|
||||
@@ -17,12 +16,15 @@ public final class Exceptions
|
||||
public static final Dynamic2CommandExceptionType COMPUTER_ARG_MANY = translated2( "argument.computercraft.computer.many_matching" );
|
||||
|
||||
public static final DynamicCommandExceptionType TRACKING_FIELD_ARG_NONE = translated1( "argument.computercraft.tracking_field.no_field" );
|
||||
public static final SimpleCommandExceptionType ARGUMENT_EXPECTED = translated( "argument.computercraft.argument_expected" );
|
||||
|
||||
static final SimpleCommandExceptionType NOT_TRACKING_EXCEPTION = translated( "commands.computercraft.track.stop.not_enabled" );
|
||||
static final SimpleCommandExceptionType NO_TIMINGS_EXCEPTION = translated( "commands.computercraft.track.dump.no_timings" );
|
||||
|
||||
static final SimpleCommandExceptionType TP_NOT_THERE = translated( "commands.computercraft.tp.not_there" );
|
||||
static final SimpleCommandExceptionType TP_NOT_PLAYER = translated( "commands.computercraft.tp.not_player" );
|
||||
|
||||
public static final SimpleCommandExceptionType ARGUMENT_EXPECTED = translated( "argument.computercraft.argument_expected" );
|
||||
|
||||
private static SimpleCommandExceptionType translated( String key )
|
||||
{
|
||||
return new SimpleCommandExceptionType( new TranslatableComponent( key ) );
|
||||
|
||||
@@ -67,6 +67,6 @@ public enum UserLevel implements Predicate<CommandSourceStack>
|
||||
Entity sender = source.getEntity();
|
||||
return server.isDedicatedServer()
|
||||
? source.getEntity() == null && source.hasPermission( 4 ) && source.getTextName().equals( "Server" )
|
||||
: sender instanceof Player && ((Player) sender).getGameProfile().getName().equalsIgnoreCase( server.getServerModName() );
|
||||
: sender instanceof Player player && player.getGameProfile().getName().equalsIgnoreCase( server.getServerModName() );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.command.arguments;
|
||||
|
||||
import com.mojang.brigadier.arguments.ArgumentType;
|
||||
@@ -15,17 +14,10 @@ import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
public final class ArgumentSerializers
|
||||
{
|
||||
public static void register()
|
||||
@SuppressWarnings( "unchecked" )
|
||||
private static <T extends ArgumentType<?>> void registerUnsafe( ResourceLocation id, Class<T> type, ArgumentSerializer<?> serializer )
|
||||
{
|
||||
register( new ResourceLocation( ComputerCraft.MOD_ID, "tracking_field" ), TrackingFieldArgumentType.trackingField() );
|
||||
register( new ResourceLocation( ComputerCraft.MOD_ID, "computer" ), ComputerArgumentType.oneComputer() );
|
||||
register( new ResourceLocation( ComputerCraft.MOD_ID, "computers" ), ComputersArgumentType.class, new ComputersArgumentType.Serializer() );
|
||||
registerUnsafe( new ResourceLocation( ComputerCraft.MOD_ID, "repeat" ), RepeatArgumentType.class, new RepeatArgumentType.Serializer() );
|
||||
}
|
||||
|
||||
private static <T extends ArgumentType<?>> void register( ResourceLocation id, T instance )
|
||||
{
|
||||
registerUnsafe( id, instance.getClass(), new EmptyArgumentSerializer<>( () -> instance ) );
|
||||
ArgumentTypes.register( id.toString(), type, (ArgumentSerializer<T>) serializer );
|
||||
}
|
||||
|
||||
private static <T extends ArgumentType<?>> void register( ResourceLocation id, Class<T> type, ArgumentSerializer<T> serializer )
|
||||
@@ -33,9 +25,16 @@ public final class ArgumentSerializers
|
||||
ArgumentTypes.register( id.toString(), type, serializer );
|
||||
}
|
||||
|
||||
@SuppressWarnings( "unchecked" )
|
||||
private static <T extends ArgumentType<?>> void registerUnsafe( ResourceLocation id, Class<T> type, ArgumentSerializer<?> serializer )
|
||||
private static <T extends ArgumentType<?>> void register( ResourceLocation id, T instance )
|
||||
{
|
||||
ArgumentTypes.register( id.toString(), type, (ArgumentSerializer<T>) serializer );
|
||||
registerUnsafe( id, instance.getClass(), new EmptyArgumentSerializer<>( () -> instance ) );
|
||||
}
|
||||
|
||||
public static void register()
|
||||
{
|
||||
register( new ResourceLocation( ComputerCraft.MOD_ID, "tracking_field" ), TrackingFieldArgumentType.trackingField() );
|
||||
register( new ResourceLocation( ComputerCraft.MOD_ID, "computer" ), ComputerArgumentType.oneComputer() );
|
||||
register( new ResourceLocation( ComputerCraft.MOD_ID, "computers" ), ComputersArgumentType.class, new ComputersArgumentType.Serializer() );
|
||||
registerUnsafe( new ResourceLocation( ComputerCraft.MOD_ID, "repeat" ), RepeatArgumentType.class, new RepeatArgumentType.Serializer() );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.command.arguments;
|
||||
|
||||
import com.mojang.brigadier.Message;
|
||||
@@ -43,10 +42,7 @@ public abstract class ChoiceArgumentType<T> implements ArgumentType<T>
|
||||
for( T choice : choices )
|
||||
{
|
||||
String choiceName = this.name.apply( choice );
|
||||
if( name.equals( choiceName ) )
|
||||
{
|
||||
return choice;
|
||||
}
|
||||
if( name.equals( choiceName ) ) return choice;
|
||||
}
|
||||
|
||||
reader.setCursor( start );
|
||||
@@ -56,16 +52,11 @@ public abstract class ChoiceArgumentType<T> implements ArgumentType<T>
|
||||
@Override
|
||||
public <S> CompletableFuture<Suggestions> listSuggestions( CommandContext<S> context, SuggestionsBuilder builder )
|
||||
{
|
||||
String remaining = builder.getRemaining()
|
||||
.toLowerCase( Locale.ROOT );
|
||||
String remaining = builder.getRemaining().toLowerCase( Locale.ROOT );
|
||||
for( T choice : choices )
|
||||
{
|
||||
String name = this.name.apply( choice );
|
||||
if( !name.toLowerCase( Locale.ROOT )
|
||||
.startsWith( remaining ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if( !name.toLowerCase( Locale.ROOT ).startsWith( remaining ) ) continue;
|
||||
builder.suggest( name, tooltip.apply( choice ) );
|
||||
}
|
||||
|
||||
@@ -76,10 +67,7 @@ public abstract class ChoiceArgumentType<T> implements ArgumentType<T>
|
||||
public Collection<String> getExamples()
|
||||
{
|
||||
List<String> items = choices instanceof Collection<?> ? new ArrayList<>( ((Collection<T>) choices).size() ) : new ArrayList<>();
|
||||
for( T choice : choices )
|
||||
{
|
||||
items.add( name.apply( choice ) );
|
||||
}
|
||||
for( T choice : choices ) items.add( name.apply( choice ) );
|
||||
items.sort( Comparator.naturalOrder() );
|
||||
return items;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.command.arguments;
|
||||
|
||||
import com.mojang.brigadier.StringReader;
|
||||
@@ -25,10 +24,6 @@ public final class ComputerArgumentType implements ArgumentType<ComputerArgument
|
||||
{
|
||||
private static final ComputerArgumentType INSTANCE = new ComputerArgumentType();
|
||||
|
||||
private ComputerArgumentType()
|
||||
{
|
||||
}
|
||||
|
||||
public static ComputerArgumentType oneComputer()
|
||||
{
|
||||
return INSTANCE;
|
||||
@@ -36,27 +31,24 @@ public final class ComputerArgumentType implements ArgumentType<ComputerArgument
|
||||
|
||||
public static ServerComputer getComputerArgument( CommandContext<CommandSourceStack> context, String name ) throws CommandSyntaxException
|
||||
{
|
||||
return context.getArgument( name, ComputerSupplier.class )
|
||||
.unwrap( context.getSource() );
|
||||
return context.getArgument( name, ComputerSupplier.class ).unwrap( context.getSource() );
|
||||
}
|
||||
|
||||
private ComputerArgumentType()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComputerSupplier parse( StringReader reader ) throws CommandSyntaxException
|
||||
{
|
||||
int start = reader.getCursor();
|
||||
ComputersSupplier supplier = ComputersArgumentType.someComputers()
|
||||
.parse( reader );
|
||||
String selector = reader.getString()
|
||||
.substring( start, reader.getCursor() );
|
||||
ComputersSupplier supplier = ComputersArgumentType.someComputers().parse( reader );
|
||||
String selector = reader.getString().substring( start, reader.getCursor() );
|
||||
|
||||
return s -> {
|
||||
Collection<ServerComputer> computers = supplier.unwrap( s );
|
||||
|
||||
if( computers.size() == 1 )
|
||||
{
|
||||
return computers.iterator()
|
||||
.next();
|
||||
}
|
||||
if( computers.size() == 1 ) return computers.iterator().next();
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
boolean first = true;
|
||||
@@ -84,15 +76,13 @@ public final class ComputerArgumentType implements ArgumentType<ComputerArgument
|
||||
@Override
|
||||
public <S> CompletableFuture<Suggestions> listSuggestions( CommandContext<S> context, SuggestionsBuilder builder )
|
||||
{
|
||||
return ComputersArgumentType.someComputers()
|
||||
.listSuggestions( context, builder );
|
||||
return ComputersArgumentType.someComputers().listSuggestions( context, builder );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getExamples()
|
||||
{
|
||||
return ComputersArgumentType.someComputers()
|
||||
.getExamples();
|
||||
return ComputersArgumentType.someComputers().getExamples();
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.command.arguments;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
@@ -36,13 +35,9 @@ public final class ComputersArgumentType implements ArgumentType<ComputersArgume
|
||||
private static final ComputersArgumentType MANY = new ComputersArgumentType( false );
|
||||
private static final ComputersArgumentType SOME = new ComputersArgumentType( true );
|
||||
|
||||
private static final List<String> EXAMPLES = Arrays.asList( "0", "#0", "@Label", "~Advanced" );
|
||||
private final boolean requireSome;
|
||||
|
||||
private ComputersArgumentType( boolean requireSome )
|
||||
{
|
||||
this.requireSome = requireSome;
|
||||
}
|
||||
private static final List<String> EXAMPLES = Arrays.asList(
|
||||
"0", "#0", "@Label", "~Advanced"
|
||||
);
|
||||
|
||||
public static ComputersArgumentType manyComputers()
|
||||
{
|
||||
@@ -56,18 +51,14 @@ public final class ComputersArgumentType implements ArgumentType<ComputersArgume
|
||||
|
||||
public static Collection<ServerComputer> getComputersArgument( CommandContext<CommandSourceStack> context, String name ) throws CommandSyntaxException
|
||||
{
|
||||
return context.getArgument( name, ComputersSupplier.class )
|
||||
.unwrap( context.getSource() );
|
||||
return context.getArgument( name, ComputersSupplier.class ).unwrap( context.getSource() );
|
||||
}
|
||||
|
||||
public static Set<ServerComputer> unwrap( CommandSourceStack source, Collection<ComputersSupplier> suppliers ) throws CommandSyntaxException
|
||||
private final boolean requireSome;
|
||||
|
||||
private ComputersArgumentType( boolean requireSome )
|
||||
{
|
||||
Set<ServerComputer> computers = new HashSet<>();
|
||||
for( ComputersSupplier supplier : suppliers )
|
||||
{
|
||||
computers.addAll( supplier.unwrap( source ) );
|
||||
}
|
||||
return computers;
|
||||
this.requireSome = requireSome;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -86,9 +77,7 @@ public final class ComputersArgumentType implements ArgumentType<ComputersArgume
|
||||
{
|
||||
reader.skip();
|
||||
String family = reader.readUnquotedString();
|
||||
computers = getComputers( x -> x.getFamily()
|
||||
.name()
|
||||
.equalsIgnoreCase( family ) );
|
||||
computers = getComputers( x -> x.getFamily().name().equalsIgnoreCase( family ) );
|
||||
}
|
||||
else if( kind == '#' )
|
||||
{
|
||||
@@ -107,14 +96,10 @@ public final class ComputersArgumentType implements ArgumentType<ComputersArgume
|
||||
|
||||
if( requireSome )
|
||||
{
|
||||
String selector = reader.getString()
|
||||
.substring( start, reader.getCursor() );
|
||||
String selector = reader.getString().substring( start, reader.getCursor() );
|
||||
return source -> {
|
||||
Collection<ServerComputer> matched = computers.unwrap( source );
|
||||
if( matched.isEmpty() )
|
||||
{
|
||||
throw COMPUTER_ARG_NONE.create( selector );
|
||||
}
|
||||
if( matched.isEmpty() ) throw COMPUTER_ARG_NONE.create( selector );
|
||||
return matched;
|
||||
};
|
||||
}
|
||||
@@ -169,8 +154,7 @@ public final class ComputersArgumentType implements ArgumentType<ComputersArgume
|
||||
for( ServerComputer computer : ComputerCraft.serverComputerRegistry.getComputers() )
|
||||
{
|
||||
String converted = renderer.apply( computer );
|
||||
if( converted != null && converted.toLowerCase( Locale.ROOT )
|
||||
.startsWith( remaining ) )
|
||||
if( converted != null && converted.toLowerCase( Locale.ROOT ).startsWith( remaining ) )
|
||||
{
|
||||
builder.suggest( converted );
|
||||
}
|
||||
@@ -179,16 +163,12 @@ public final class ComputersArgumentType implements ArgumentType<ComputersArgume
|
||||
|
||||
private static ComputersSupplier getComputers( Predicate<ServerComputer> predicate )
|
||||
{
|
||||
return s -> Collections.unmodifiableList( ComputerCraft.serverComputerRegistry.getComputers()
|
||||
return s -> Collections.unmodifiableList( ComputerCraft.serverComputerRegistry
|
||||
.getComputers()
|
||||
.stream()
|
||||
.filter( predicate )
|
||||
.collect( Collectors.toList() ) );
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ComputersSupplier
|
||||
{
|
||||
Collection<ServerComputer> unwrap( CommandSourceStack source ) throws CommandSyntaxException;
|
||||
.collect( Collectors.toList() )
|
||||
);
|
||||
}
|
||||
|
||||
public static class Serializer implements ArgumentSerializer<ComputersArgumentType>
|
||||
@@ -213,4 +193,17 @@ public final class ComputersArgumentType implements ArgumentType<ComputersArgume
|
||||
json.addProperty( "requireSome", arg.requireSome );
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ComputersSupplier
|
||||
{
|
||||
Collection<ServerComputer> unwrap( CommandSourceStack source ) throws CommandSyntaxException;
|
||||
}
|
||||
|
||||
public static Set<ServerComputer> unwrap( CommandSourceStack source, Collection<ComputersSupplier> suppliers ) throws CommandSyntaxException
|
||||
{
|
||||
Set<ServerComputer> computers = new HashSet<>();
|
||||
for( ComputersSupplier supplier : suppliers ) computers.addAll( supplier.unwrap( source ) );
|
||||
return computers;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.command.arguments;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
@@ -32,8 +31,8 @@ import java.util.function.BiConsumer;
|
||||
/**
|
||||
* Reads one argument multiple times.
|
||||
*
|
||||
* Note that this must be the last element in an argument chain: in order to improve the quality of error messages, we will always try to consume another
|
||||
* argument while there is input remaining.
|
||||
* Note that this must be the last element in an argument chain: in order to improve the quality of error messages,
|
||||
* we will always try to consume another argument while there is input remaining.
|
||||
*
|
||||
* One problem with how parsers function, is that they must consume some input: and thus we
|
||||
*
|
||||
@@ -73,10 +72,7 @@ public final class RepeatArgumentType<T, U> implements ArgumentType<List<T>>
|
||||
while( true )
|
||||
{
|
||||
reader.skipWhitespace();
|
||||
if( !reader.canRead() )
|
||||
{
|
||||
break;
|
||||
}
|
||||
if( !reader.canRead() ) break;
|
||||
|
||||
int startParse = reader.getCursor();
|
||||
appender.accept( out, child.parse( reader ) );
|
||||
@@ -91,10 +87,7 @@ public final class RepeatArgumentType<T, U> implements ArgumentType<List<T>>
|
||||
// Note that each child may return an empty list, we just require that some actual input
|
||||
// was consumed.
|
||||
// We should probably review that this is sensible in the future.
|
||||
if( !hadSome )
|
||||
{
|
||||
throw some.createWithContext( reader );
|
||||
}
|
||||
if( !hadSome ) throw some.createWithContext( reader );
|
||||
|
||||
return Collections.unmodifiableList( out );
|
||||
}
|
||||
@@ -118,10 +111,7 @@ public final class RepeatArgumentType<T, U> implements ArgumentType<List<T>>
|
||||
|
||||
int cursor = reader.getCursor();
|
||||
reader.skipWhitespace();
|
||||
if( cursor == reader.getCursor() )
|
||||
{
|
||||
break;
|
||||
}
|
||||
if( cursor == reader.getCursor() ) break;
|
||||
previous = reader.getCursor();
|
||||
}
|
||||
|
||||
@@ -147,10 +137,7 @@ public final class RepeatArgumentType<T, U> implements ArgumentType<List<T>>
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@SuppressWarnings( {
|
||||
"unchecked",
|
||||
"rawtypes"
|
||||
} )
|
||||
@SuppressWarnings( { "unchecked", "rawtypes" } )
|
||||
public RepeatArgumentType<?, ?> deserializeFromNetwork( @Nonnull FriendlyByteBuf buf )
|
||||
{
|
||||
boolean isList = buf.readBoolean();
|
||||
@@ -170,12 +157,8 @@ public final class RepeatArgumentType<T, U> implements ArgumentType<List<T>>
|
||||
|
||||
private static Component getMessage( RepeatArgumentType<?, ?> arg )
|
||||
{
|
||||
Message message = arg.some.create()
|
||||
.getRawMessage();
|
||||
if( message instanceof Component )
|
||||
{
|
||||
return (Component) message;
|
||||
}
|
||||
Message message = arg.some.create().getRawMessage();
|
||||
if( message instanceof Component ) return (Component) message;
|
||||
return new TextComponent( message.getString() );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.command.arguments;
|
||||
|
||||
import dan200.computercraft.core.tracking.TrackingField;
|
||||
@@ -17,8 +16,7 @@ public final class TrackingFieldArgumentType extends ChoiceArgumentType<Tracking
|
||||
|
||||
private TrackingFieldArgumentType()
|
||||
{
|
||||
super( TrackingField.fields()
|
||||
.values(), TrackingField::id, x -> translate( x.translationKey() ), Exceptions.TRACKING_FIELD_ARG_NONE );
|
||||
super( TrackingField.fields().values(), TrackingField::id, x -> translate( x.translationKey() ), Exceptions.TRACKING_FIELD_ARG_NONE );
|
||||
}
|
||||
|
||||
public static TrackingFieldArgumentType trackingField()
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.command.builder;
|
||||
|
||||
import com.mojang.brigadier.Command;
|
||||
@@ -25,13 +24,14 @@ import static dan200.computercraft.shared.command.Exceptions.ARGUMENT_EXPECTED;
|
||||
import static dan200.computercraft.shared.command.builder.HelpingArgumentBuilder.literal;
|
||||
|
||||
/**
|
||||
* An alternative way of building command nodes, so one does not have to nest. {@link ArgumentBuilder#then(CommandNode)}s.
|
||||
* An alternative way of building command nodes, so one does not have to nest.
|
||||
* {@link ArgumentBuilder#then(CommandNode)}s.
|
||||
*
|
||||
* @param <S> The command source we consume.
|
||||
*/
|
||||
public class CommandBuilder<S> implements CommandNodeBuilder<S, Command<S>>
|
||||
{
|
||||
private List<ArgumentBuilder<S, ?>> args = new ArrayList<>();
|
||||
private final List<ArgumentBuilder<S, ?>> args = new ArrayList<>();
|
||||
private Predicate<S> requires;
|
||||
|
||||
public static CommandBuilder<CommandSourceStack> args()
|
||||
@@ -58,34 +58,38 @@ public class CommandBuilder<S> implements CommandNodeBuilder<S, Command<S>>
|
||||
return this;
|
||||
}
|
||||
|
||||
public <T> CommandNodeBuilder<S, ArgCommand<S, List<T>>> argManyValue( String name, ArgumentType<T> type, T defaultValue )
|
||||
{
|
||||
return argManyValue( name, type, Collections.singletonList( defaultValue ) );
|
||||
}
|
||||
|
||||
public <T> CommandNodeBuilder<S, ArgCommand<S, List<T>>> argManyValue( String name, ArgumentType<T> type, List<T> empty )
|
||||
{
|
||||
return argMany( name, type, () -> empty );
|
||||
}
|
||||
|
||||
public <T> CommandNodeBuilder<S, ArgCommand<S, List<T>>> argManyValue( String name, ArgumentType<T> type, T defaultValue )
|
||||
{
|
||||
return argManyValue( name, type, Collections.singletonList( defaultValue ) );
|
||||
}
|
||||
|
||||
public <T> CommandNodeBuilder<S, ArgCommand<S, List<T>>> argMany( String name, ArgumentType<T> type, Supplier<List<T>> empty )
|
||||
{
|
||||
return argMany( name, RepeatArgumentType.some( type, ARGUMENT_EXPECTED ), empty );
|
||||
}
|
||||
|
||||
public <T> CommandNodeBuilder<S, ArgCommand<S, List<T>>> argManyFlatten( String name, ArgumentType<List<T>> type, Supplier<List<T>> empty )
|
||||
{
|
||||
return argMany( name, RepeatArgumentType.someFlat( type, ARGUMENT_EXPECTED ), empty );
|
||||
}
|
||||
|
||||
private <T, U> CommandNodeBuilder<S, ArgCommand<S, List<T>>> argMany( String name, RepeatArgumentType<T, ?> type, Supplier<List<T>> empty )
|
||||
{
|
||||
if( args.isEmpty() )
|
||||
{
|
||||
throw new IllegalStateException( "Cannot have empty arg chain builder" );
|
||||
}
|
||||
if( args.isEmpty() ) throw new IllegalStateException( "Cannot have empty arg chain builder" );
|
||||
|
||||
return command -> {
|
||||
// The node for no arguments
|
||||
ArgumentBuilder<S, ?> tail = tail( ctx -> command.run( ctx, empty.get() ) );
|
||||
|
||||
// The node for one or more arguments
|
||||
ArgumentBuilder<S, ?> moreArg = RequiredArgumentBuilder.<S, List<T>>argument( name, type ).executes( ctx -> command.run( ctx, getList( ctx, name ) ) );
|
||||
ArgumentBuilder<S, ?> moreArg = RequiredArgumentBuilder
|
||||
.<S, List<T>>argument( name, type )
|
||||
.executes( ctx -> command.run( ctx, getList( ctx, name ) ) );
|
||||
|
||||
// Chain all of them together!
|
||||
tail.then( moreArg );
|
||||
@@ -93,46 +97,31 @@ public class CommandBuilder<S> implements CommandNodeBuilder<S, Command<S>>
|
||||
};
|
||||
}
|
||||
|
||||
private ArgumentBuilder<S, ?> tail( Command<S> command )
|
||||
{
|
||||
ArgumentBuilder<S, ?> defaultTail = args.get( args.size() - 1 );
|
||||
defaultTail.executes( command );
|
||||
if( requires != null )
|
||||
{
|
||||
defaultTail.requires( requires );
|
||||
}
|
||||
return defaultTail;
|
||||
}
|
||||
|
||||
@SuppressWarnings( "unchecked" )
|
||||
private static <T> List<T> getList( CommandContext<?> context, String name )
|
||||
{
|
||||
return (List<T>) context.getArgument( name, List.class );
|
||||
}
|
||||
|
||||
private CommandNode<S> link( ArgumentBuilder<S, ?> tail )
|
||||
{
|
||||
for( int i = args.size() - 2; i >= 0; i-- )
|
||||
{
|
||||
tail = args.get( i )
|
||||
.then( tail );
|
||||
}
|
||||
return tail.build();
|
||||
}
|
||||
|
||||
public <T> CommandNodeBuilder<S, ArgCommand<S, List<T>>> argManyFlatten( String name, ArgumentType<List<T>> type, Supplier<List<T>> empty )
|
||||
{
|
||||
return argMany( name, RepeatArgumentType.someFlat( type, ARGUMENT_EXPECTED ), empty );
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandNode<S> executes( Command<S> command )
|
||||
{
|
||||
if( args.isEmpty() )
|
||||
{
|
||||
throw new IllegalStateException( "Cannot have empty arg chain builder" );
|
||||
}
|
||||
if( args.isEmpty() ) throw new IllegalStateException( "Cannot have empty arg chain builder" );
|
||||
|
||||
return link( tail( command ) );
|
||||
}
|
||||
|
||||
private ArgumentBuilder<S, ?> tail( Command<S> command )
|
||||
{
|
||||
ArgumentBuilder<S, ?> defaultTail = args.get( args.size() - 1 );
|
||||
defaultTail.executes( command );
|
||||
if( requires != null ) defaultTail.requires( requires );
|
||||
return defaultTail;
|
||||
}
|
||||
|
||||
private CommandNode<S> link( ArgumentBuilder<S, ?> tail )
|
||||
{
|
||||
for( int i = args.size() - 2; i >= 0; i-- ) tail = args.get( i ).then( tail );
|
||||
return tail.build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.command.builder;
|
||||
|
||||
import com.mojang.brigadier.Command;
|
||||
@@ -28,14 +27,11 @@ import static dan200.computercraft.shared.command.text.ChatHelpers.coloured;
|
||||
import static dan200.computercraft.shared.command.text.ChatHelpers.translate;
|
||||
|
||||
/**
|
||||
* An alternative to {@link LiteralArgumentBuilder} which also provides a {@code /... help} command, and defaults to that command when no arguments are
|
||||
* given.
|
||||
* An alternative to {@link LiteralArgumentBuilder} which also provides a {@code /... help} command, and defaults
|
||||
* to that command when no arguments are given.
|
||||
*/
|
||||
public final class HelpingArgumentBuilder extends LiteralArgumentBuilder<CommandSourceStack>
|
||||
{
|
||||
private static final ChatFormatting HEADER = ChatFormatting.LIGHT_PURPLE;
|
||||
private static final ChatFormatting SYNOPSIS = ChatFormatting.AQUA;
|
||||
private static final ChatFormatting NAME = ChatFormatting.GREEN;
|
||||
private final Collection<HelpingArgumentBuilder> children = new ArrayList<>();
|
||||
|
||||
private HelpingArgumentBuilder( String literal )
|
||||
@@ -48,69 +44,16 @@ public final class HelpingArgumentBuilder extends LiteralArgumentBuilder<Command
|
||||
return new HelpingArgumentBuilder( literal );
|
||||
}
|
||||
|
||||
private static Command<CommandSourceStack> helpForChild( CommandNode<CommandSourceStack> node, String id, String command )
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> executes( final Command<CommandSourceStack> command )
|
||||
{
|
||||
return context -> {
|
||||
context.getSource()
|
||||
.sendSuccess( getHelp( context,
|
||||
node,
|
||||
id + "." + node.getName()
|
||||
.replace( '-', '_' ),
|
||||
command + " " + node.getName() ), false );
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
private static Component getHelp( CommandContext<CommandSourceStack> context, CommandNode<CommandSourceStack> node, String id, String command )
|
||||
{
|
||||
// An ugly hack to extract usage information from the dispatcher. We generate a temporary node, generate
|
||||
// the shorthand usage, and emit that.
|
||||
CommandDispatcher<CommandSourceStack> dispatcher = context.getSource()
|
||||
.getServer()
|
||||
.getCommands()
|
||||
.getDispatcher();
|
||||
CommandNode<CommandSourceStack> temp = new LiteralCommandNode<>( "_", null, x -> true, null, null, false );
|
||||
temp.addChild( node );
|
||||
String usage = dispatcher.getSmartUsage( temp, context.getSource() )
|
||||
.get( node )
|
||||
.substring( node.getName()
|
||||
.length() );
|
||||
|
||||
MutableComponent output = new TextComponent( "" ).append( coloured( "/" + command + usage, HEADER ) )
|
||||
.append( " " )
|
||||
.append( coloured( translate( "commands." + id + ".synopsis" ), SYNOPSIS ) )
|
||||
.append( "\n" )
|
||||
.append( translate( "commands." + id + ".desc" ) );
|
||||
|
||||
for( CommandNode<CommandSourceStack> child : node.getChildren() )
|
||||
{
|
||||
if( !child.getRequirement()
|
||||
.test( context.getSource() ) || !(child instanceof LiteralCommandNode) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
output.append( "\n" );
|
||||
|
||||
MutableComponent component = coloured( child.getName(), NAME );
|
||||
component.getStyle()
|
||||
.withClickEvent( new ClickEvent( ClickEvent.Action.SUGGEST_COMMAND, "/" + command + " " + child.getName() ) );
|
||||
output.append( component );
|
||||
|
||||
output.append( " - " )
|
||||
.append( translate( "commands." + id + "." + child.getName() + ".synopsis" ) );
|
||||
}
|
||||
|
||||
return output;
|
||||
throw new IllegalStateException( "Cannot use executes on a HelpingArgumentBuilder" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> then( final ArgumentBuilder<CommandSourceStack, ?> argument )
|
||||
{
|
||||
if( getRedirect() != null )
|
||||
{
|
||||
throw new IllegalStateException( "Cannot add children to a redirected node" );
|
||||
}
|
||||
if( getRedirect() != null ) throw new IllegalStateException( "Cannot add children to a redirected node" );
|
||||
|
||||
if( argument instanceof HelpingArgumentBuilder )
|
||||
{
|
||||
@@ -138,12 +81,6 @@ public final class HelpingArgumentBuilder extends LiteralArgumentBuilder<Command
|
||||
return super.then( argument );
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> executes( final Command<CommandSourceStack> command )
|
||||
{
|
||||
throw new IllegalStateException( "Cannot use executes on a HelpingArgumentBuilder" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralCommandNode<CommandSourceStack> build()
|
||||
{
|
||||
@@ -158,28 +95,24 @@ public final class HelpingArgumentBuilder extends LiteralArgumentBuilder<Command
|
||||
private LiteralCommandNode<CommandSourceStack> buildImpl( String id, String command )
|
||||
{
|
||||
HelpCommand helpCommand = new HelpCommand( id, command );
|
||||
LiteralCommandNode<CommandSourceStack> node = new LiteralCommandNode<>( getLiteral(),
|
||||
helpCommand, getRequirement(),
|
||||
getRedirect(), getRedirectModifier(), isFork() );
|
||||
LiteralCommandNode<CommandSourceStack> node = new LiteralCommandNode<>( getLiteral(), helpCommand, getRequirement(), getRedirect(), getRedirectModifier(), isFork() );
|
||||
helpCommand.node = node;
|
||||
|
||||
// Set up a /... help command
|
||||
LiteralArgumentBuilder<CommandSourceStack> helpNode =
|
||||
LiteralArgumentBuilder.<CommandSourceStack>literal( "help" ).requires( x -> getArguments().stream()
|
||||
.anyMatch(
|
||||
y -> y.getRequirement()
|
||||
.test(
|
||||
x ) ) )
|
||||
.executes( helpCommand );
|
||||
LiteralArgumentBuilder<CommandSourceStack> helpNode = LiteralArgumentBuilder.<CommandSourceStack>literal( "help" )
|
||||
.requires( x -> getArguments().stream().anyMatch( y -> y.getRequirement().test( x ) ) )
|
||||
.executes( helpCommand );
|
||||
|
||||
// Add all normal command children to this and the help node
|
||||
for( CommandNode<CommandSourceStack> child : getArguments() )
|
||||
{
|
||||
node.addChild( child );
|
||||
|
||||
helpNode.then( LiteralArgumentBuilder.<CommandSourceStack>literal( child.getName() ).requires( child.getRequirement() )
|
||||
helpNode.then( LiteralArgumentBuilder.<CommandSourceStack>literal( child.getName() )
|
||||
.requires( child.getRequirement() )
|
||||
.executes( helpForChild( child, id, command ) )
|
||||
.build() );
|
||||
.build()
|
||||
);
|
||||
}
|
||||
|
||||
// And add alternative versions of which forward instead
|
||||
@@ -187,10 +120,12 @@ public final class HelpingArgumentBuilder extends LiteralArgumentBuilder<Command
|
||||
{
|
||||
LiteralCommandNode<CommandSourceStack> child = childBuilder.build( id, command );
|
||||
node.addChild( child );
|
||||
helpNode.then( LiteralArgumentBuilder.<CommandSourceStack>literal( child.getName() ).requires( child.getRequirement() )
|
||||
helpNode.then( LiteralArgumentBuilder.<CommandSourceStack>literal( child.getName() )
|
||||
.requires( child.getRequirement() )
|
||||
.executes( helpForChild( child, id, command ) )
|
||||
.redirect( child.getChild( "help" ) )
|
||||
.build() );
|
||||
.build()
|
||||
);
|
||||
}
|
||||
|
||||
node.addChild( helpNode.build() );
|
||||
@@ -198,6 +133,10 @@ public final class HelpingArgumentBuilder extends LiteralArgumentBuilder<Command
|
||||
return node;
|
||||
}
|
||||
|
||||
private static final ChatFormatting HEADER = ChatFormatting.LIGHT_PURPLE;
|
||||
private static final ChatFormatting SYNOPSIS = ChatFormatting.AQUA;
|
||||
private static final ChatFormatting NAME = ChatFormatting.GREEN;
|
||||
|
||||
private static final class HelpCommand implements Command<CommandSourceStack>
|
||||
{
|
||||
private final String id;
|
||||
@@ -213,9 +152,54 @@ public final class HelpingArgumentBuilder extends LiteralArgumentBuilder<Command
|
||||
@Override
|
||||
public int run( CommandContext<CommandSourceStack> context )
|
||||
{
|
||||
context.getSource()
|
||||
.sendSuccess( getHelp( context, node, id, command ), false );
|
||||
context.getSource().sendSuccess( getHelp( context, node, id, command ), false );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private static Command<CommandSourceStack> helpForChild( CommandNode<CommandSourceStack> node, String id, String command )
|
||||
{
|
||||
return context -> {
|
||||
context.getSource().sendSuccess( getHelp( context, node, id + "." + node.getName().replace( '-', '_' ), command + " " + node.getName() ), false );
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
private static Component getHelp( CommandContext<CommandSourceStack> context, CommandNode<CommandSourceStack> node, String id, String command )
|
||||
{
|
||||
// An ugly hack to extract usage information from the dispatcher. We generate a temporary node, generate
|
||||
// the shorthand usage, and emit that.
|
||||
CommandDispatcher<CommandSourceStack> dispatcher = context.getSource().getServer().getCommands().getDispatcher();
|
||||
CommandNode<CommandSourceStack> temp = new LiteralCommandNode<>( "_", null, x -> true, null, null, false );
|
||||
temp.addChild( node );
|
||||
String usage = dispatcher.getSmartUsage( temp, context.getSource() ).get( node ).substring( node.getName().length() );
|
||||
|
||||
MutableComponent output = new TextComponent( "" )
|
||||
.append( coloured( "/" + command + usage, HEADER ) )
|
||||
.append( " " )
|
||||
.append( coloured( translate( "commands." + id + ".synopsis" ), SYNOPSIS ) )
|
||||
.append( "\n" )
|
||||
.append( translate( "commands." + id + ".desc" ) );
|
||||
|
||||
for( CommandNode<CommandSourceStack> child : node.getChildren() )
|
||||
{
|
||||
if( !child.getRequirement().test( context.getSource() ) || !(child instanceof LiteralCommandNode) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
output.append( "\n" );
|
||||
|
||||
MutableComponent component = coloured( child.getName(), NAME );
|
||||
component.getStyle().withClickEvent( new ClickEvent(
|
||||
ClickEvent.Action.SUGGEST_COMMAND,
|
||||
"/" + command + " " + child.getName()
|
||||
) );
|
||||
output.append( component );
|
||||
|
||||
output.append( " - " ).append( translate( "commands." + id + "." + child.getName() + ".synopsis" ) );
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,14 +20,12 @@ public final class ChatHelpers
|
||||
|
||||
public static MutableComponent coloured( String text, ChatFormatting colour )
|
||||
{
|
||||
MutableComponent component = new TextComponent( text == null ? "" : text );
|
||||
component.setStyle( component.getStyle().withColor( colour ) );
|
||||
return component;
|
||||
return new TextComponent( text == null ? "" : text ).withStyle( colour );
|
||||
}
|
||||
|
||||
public static <T extends MutableComponent> T coloured( T component, ChatFormatting colour )
|
||||
{
|
||||
component.setStyle( component.getStyle().withColor( colour ) );
|
||||
component.withStyle( colour );
|
||||
return component;
|
||||
}
|
||||
|
||||
@@ -46,10 +44,10 @@ public final class ChatHelpers
|
||||
return new TranslatableComponent( text == null ? "" : text, args );
|
||||
}
|
||||
|
||||
public static MutableComponent list( MutableComponent... children )
|
||||
public static MutableComponent list( Component... children )
|
||||
{
|
||||
MutableComponent component = new TextComponent( "" );
|
||||
for( MutableComponent child : children )
|
||||
for( Component child : children )
|
||||
{
|
||||
component.append( child );
|
||||
}
|
||||
@@ -69,12 +67,12 @@ public final class ChatHelpers
|
||||
: coloured( translate( "commands.computercraft.generic.no" ), ChatFormatting.RED );
|
||||
}
|
||||
|
||||
public static MutableComponent link( MutableComponent component, String command, MutableComponent toolTip )
|
||||
public static Component link( MutableComponent component, String command, Component toolTip )
|
||||
{
|
||||
return link( component, new ClickEvent( ClickEvent.Action.RUN_COMMAND, command ), toolTip );
|
||||
}
|
||||
|
||||
public static MutableComponent link( MutableComponent component, ClickEvent click, MutableComponent toolTip )
|
||||
public static Component link( Component component, ClickEvent click, Component toolTip )
|
||||
{
|
||||
Style style = component.getStyle();
|
||||
|
||||
@@ -82,9 +80,7 @@ public final class ChatHelpers
|
||||
style = style.withClickEvent( click );
|
||||
style = style.withHoverEvent( new HoverEvent( HoverEvent.Action.SHOW_TEXT, toolTip ) );
|
||||
|
||||
component.setStyle( style );
|
||||
|
||||
return component;
|
||||
return component.copy().withStyle( style );
|
||||
}
|
||||
|
||||
public static MutableComponent header( String text )
|
||||
@@ -95,9 +91,9 @@ public final class ChatHelpers
|
||||
public static MutableComponent copy( String text )
|
||||
{
|
||||
TextComponent name = new TextComponent( text );
|
||||
name.setStyle( name.getStyle()
|
||||
Style style = name.getStyle()
|
||||
.withClickEvent( new ClickEvent( ClickEvent.Action.COPY_TO_CLIPBOARD, text ) )
|
||||
.withHoverEvent( new HoverEvent( HoverEvent.Action.SHOW_TEXT, new TranslatableComponent( "gui.computercraft.tooltip.copy" ) ) ) );
|
||||
return name;
|
||||
.withHoverEvent( new HoverEvent( HoverEvent.Action.SHOW_TEXT, new TranslatableComponent( "gui.computercraft.tooltip.copy" ) ) );
|
||||
return name.withStyle( style );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.command.text;
|
||||
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
@@ -27,10 +26,7 @@ public class ServerTableFormatter implements TableFormatter
|
||||
public Component getPadding( Component component, int width )
|
||||
{
|
||||
int extraWidth = width - getWidth( component );
|
||||
if( extraWidth <= 0 )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if( extraWidth <= 0 ) return null;
|
||||
return new TextComponent( StringUtils.repeat( ' ', extraWidth ) );
|
||||
}
|
||||
|
||||
@@ -43,8 +39,7 @@ public class ServerTableFormatter implements TableFormatter
|
||||
@Override
|
||||
public int getWidth( Component component )
|
||||
{
|
||||
return component.getString()
|
||||
.length();
|
||||
return component.getString().length();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.command.text;
|
||||
|
||||
import dan200.computercraft.shared.command.CommandUtils;
|
||||
@@ -21,17 +20,14 @@ import java.util.List;
|
||||
public class TableBuilder
|
||||
{
|
||||
private final int id;
|
||||
private int columns = -1;
|
||||
private final Component[] headers;
|
||||
private final ArrayList<Component[]> rows = new ArrayList<>();
|
||||
private int columns = -1;
|
||||
private int additional;
|
||||
|
||||
public TableBuilder( int id, @Nonnull Component... headers )
|
||||
{
|
||||
if( id < 0 )
|
||||
{
|
||||
throw new IllegalArgumentException( "ID must be positive" );
|
||||
}
|
||||
if( id < 0 ) throw new IllegalArgumentException( "ID must be positive" );
|
||||
this.id = id;
|
||||
this.headers = headers;
|
||||
columns = headers.length;
|
||||
@@ -39,47 +35,33 @@ public class TableBuilder
|
||||
|
||||
public TableBuilder( int id )
|
||||
{
|
||||
if( id < 0 )
|
||||
{
|
||||
throw new IllegalArgumentException( "ID must be positive" );
|
||||
}
|
||||
if( id < 0 ) throw new IllegalArgumentException( "ID must be positive" );
|
||||
this.id = id;
|
||||
headers = null;
|
||||
}
|
||||
|
||||
public TableBuilder( int id, @Nonnull String... headers )
|
||||
{
|
||||
if( id < 0 )
|
||||
{
|
||||
throw new IllegalArgumentException( "ID must be positive" );
|
||||
}
|
||||
if( id < 0 ) throw new IllegalArgumentException( "ID must be positive" );
|
||||
this.id = id;
|
||||
this.headers = new Component[headers.length];
|
||||
columns = headers.length;
|
||||
|
||||
for( int i = 0; i < headers.length; i++ )
|
||||
{
|
||||
this.headers[i] = ChatHelpers.header( headers[i] );
|
||||
}
|
||||
for( int i = 0; i < headers.length; i++ ) this.headers[i] = ChatHelpers.header( headers[i] );
|
||||
}
|
||||
|
||||
public void row( @Nonnull Component... row )
|
||||
{
|
||||
if( columns == -1 )
|
||||
{
|
||||
columns = row.length;
|
||||
}
|
||||
if( row.length != columns )
|
||||
{
|
||||
throw new IllegalArgumentException( "Row is the incorrect length" );
|
||||
}
|
||||
if( columns == -1 ) columns = row.length;
|
||||
if( row.length != columns ) throw new IllegalArgumentException( "Row is the incorrect length" );
|
||||
rows.add( row );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the unique identifier for this table type.
|
||||
*
|
||||
* When showing a table within Minecraft, previous instances of this table with the same ID will be removed from chat.
|
||||
* When showing a table within Minecraft, previous instances of this table with
|
||||
* the same ID will be removed from chat.
|
||||
*
|
||||
* @return This table's type.
|
||||
*/
|
||||
@@ -91,7 +73,8 @@ public class TableBuilder
|
||||
/**
|
||||
* Get the number of columns for this table.
|
||||
*
|
||||
* This will be the same as {@link #getHeaders()}'s length if it is is non-{@code null}, otherwise the length of the first column.
|
||||
* This will be the same as {@link #getHeaders()}'s length if it is is non-{@code null},
|
||||
* otherwise the length of the first column.
|
||||
*
|
||||
* @return The number of columns.
|
||||
*/
|
||||
@@ -122,6 +105,20 @@ public class TableBuilder
|
||||
this.additional = additional;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim this table to a given height.
|
||||
*
|
||||
* @param height The desired height.
|
||||
*/
|
||||
public void trim( int height )
|
||||
{
|
||||
if( rows.size() > height )
|
||||
{
|
||||
additional += rows.size() - height - 1;
|
||||
rows.subList( height - 1, rows.size() ).clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void display( CommandSourceStack source )
|
||||
{
|
||||
if( CommandUtils.isPlayer( source ) )
|
||||
@@ -135,19 +132,4 @@ public class TableBuilder
|
||||
new ServerTableFormatter( source ).display( this );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim this table to a given height.
|
||||
*
|
||||
* @param height The desired height.
|
||||
*/
|
||||
public void trim( int height )
|
||||
{
|
||||
if( rows.size() > height )
|
||||
{
|
||||
additional += rows.size() - height - 1;
|
||||
rows.subList( height - 1, rows.size() )
|
||||
.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.command.text;
|
||||
|
||||
import net.minecraft.ChatFormatting;
|
||||
@@ -21,12 +20,30 @@ public interface TableFormatter
|
||||
Component SEPARATOR = coloured( "| ", ChatFormatting.GRAY );
|
||||
Component HEADER = coloured( "=", ChatFormatting.GRAY );
|
||||
|
||||
/**
|
||||
* Get additional padding for the component.
|
||||
*
|
||||
* @param component The component to pad
|
||||
* @param width The desired width for the component
|
||||
* @return The padding for this component, or {@code null} if none is needed.
|
||||
*/
|
||||
@Nullable
|
||||
Component getPadding( Component component, int width );
|
||||
|
||||
/**
|
||||
* Get the minimum padding between each column.
|
||||
*
|
||||
* @return The minimum padding.
|
||||
*/
|
||||
int getColumnPadding();
|
||||
|
||||
int getWidth( Component component );
|
||||
|
||||
void writeLine( int id, Component component );
|
||||
|
||||
default int display( TableBuilder table )
|
||||
{
|
||||
if( table.getColumns() <= 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if( table.getColumns() <= 0 ) return 0;
|
||||
|
||||
int rowId = table.getId();
|
||||
int columns = table.getColumns();
|
||||
@@ -35,10 +52,7 @@ public interface TableFormatter
|
||||
Component[] headers = table.getHeaders();
|
||||
if( headers != null )
|
||||
{
|
||||
for( int i = 0; i < columns; i++ )
|
||||
{
|
||||
maxWidths[i] = getWidth( headers[i] );
|
||||
}
|
||||
for( int i = 0; i < columns; i++ ) maxWidths[i] = getWidth( headers[i] );
|
||||
}
|
||||
|
||||
for( Component[] row : table.getRows() )
|
||||
@@ -46,28 +60,19 @@ public interface TableFormatter
|
||||
for( int i = 0; i < row.length; i++ )
|
||||
{
|
||||
int width = getWidth( row[i] );
|
||||
if( width > maxWidths[i] )
|
||||
{
|
||||
maxWidths[i] = width;
|
||||
}
|
||||
if( width > maxWidths[i] ) maxWidths[i] = width;
|
||||
}
|
||||
}
|
||||
|
||||
// Add a small amount of padding after each column
|
||||
{
|
||||
int padding = getColumnPadding();
|
||||
for( int i = 0; i < maxWidths.length - 1; i++ )
|
||||
{
|
||||
maxWidths[i] += padding;
|
||||
}
|
||||
for( int i = 0; i < maxWidths.length - 1; i++ ) maxWidths[i] += padding;
|
||||
}
|
||||
|
||||
// And compute the total width
|
||||
int totalWidth = (columns - 1) * getWidth( SEPARATOR );
|
||||
for( int x : maxWidths )
|
||||
{
|
||||
totalWidth += x;
|
||||
}
|
||||
for( int x : maxWidths ) totalWidth += x;
|
||||
|
||||
if( headers != null )
|
||||
{
|
||||
@@ -76,10 +81,7 @@ public interface TableFormatter
|
||||
{
|
||||
line.append( headers[i] );
|
||||
Component padding = getPadding( headers[i], maxWidths[i] );
|
||||
if( padding != null )
|
||||
{
|
||||
line.append( padding );
|
||||
}
|
||||
if( padding != null ) line.append( padding );
|
||||
line.append( SEPARATOR );
|
||||
}
|
||||
line.append( headers[columns - 1] );
|
||||
@@ -100,10 +102,7 @@ public interface TableFormatter
|
||||
{
|
||||
line.append( row[i] );
|
||||
Component padding = getPadding( row[i], maxWidths[i] );
|
||||
if( padding != null )
|
||||
{
|
||||
line.append( padding );
|
||||
}
|
||||
if( padding != null ) line.append( padding );
|
||||
line.append( SEPARATOR );
|
||||
}
|
||||
line.append( row[columns - 1] );
|
||||
@@ -117,25 +116,4 @@ public interface TableFormatter
|
||||
|
||||
return rowId - table.getId();
|
||||
}
|
||||
|
||||
int getWidth( Component component );
|
||||
|
||||
/**
|
||||
* Get the minimum padding between each column.
|
||||
*
|
||||
* @return The minimum padding.
|
||||
*/
|
||||
int getColumnPadding();
|
||||
|
||||
/**
|
||||
* Get additional padding for the component.
|
||||
*
|
||||
* @param component The component to pad
|
||||
* @param width The desired width for the component
|
||||
* @return The padding for this component, or {@code null} if none is needed.
|
||||
*/
|
||||
@Nullable
|
||||
Component getPadding( Component component, int width );
|
||||
|
||||
void writeLine( int id, Component component );
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.common;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
@@ -23,66 +22,45 @@ import net.minecraft.world.phys.BlockHitResult;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Random;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public abstract class BlockGeneric extends BaseEntityBlock
|
||||
{
|
||||
private final BlockEntityType<? extends TileGeneric> type;
|
||||
private final Supplier<? extends BlockEntityType<? extends TileGeneric>> type;
|
||||
|
||||
public BlockGeneric( Properties settings, BlockEntityType<? extends TileGeneric> type )
|
||||
public BlockGeneric( Properties settings, Supplier<? extends BlockEntityType<? extends TileGeneric>> type )
|
||||
{
|
||||
super( settings );
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public BlockEntityType<? extends TileGeneric> getType()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RenderShape getRenderShape( BlockState state )
|
||||
{
|
||||
return RenderShape.MODEL;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public final void neighborChanged( @Nonnull BlockState state, Level world, @Nonnull BlockPos pos, @Nonnull Block neighbourBlock,
|
||||
@Nonnull BlockPos neighbourPos, boolean isMoving )
|
||||
{
|
||||
BlockEntity tile = world.getBlockEntity( pos );
|
||||
if( tile instanceof TileGeneric )
|
||||
{
|
||||
((TileGeneric) tile).onNeighbourChange( neighbourPos );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public final void onRemove( @Nonnull BlockState block, @Nonnull Level world, @Nonnull BlockPos pos, BlockState replace, boolean bool )
|
||||
{
|
||||
if( block.getBlock() == replace.getBlock() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
if( block.getBlock() == replace.getBlock() ) return;
|
||||
|
||||
BlockEntity tile = world.getBlockEntity( pos );
|
||||
super.onRemove( block, world, pos, replace, bool );
|
||||
world.removeBlockEntity( pos );
|
||||
if( tile instanceof TileGeneric )
|
||||
{
|
||||
((TileGeneric) tile).destroy();
|
||||
}
|
||||
if( tile instanceof TileGeneric generic ) generic.destroy();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@Deprecated
|
||||
public final InteractionResult use( @Nonnull BlockState state, Level world, @Nonnull BlockPos pos, @Nonnull Player player, @Nonnull InteractionHand hand,
|
||||
@Nonnull BlockHitResult hit )
|
||||
public final InteractionResult use( @Nonnull BlockState state, Level world, @Nonnull BlockPos pos, @Nonnull Player player, @Nonnull InteractionHand hand, @Nonnull BlockHitResult hit )
|
||||
{
|
||||
BlockEntity tile = world.getBlockEntity( pos );
|
||||
return tile instanceof TileGeneric ? ((TileGeneric) tile).onActivate( player, hand, hit ) : InteractionResult.PASS;
|
||||
return tile instanceof TileGeneric generic ? generic.onActivate( player, hand, hit ) : InteractionResult.PASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public final void neighborChanged( @Nonnull BlockState state, Level world, @Nonnull BlockPos pos, @Nonnull Block neighbourBlock, @Nonnull BlockPos neighbourPos, boolean isMoving )
|
||||
{
|
||||
BlockEntity tile = world.getBlockEntity( pos );
|
||||
if( tile instanceof TileGeneric generic ) generic.onNeighbourChange( neighbourPos );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -90,20 +68,21 @@ public abstract class BlockGeneric extends BaseEntityBlock
|
||||
public void tick( @Nonnull BlockState state, ServerLevel world, @Nonnull BlockPos pos, @Nonnull Random rand )
|
||||
{
|
||||
BlockEntity te = world.getBlockEntity( pos );
|
||||
if( te instanceof TileGeneric )
|
||||
{
|
||||
((TileGeneric) te).blockTick();
|
||||
}
|
||||
if( te instanceof TileGeneric generic ) generic.blockTick();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockEntity newBlockEntity( BlockPos pos, BlockState state )
|
||||
public BlockEntity newBlockEntity( @Nonnull BlockPos pos, @Nonnull BlockState state )
|
||||
{
|
||||
if( this.type != null )
|
||||
{
|
||||
return type.create( pos, state );
|
||||
}
|
||||
return null;
|
||||
return type.get().create( pos, state );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@Deprecated
|
||||
public RenderShape getRenderShape( @Nonnull BlockState state )
|
||||
{
|
||||
return RenderShape.MODEL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,12 +3,10 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.common;
|
||||
|
||||
import dan200.computercraft.core.terminal.Terminal;
|
||||
import dan200.computercraft.shared.network.client.TerminalState;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
|
||||
public class ClientTerminal implements ITerminal
|
||||
{
|
||||
@@ -79,19 +77,4 @@ public class ClientTerminal implements ITerminal
|
||||
terminalChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void readDescription( CompoundTag nbt )
|
||||
{
|
||||
colour = nbt.getBoolean( "colour" );
|
||||
if( nbt.contains( "terminal" ) )
|
||||
{
|
||||
CompoundTag terminal = nbt.getCompound( "terminal" );
|
||||
resizeTerminal( terminal.getInt( "term_width" ), terminal.getInt( "term_height" ) );
|
||||
this.terminal.readFromNBT( terminal );
|
||||
}
|
||||
else
|
||||
{
|
||||
deleteTerminal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.common;
|
||||
|
||||
import dan200.computercraft.shared.util.ColourTracker;
|
||||
@@ -21,8 +20,6 @@ import javax.annotation.Nonnull;
|
||||
|
||||
public final class ColourableRecipe extends CustomRecipe
|
||||
{
|
||||
public static final RecipeSerializer<?> SERIALIZER = new SimpleRecipeSerializer<>( ColourableRecipe::new );
|
||||
|
||||
private ColourableRecipe( ResourceLocation id )
|
||||
{
|
||||
super( id );
|
||||
@@ -36,17 +33,11 @@ public final class ColourableRecipe extends CustomRecipe
|
||||
for( int i = 0; i < inv.getContainerSize(); i++ )
|
||||
{
|
||||
ItemStack stack = inv.getItem( i );
|
||||
if( stack.isEmpty() )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if( stack.isEmpty() ) continue;
|
||||
|
||||
if( stack.getItem() instanceof IColouredItem )
|
||||
{
|
||||
if( hasColourable )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if( hasColourable ) return false;
|
||||
hasColourable = true;
|
||||
}
|
||||
else if( ColourUtils.getStackColour( stack ) != null )
|
||||
@@ -74,9 +65,11 @@ public final class ColourableRecipe extends CustomRecipe
|
||||
{
|
||||
ItemStack stack = inv.getItem( i );
|
||||
|
||||
if( stack.isEmpty() )
|
||||
if( stack.isEmpty() ) continue;
|
||||
|
||||
if( stack.getItem() instanceof IColouredItem )
|
||||
{
|
||||
continue;
|
||||
colourable = stack;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -104,4 +97,6 @@ public final class ColourableRecipe extends CustomRecipe
|
||||
{
|
||||
return SERIALIZER;
|
||||
}
|
||||
|
||||
public static final SimpleRecipeSerializer<?> SERIALIZER = new SimpleRecipeSerializer<>( ColourableRecipe::new );
|
||||
}
|
||||
|
||||
@@ -3,10 +3,9 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.common;
|
||||
|
||||
import dan200.computercraft.shared.ComputerCraftRegistry;
|
||||
import dan200.computercraft.shared.Registry;
|
||||
import dan200.computercraft.shared.network.container.HeldItemContainerData;
|
||||
import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
@@ -32,13 +31,12 @@ public class ContainerHeldItem extends AbstractContainerMenu
|
||||
super( type, id );
|
||||
|
||||
this.hand = hand;
|
||||
stack = player.getItemInHand( hand )
|
||||
.copy();
|
||||
stack = player.getItemInHand( hand ).copy();
|
||||
}
|
||||
|
||||
public static ContainerHeldItem createPrintout( int id, Inventory inventory, HeldItemContainerData data )
|
||||
{
|
||||
return new ContainerHeldItem( ComputerCraftRegistry.ModContainers.PRINTOUT, id, inventory.player, data.getHand() );
|
||||
return new ContainerHeldItem( Registry.ModContainers.PRINTOUT, id, inventory.player, data.getHand() );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@@ -50,10 +48,7 @@ public class ContainerHeldItem extends AbstractContainerMenu
|
||||
@Override
|
||||
public boolean stillValid( @Nonnull Player player )
|
||||
{
|
||||
if( !player.isAlive() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if( !player.isAlive() ) return false;
|
||||
|
||||
ItemStack stack = player.getItemInHand( hand );
|
||||
return stack == this.stack || !stack.isEmpty() && !this.stack.isEmpty() && stack.getItem() == this.stack.getItem();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user