mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-10-15 14:07:38 +00:00
Compare commits
493 Commits
v1.20.1-1.
...
v1.21.1-1.
Author | SHA1 | Date | |
---|---|---|---|
![]() |
fbf994e803 | ||
![]() |
8344c0a5c2 | ||
![]() |
a292d33830 | ||
![]() |
341d1c7bc2 | ||
![]() |
531eacfac7 | ||
![]() |
1f3da5205c | ||
![]() |
798ceefafe | ||
![]() |
7c0f79fc3c | ||
![]() |
b35cefc5dd | ||
![]() |
89dd521930 | ||
![]() |
9272e2efcd | ||
![]() |
69353a4fcf | ||
![]() |
ff363dca5a | ||
![]() |
1c51282426 | ||
![]() |
4a3a1c9275 | ||
![]() |
2557dd0af9 | ||
![]() |
b5c0c6e104 | ||
![]() |
876fd8ddb8 | ||
![]() |
ee3b1343b5 | ||
![]() |
b440b964b7 | ||
![]() |
5dfc401b45 | ||
![]() |
418c9be7ac | ||
![]() |
b491f6b11f | ||
![]() |
4344c3072f | ||
![]() |
947001104d | ||
![]() |
8711512769 | ||
![]() |
fdae94b3c1 | ||
![]() |
9c0ce27ce6 | ||
![]() |
c458360b18 | ||
![]() |
09ad6c1905 | ||
![]() |
0e1e8a72d3 | ||
![]() |
ffa6eadc26 | ||
![]() |
7c1e8e1951 | ||
![]() |
b805a34c2d | ||
![]() |
b03546a158 | ||
![]() |
582713467f | ||
![]() |
b6f41a0df5 | ||
![]() |
594738a022 | ||
![]() |
27f2ab364c | ||
![]() |
5a43273757 | ||
![]() |
97e28516fb | ||
![]() |
676fb5fb53 | ||
![]() |
08dc08b5a3 | ||
![]() |
8f4d4038f6 | ||
![]() |
63ba3fe274 | ||
![]() |
749b3df227 | ||
![]() |
b97634b717 | ||
![]() |
1b8344d0a3 | ||
![]() |
b42bc0a01a | ||
![]() |
70a7478529 | ||
![]() |
0cff73e2fc | ||
![]() |
a892739f8e | ||
![]() |
f8785a092f | ||
![]() |
598fc4aefd | ||
![]() |
dd7e8fcefc | ||
![]() |
29c8f96912 | ||
![]() |
b9267ecbfc | ||
![]() |
9d2c2db22b | ||
![]() |
6660966320 | ||
![]() |
3acb231f01 | ||
![]() |
16324e1eac | ||
![]() |
fa33949113 | ||
![]() |
0c04d9de47 | ||
![]() |
32f5c38485 | ||
![]() |
01fe949b3e | ||
![]() |
c03fce275e | ||
![]() |
0998acaa82 | ||
![]() |
12a44fed6f | ||
![]() |
3f8c3b026a | ||
![]() |
0a8d505323 | ||
![]() |
237a0ac3bb | ||
![]() |
b185d088b3 | ||
![]() |
051c70a731 | ||
![]() |
2e2f308ff3 | ||
![]() |
0f123b5efd | ||
![]() |
1278246cf7 | ||
![]() |
88cb03be6b | ||
![]() |
1e25fa9bc3 | ||
![]() |
74f707aaea | ||
![]() |
9bb62b047a | ||
![]() |
4360485880 | ||
![]() |
b69a44a927 | ||
![]() |
7d8f609c49 | ||
![]() |
e7f56c4d25 | ||
![]() |
fa2140d00b | ||
![]() |
03388149b1 | ||
![]() |
f212861370 | ||
![]() |
4f3663ccc9 | ||
![]() |
53425c1e76 | ||
![]() |
55edced9de | ||
![]() |
dc969c5a78 | ||
![]() |
94ad6dab0e | ||
![]() |
938eb38ad5 | ||
![]() |
6739c4c6c0 | ||
![]() |
d6749f8461 | ||
![]() |
d697c47b80 | ||
![]() |
5ba7f99326 | ||
![]() |
4710ee5bcc | ||
![]() |
62c9e5b08f | ||
![]() |
2ca5850060 | ||
![]() |
ed631b05e7 | ||
![]() |
a2b9490d5c | ||
![]() |
8204944b5f | ||
![]() |
ef0af67e96 | ||
![]() |
9a914e75c4 | ||
![]() |
4a532952d4 | ||
![]() |
546577041b | ||
![]() |
f881c0ced0 | ||
![]() |
0b389e04b0 | ||
![]() |
d3a3ab3c21 | ||
![]() |
22e6c06e59 | ||
![]() |
7337b91692 | ||
![]() |
3c46b8acd7 | ||
![]() |
d9fc1c3a80 | ||
![]() |
479aabdd09 | ||
![]() |
ad74893058 | ||
![]() |
2ba6d5815b | ||
![]() |
7e2f490626 | ||
![]() |
4dc649d5e5 | ||
![]() |
5bab415790 | ||
![]() |
f04c699df6 | ||
![]() |
9bbf3f3e1d | ||
![]() |
a3f8e653d4 | ||
![]() |
7c02979c22 | ||
![]() |
fdb65c9368 | ||
![]() |
ea670cc358 | ||
![]() |
b7396f3796 | ||
![]() |
1963e0160f | ||
![]() |
9a06904634 | ||
![]() |
5eb50ecb06 | ||
![]() |
5e24ad17d7 | ||
![]() |
8b1cb09ddf | ||
![]() |
7af2c14327 | ||
![]() |
d1a6b043c2 | ||
![]() |
cddb8fec11 | ||
![]() |
1d7d8006d4 | ||
![]() |
63bdc2537c | ||
![]() |
f776b17150 | ||
![]() |
0056709999 | ||
![]() |
31da2555cb | ||
![]() |
9b19a93ab9 | ||
![]() |
0c8e757314 | ||
![]() |
f39e86bb10 | ||
![]() |
ad52117f0f | ||
![]() |
bdffabc08e | ||
![]() |
87ce41f251 | ||
![]() |
e7c7919cad | ||
![]() |
4f66ac79d3 | ||
![]() |
ba6da3bc6c | ||
![]() |
b742745854 | ||
![]() |
3293639adf | ||
![]() |
064ff31830 | ||
![]() |
5d473725d5 | ||
![]() |
97a2f2dbdd | ||
![]() |
37c4789fa4 | ||
![]() |
0aaeeeee24 | ||
![]() |
2155ec3d63 | ||
![]() |
0da906fc93 | ||
![]() |
9e5e6a1b60 | ||
![]() |
dcc74e15c7 | ||
![]() |
c271ed7c7f | ||
![]() |
d6a246c122 | ||
![]() |
0bef3ee0d8 | ||
![]() |
bb04df7086 | ||
![]() |
a70baf0d74 | ||
![]() |
86e2f92493 | ||
![]() |
e9aceca1de | ||
![]() |
3042950507 | ||
![]() |
63181e73a1 | ||
![]() |
4f3247a0e2 | ||
![]() |
f7a6aac657 | ||
![]() |
782564e6ab | ||
![]() |
6b8ba8b80b | ||
![]() |
52b76d8886 | ||
![]() |
ba36c69583 | ||
![]() |
370e5f92a0 | ||
![]() |
36d05e4774 | ||
![]() |
89d1be17c9 | ||
![]() |
0069591af9 | ||
![]() |
c36c8605bf | ||
![]() |
3c72a00d46 | ||
![]() |
58aefc8df8 | ||
![]() |
97ddfc2794 | ||
![]() |
4f15f4197b | ||
![]() |
6e4ec86586 | ||
![]() |
0d8ac304c7 | ||
![]() |
fdd5f49369 | ||
![]() |
d24984c1d5 | ||
![]() |
8080dcdd9e | ||
![]() |
d7cea55e2a | ||
![]() |
9b2f974a81 | ||
![]() |
43770fa9bd | ||
![]() |
80c7a54ad4 | ||
![]() |
e57b6fede2 | ||
![]() |
34a2fd039f | ||
![]() |
3299d0e72a | ||
![]() |
b89e2615db | ||
![]() |
cdcd82679c | ||
![]() |
cdfa866760 | ||
![]() |
aa8078ddeb | ||
![]() |
7e53c19d74 | ||
![]() |
b7a8432cfb | ||
![]() |
356c8e8aeb | ||
![]() |
ed283155f7 | ||
![]() |
87dfad026e | ||
![]() |
bb97c465d9 | ||
![]() |
8bd4c3370e | ||
![]() |
3eb84ffedd | ||
![]() |
9484315d37 | ||
![]() |
be59f1a875 | ||
![]() |
bfb28b4710 | ||
![]() |
216f0adb3c | ||
![]() |
dad6874638 | ||
![]() |
77af4bc213 | ||
![]() |
5abab982c7 | ||
![]() |
764e1aa332 | ||
![]() |
c47718b09d | ||
![]() |
45cb597ecc | ||
![]() |
08d4f91c8b | ||
![]() |
b9eac4e509 | ||
![]() |
16577783d3 | ||
![]() |
c179da28f0 | ||
![]() |
dc3d8ea198 | ||
![]() |
cbe075b001 | ||
![]() |
ed0b156e05 | ||
![]() |
2765abf971 | ||
![]() |
4dd0735066 | ||
![]() |
38e516d7c7 | ||
![]() |
70a31855ac | ||
![]() |
6c8e64ffcd | ||
![]() |
7285c32d58 | ||
![]() |
99c60ac54b | ||
![]() |
63e40cf3cb | ||
![]() |
1d45935a25 | ||
![]() |
f80373e7a2 | ||
![]() |
63185629b7 | ||
![]() |
4bfb9ac323 | ||
![]() |
5926b6c994 | ||
![]() |
f5ed43584d | ||
![]() |
2c740bb904 | ||
![]() |
d77f5f135f | ||
![]() |
0e4710a956 | ||
![]() |
aca1d43550 | ||
![]() |
f10e401aea | ||
![]() |
7744d2663b | ||
![]() |
4566cb8273 | ||
![]() |
052e7a7ae5 | ||
![]() |
0895200681 | ||
![]() |
1a1623075f | ||
![]() |
54a95e07a4 | ||
![]() |
09d0f563b7 | ||
![]() |
e188f1d3fa | ||
![]() |
efd9a0f315 | ||
![]() |
28f75a0687 | ||
![]() |
819a4f7231 | ||
![]() |
898cb2a95d | ||
![]() |
03a8f83191 | ||
![]() |
aef92c8ebc | ||
![]() |
571ea794a8 | ||
![]() |
4b102f16b3 | ||
![]() |
e81af93043 | ||
![]() |
bb933d0100 | ||
![]() |
25b8a65c5c | ||
![]() |
e4236824d7 | ||
![]() |
cfd11ffa92 | ||
![]() |
ce133a5e66 | ||
![]() |
038fbc1ed1 | ||
![]() |
c582fb521c | ||
![]() |
af21792844 | ||
![]() |
9fbb1070ef | ||
![]() |
1944995c33 | ||
![]() |
ac851a795b | ||
![]() |
334761788a | ||
![]() |
5af3e15dd5 | ||
![]() |
de078e3037 | ||
![]() |
209b1ddbf9 | ||
![]() |
0c9f9a8652 | ||
![]() |
862d92785e | ||
![]() |
d48b85d50c | ||
![]() |
4d619de357 | ||
![]() |
57c289f173 | ||
![]() |
f63f85921f | ||
![]() |
c7e49d1929 | ||
![]() |
eb584aa94d | ||
![]() |
ad70e2ad90 | ||
![]() |
d9b0cc7075 | ||
![]() |
2c0d8263d3 | ||
![]() |
1e214f329e | ||
![]() |
de930c8d09 | ||
![]() |
94c864759d | ||
![]() |
735e7ce09b | ||
![]() |
2226df7224 | ||
![]() |
959bdaeb61 | ||
![]() |
06ac373e83 | ||
![]() |
0aca6a4dc9 | ||
![]() |
bf203bb1f3 | ||
![]() |
6e9799316a | ||
![]() |
cd9840d1c1 | ||
![]() |
b9a002586c | ||
![]() |
a3b07909b0 | ||
![]() |
d7786ee4b9 | ||
![]() |
4e90240922 | ||
![]() |
1a87d1bf45 | ||
![]() |
188806e8b0 | ||
![]() |
01407544c9 | ||
![]() |
bd2fd9d4c8 | ||
![]() |
00e2e2bd2d | ||
![]() |
7c1f40031b | ||
![]() |
929debd382 | ||
![]() |
4980b7355d | ||
![]() |
5c457950d8 | ||
![]() |
925092add3 | ||
![]() |
550296edc5 | ||
![]() |
0771c4891b | ||
![]() |
776fa00b94 | ||
![]() |
03bb279206 | ||
![]() |
fabd77132d | ||
![]() |
95be0a25bf | ||
![]() |
75f3ecce18 | ||
![]() |
688fdc40a6 | ||
![]() |
22bd5309ba | ||
![]() |
ad49325376 | ||
![]() |
825d45eb26 | ||
![]() |
8b2516abb5 | ||
![]() |
bce099ef32 | ||
![]() |
6d14ce625f | ||
![]() |
c8eadf4011 | ||
![]() |
0c1ab780bb | ||
![]() |
0f623c2cca | ||
![]() |
b9ba2534a4 | ||
![]() |
c764981a40 | ||
![]() |
6363164f2b | ||
![]() |
63580b4acb | ||
![]() |
9af1aa1ecf | ||
![]() |
ad0f551204 | ||
![]() |
0d3e00cc41 | ||
![]() |
836d6b939e | ||
![]() |
0e5248e5e6 | ||
![]() |
e154b0db2a | ||
![]() |
ae767eb5be | ||
![]() |
c50d56d9fa | ||
![]() |
777aa34bb0 | ||
![]() |
286f969f94 | ||
![]() |
7b9a156abc | ||
![]() |
0a9e5c78f3 | ||
![]() |
da5885ef35 | ||
![]() |
57c72711bb | ||
![]() |
cbafbca86b | ||
![]() |
c9caffb10f | ||
![]() |
4675583e1c | ||
![]() |
afe16cc593 | ||
![]() |
0abd107348 | ||
![]() |
cef4b4906b | ||
![]() |
04900dc82f | ||
![]() |
9b63cc81b1 | ||
![]() |
9eead7a0ec | ||
![]() |
ad97b2922b | ||
![]() |
52986f8d73 | ||
![]() |
ab00580389 | ||
![]() |
128ac2f109 | ||
![]() |
5d8c46c7e6 | ||
![]() |
1a5dc92bd4 | ||
![]() |
98b2d3f310 | ||
![]() |
e92c2d02f8 | ||
![]() |
f8ef40d378 | ||
![]() |
61f9b1d0c6 | ||
![]() |
ffb62dfa02 | ||
![]() |
6fb291112d | ||
![]() |
7ee821e9c9 | ||
![]() |
b7df91349a | ||
![]() |
cb8e06af2a | ||
![]() |
6478fca7a2 | ||
![]() |
3493159a05 | ||
![]() |
eead67e314 | ||
![]() |
3b8813cf8f | ||
![]() |
a9191a4d4e | ||
![]() |
451a2593ce | ||
![]() |
d38b1da974 | ||
![]() |
6e374579a4 | ||
![]() |
4daa2a2b6a | ||
![]() |
84b6edab82 | ||
![]() |
31aaf46d09 | ||
![]() |
2d11b51c62 | ||
![]() |
240528cce5 | ||
![]() |
83f1f86888 | ||
![]() |
a0f759527d | ||
![]() |
385e4210fa | ||
![]() |
d2896473f2 | ||
![]() |
f14cb2a3d1 | ||
![]() |
8db5c6bc3a | ||
![]() |
9c202bd1c2 | ||
![]() |
fc834cd97f | ||
![]() |
f26e443e81 | ||
![]() |
033378333f | ||
![]() |
ebeaa757a9 | ||
![]() |
57b1a65db3 | ||
![]() |
27c72a4571 | ||
![]() |
f284328656 | ||
![]() |
6b83c63991 | ||
![]() |
b27526bd21 | ||
![]() |
cb25f6c08a | ||
![]() |
d38b1d04e7 | ||
![]() |
9ccee75a99 | ||
![]() |
359c8d6652 | ||
![]() |
1788afacfc | ||
![]() |
f695f22d8a | ||
![]() |
bc03090ca4 | ||
![]() |
a617d0d566 | ||
![]() |
36599b321e | ||
![]() |
1d6e3f4fc0 | ||
![]() |
30dc4cb38c | ||
![]() |
be4512d1c3 | ||
![]() |
e6ee292850 | ||
![]() |
9d36f72bad | ||
![]() |
b5923c4462 | ||
![]() |
4d1e689719 | ||
![]() |
9d4af07568 | ||
![]() |
89294f4a22 | ||
![]() |
133b51b092 | ||
![]() |
272010e945 | ||
![]() |
e0889c613a | ||
![]() |
f115d43d07 | ||
![]() |
8be6b1b772 | ||
![]() |
104d5e70de | ||
![]() |
e3bda2f763 | ||
![]() |
234f69e8e5 | ||
![]() |
ed3a17f9b9 | ||
![]() |
0349c2b1f9 | ||
![]() |
03f9e6bd6d | ||
![]() |
9d8c933a14 | ||
![]() |
78bb3da58c | ||
![]() |
39a5e40c92 | ||
![]() |
763ba51919 | ||
![]() |
cf6ec8c28f | ||
![]() |
95d3b646b2 | ||
![]() |
488f66eead | ||
![]() |
1f7d245876 | ||
![]() |
af12b3a0ea | ||
![]() |
eb3e8ba677 | ||
![]() |
2043939531 | ||
![]() |
84a799d27a | ||
![]() |
fe826f5c9c | ||
![]() |
f8b7422294 | ||
![]() |
b343c01216 | ||
![]() |
76968f2f28 | ||
![]() |
1d365f5a0b | ||
![]() |
7b240cbf7e | ||
![]() |
d272a327c7 | ||
![]() |
0c0556a5bc | ||
![]() |
87345c6b2e | ||
![]() |
784e623776 | ||
![]() |
bcb3e9bd53 | ||
![]() |
c30bffbd0f | ||
![]() |
91c41856c5 | ||
![]() |
18c9723308 | ||
![]() |
aee382ed70 | ||
![]() |
6656da5877 | ||
![]() |
09e521727f | ||
![]() |
cab66a2d6e | ||
![]() |
8eabd4f303 | ||
![]() |
e3ced84885 | ||
![]() |
0929ab577d | ||
![]() |
2228733abc | ||
![]() |
e67c94d1bd | ||
![]() |
ae5a661a47 | ||
![]() |
0ff58cdc3e | ||
![]() |
1747c74770 | ||
![]() |
71669cf49c | ||
![]() |
bd327e37eb | ||
![]() |
bdce9a8170 | ||
![]() |
7e5598d084 | ||
![]() |
440fca6535 | ||
![]() |
6635edd35c | ||
![]() |
93ad40efbb | ||
![]() |
27dc8b5b2c | ||
![]() |
3ebdf7ef5e | ||
![]() |
905d4cb091 | ||
![]() |
e7ab05d064 | ||
![]() |
6ec34b42e5 | ||
![]() |
ab785a0906 | ||
![]() |
4541decd40 | ||
![]() |
747a5a53b4 | ||
![]() |
c0643fadca | ||
![]() |
0a31de43c2 | ||
![]() |
96b6947ef2 | ||
![]() |
e7a1065bfc | ||
![]() |
663eecff0c | ||
![]() |
e6125bcf60 | ||
![]() |
0d6c6e7ae7 | ||
![]() |
ae71eb3cae | ||
![]() |
3188197447 | ||
![]() |
6c8b391dab | ||
![]() |
b1248e4901 |
@@ -18,11 +18,6 @@ ij_any_if_brace_force = if_multiline
|
|||||||
ij_any_for_brace_force = if_multiline
|
ij_any_for_brace_force = if_multiline
|
||||||
ij_any_spaces_within_array_initializer_braces = true
|
ij_any_spaces_within_array_initializer_braces = true
|
||||||
|
|
||||||
ij_kotlin_allow_trailing_comma = true
|
|
||||||
ij_kotlin_allow_trailing_comma_on_call_site = true
|
|
||||||
ij_kotlin_method_parameters_wrap = off
|
|
||||||
ij_kotlin_call_parameters_wrap = off
|
|
||||||
|
|
||||||
[*.md]
|
[*.md]
|
||||||
trim_trailing_whitespace = false
|
trim_trailing_whitespace = false
|
||||||
|
|
||||||
@@ -31,3 +26,27 @@ indent_size = 2
|
|||||||
|
|
||||||
[*.yml]
|
[*.yml]
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.{kt,kts}]
|
||||||
|
ij_kotlin_code_style_defaults = KOTLIN_OFFICIAL
|
||||||
|
ij_kotlin_continuation_indent_size = 4
|
||||||
|
ij_kotlin_spaces_around_equality_operators = true
|
||||||
|
|
||||||
|
ij_kotlin_allow_trailing_comma = true
|
||||||
|
ij_kotlin_allow_trailing_comma_on_call_site = true
|
||||||
|
|
||||||
|
# Prefer to handle these manually
|
||||||
|
ij_kotlin_method_parameters_wrap = off
|
||||||
|
ij_kotlin_call_parameters_wrap = off
|
||||||
|
ij_kotlin_extends_list_wrap = off
|
||||||
|
|
||||||
|
ktlint_code_style = intellij_idea
|
||||||
|
ktlint_standard_class-naming = disabled
|
||||||
|
ktlint_standard_class-signature = disabled
|
||||||
|
ktlint_standard_function-naming = disabled
|
||||||
|
ktlint_standard_no-wildcard-imports = disabled
|
||||||
|
|
||||||
|
# FIXME: These two are disable right now as they're over-eager in putting things
|
||||||
|
# on the same line. We should set max_line_length and handle this properly.
|
||||||
|
ktlint_standard_function-signature = disabled
|
||||||
|
ktlint_standard_function-expression-body = disabled
|
||||||
|
19
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
19
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
@@ -1,17 +1,17 @@
|
|||||||
name: Bug report
|
name: Bug report
|
||||||
description: Report some misbehaviour in the mod
|
description: Report some misbehaviour in the mod
|
||||||
labels: [ bug ]
|
labels: [ bug ]
|
||||||
|
type: bug
|
||||||
body:
|
body:
|
||||||
- type: dropdown
|
- type: dropdown
|
||||||
id: mc-version
|
id: mc-version
|
||||||
attributes:
|
attributes:
|
||||||
label: Minecraft Version
|
label: Minecraft Version
|
||||||
description: What version of Minecraft are you using?
|
description: |
|
||||||
|
What version of Minecraft are you using? If your version is not listed, please try to reproduce on one of the supported versions.
|
||||||
options:
|
options:
|
||||||
- 1.16.x
|
- 1.20.1
|
||||||
- 1.18.x
|
- 1.21.x
|
||||||
- 1.19.x
|
|
||||||
- 1.20.x
|
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: input
|
- type: input
|
||||||
@@ -28,8 +28,7 @@ body:
|
|||||||
label: Details
|
label: Details
|
||||||
description: |
|
description: |
|
||||||
Description of the bug. Please include the following:
|
Description of the bug. Please include the following:
|
||||||
- Logs: These will be located in the `logs/` directory of your Minecraft
|
- Logs: These will be located in the `logs/` directory of your Minecraft instance. This is always useful, even if it doesn't include errors, so please upload this!
|
||||||
instance. Please upload them as a gist or directly into this editor.
|
- Detailed reproduction steps: sometimes I can spot a bug pretty easily, but often it's much more obscure. The more information I have to help reproduce it, the quicker it'll get fixed.
|
||||||
- Detailed reproduction steps: sometimes I can spot a bug pretty easily,
|
|
||||||
but often it's much more obscure. The more information I have to help
|

|
||||||
reproduce it, the quicker it'll get fixed.
|
|
||||||
|
1
.github/ISSUE_TEMPLATE/feature_request.md
vendored
1
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -2,6 +2,7 @@
|
|||||||
name: Feature request
|
name: Feature request
|
||||||
about: Suggest an idea or improvement
|
about: Suggest an idea or improvement
|
||||||
labels: enhancement
|
labels: enhancement
|
||||||
|
type: feature
|
||||||
---
|
---
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
|
72
.github/workflows/main-ci.yml
vendored
72
.github/workflows/main-ci.yml
vendored
@@ -9,16 +9,16 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: 📥 Clone repository
|
- name: 📥 Clone repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: 📥 Set up Java
|
- name: 📥 Set up Java
|
||||||
uses: actions/setup-java@v3
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
java-version: 17
|
java-version: 21
|
||||||
distribution: 'temurin'
|
distribution: 'temurin'
|
||||||
|
|
||||||
- name: 📥 Setup Gradle
|
- name: 📥 Setup Gradle
|
||||||
uses: gradle/gradle-build-action@v2
|
uses: gradle/actions/setup-gradle@v3
|
||||||
with:
|
with:
|
||||||
cache-read-only: ${{ !startsWith(github.ref, 'refs/heads/mc-') }}
|
cache-read-only: ${{ !startsWith(github.ref, 'refs/heads/mc-') }}
|
||||||
|
|
||||||
@@ -30,8 +30,28 @@ jobs:
|
|||||||
- name: ⚒️ Build
|
- name: ⚒️ Build
|
||||||
run: ./gradlew assemble || ./gradlew assemble
|
run: ./gradlew assemble || ./gradlew assemble
|
||||||
|
|
||||||
|
- name: 📦 Prepare Jars
|
||||||
|
run: |
|
||||||
|
# Find the main jar and append the git hash onto it.
|
||||||
|
mkdir -p jars
|
||||||
|
find projects/forge/build/libs projects/fabric/build/libs -type f -regex '.*[0-9.]+\(-SNAPSHOT\)?\.jar$' -exec bash -c 'cp {} "jars/$(basename {} .jar)-$(git rev-parse HEAD).jar"' \;
|
||||||
|
|
||||||
|
- name: 📤 Upload Jar
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: CC-Tweaked
|
||||||
|
path: ./jars
|
||||||
|
|
||||||
|
- name: Cache pre-commit
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: ~/.cache/pre-commit
|
||||||
|
key: pre-commit-3|${{ env.pythonLocation }}|${{ hashFiles('.pre-commit-config.yaml') }}
|
||||||
|
|
||||||
- name: 💡 Lint
|
- name: 💡 Lint
|
||||||
uses: pre-commit/action@v3.0.0
|
run: |
|
||||||
|
pipx install pre-commit
|
||||||
|
pre-commit run --show-diff-on-failure --color=always
|
||||||
|
|
||||||
- name: 🧪 Run tests
|
- name: 🧪 Run tests
|
||||||
run: ./gradlew test validateMixinNames checkChangelog
|
run: ./gradlew test validateMixinNames checkChangelog
|
||||||
@@ -42,30 +62,10 @@ jobs:
|
|||||||
- name: 🧪 Run integration tests
|
- name: 🧪 Run integration tests
|
||||||
run: ./gradlew runGametest
|
run: ./gradlew runGametest
|
||||||
|
|
||||||
- name: 🧪 Run client tests
|
|
||||||
run: ./gradlew runGametestClient # Not checkClient, as no point running rendering tests.
|
|
||||||
# These are a little flaky on GH actions: its useful to run them, but don't break the build.
|
|
||||||
continue-on-error: true
|
|
||||||
|
|
||||||
- name: 🧪 Parse test reports
|
- name: 🧪 Parse test reports
|
||||||
run: ./tools/parse-reports.py
|
run: ./tools/parse-reports.py
|
||||||
if: ${{ failure() }}
|
if: ${{ failure() }}
|
||||||
|
|
||||||
- name: 📦 Prepare Jars
|
|
||||||
run: |
|
|
||||||
# Find the main jar and append the git hash onto it.
|
|
||||||
mkdir -p jars
|
|
||||||
find projects/forge/build/libs projects/fabric/build/libs -type f -regex '.*[0-9.]+\(-SNAPSHOT\)?\.jar$' -exec bash -c 'cp {} "jars/$(basename {} .jar)-$(git rev-parse HEAD).jar"' \;
|
|
||||||
|
|
||||||
- name: 📤 Upload Jar
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: CC-Tweaked
|
|
||||||
path: ./jars
|
|
||||||
|
|
||||||
- name: 📤 Upload coverage
|
|
||||||
uses: codecov/codecov-action@v3
|
|
||||||
|
|
||||||
build-core:
|
build-core:
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
@@ -81,24 +81,28 @@ jobs:
|
|||||||
runs-on: ${{ matrix.uses }}
|
runs-on: ${{ matrix.uses }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Clone repository
|
- name: 📥 Clone repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up Java
|
- name: 📥 Set up Java
|
||||||
uses: actions/setup-java@v3
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
java-version: 17
|
java-version: 21
|
||||||
distribution: 'temurin'
|
distribution: 'temurin'
|
||||||
|
|
||||||
- name: Setup Gradle
|
- name: 📥 Setup Gradle
|
||||||
uses: gradle/gradle-build-action@v2
|
uses: gradle/actions/setup-gradle@v3
|
||||||
with:
|
with:
|
||||||
cache-read-only: ${{ !startsWith(github.ref, 'refs/heads/mc-') }}
|
cache-read-only: ${{ !startsWith(github.ref, 'refs/heads/mc-') }}
|
||||||
|
|
||||||
- name: Run tests
|
- name: ⚒️ Build
|
||||||
|
run: |
|
||||||
|
./gradlew --configure-on-demand :core:assemble
|
||||||
|
|
||||||
|
- name: 🧪 Run tests
|
||||||
run: |
|
run: |
|
||||||
./gradlew --configure-on-demand :core:test
|
./gradlew --configure-on-demand :core:test
|
||||||
|
|
||||||
- name: Parse test reports
|
- name: 🧪 Parse test reports
|
||||||
run: python3 ./tools/parse-reports.py
|
run: python3 ./tools/parse-reports.py
|
||||||
if: ${{ failure() }}
|
if: ${{ failure() }}
|
||||||
|
19
.github/workflows/make-doc.sh
vendored
19
.github/workflows/make-doc.sh
vendored
@@ -1,19 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
DEST="${GITHUB_REF#refs/*/}"
|
|
||||||
echo "Uploading docs to https://tweaked.cc/$DEST"
|
|
||||||
|
|
||||||
# Setup ssh key
|
|
||||||
mkdir -p "$HOME/.ssh/"
|
|
||||||
echo "$SSH_KEY" > "$HOME/.ssh/key"
|
|
||||||
chmod 600 "$HOME/.ssh/key"
|
|
||||||
|
|
||||||
# And upload
|
|
||||||
rsync -avc -e "ssh -i $HOME/.ssh/key -o StrictHostKeyChecking=no -p $SSH_PORT" \
|
|
||||||
"$GITHUB_WORKSPACE/projects/web/build/site/" \
|
|
||||||
"$SSH_USER@$SSH_HOST:/$DEST"
|
|
||||||
rsync -avc -e "ssh -i $HOME/.ssh/key -o StrictHostKeyChecking=no -p $SSH_PORT" \
|
|
||||||
"$GITHUB_WORKSPACE/projects/common-api/build/docs/javadoc/" \
|
|
||||||
"$SSH_USER@$SSH_HOST:/$DEST/javadoc"
|
|
36
.github/workflows/make-doc.yml
vendored
36
.github/workflows/make-doc.yml
vendored
@@ -3,8 +3,7 @@ name: Build documentation
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- mc-1.19.x
|
- mc-*
|
||||||
- mc-1.20.x
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
make_doc:
|
make_doc:
|
||||||
@@ -12,30 +11,25 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Clone repository
|
- name: 📥 Clone repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up Java
|
- name: 📥 Set up Java
|
||||||
uses: actions/setup-java@v1
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
java-version: 17
|
java-version: 21
|
||||||
distribution: 'temurin'
|
distribution: 'temurin'
|
||||||
|
|
||||||
- name: Setup Gradle
|
- name: 📥 Setup Gradle
|
||||||
uses: gradle/gradle-build-action@v2
|
uses: gradle/actions/setup-gradle@v3
|
||||||
with:
|
with:
|
||||||
cache-read-only: ${{ !startsWith(github.ref, 'refs/heads/mc-') }}
|
cache-read-only: ${{ !startsWith(github.ref, 'refs/heads/mc-') }}
|
||||||
|
|
||||||
- name: Build with Gradle
|
- name: ⚒️ Generate documentation
|
||||||
run: ./gradlew compileJava --no-daemon || ./gradlew compileJava --no-daemon
|
run: ./gradlew docWebsite --no-daemon
|
||||||
|
|
||||||
- name: Generate documentation
|
- name: 📤 Upload Jar
|
||||||
run: ./gradlew docWebsite :common-api:javadoc --no-daemon
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
- name: Upload documentation
|
name: Documentation
|
||||||
run: .github/workflows/make-doc.sh 2> /dev/null
|
path: ./projects/web/build/site/
|
||||||
env:
|
|
||||||
SSH_KEY: ${{ secrets.SSH_KEY }}
|
|
||||||
SSH_USER: ${{ secrets.SSH_USER }}
|
|
||||||
SSH_HOST: ${{ secrets.SSH_HOST }}
|
|
||||||
SSH_PORT: ${{ secrets.SSH_PORT }}
|
|
||||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@@ -7,7 +7,9 @@
|
|||||||
/logs
|
/logs
|
||||||
/build
|
/build
|
||||||
/projects/*/logs
|
/projects/*/logs
|
||||||
|
/projects/fabric/fabricloader.log
|
||||||
/projects/*/build
|
/projects/*/build
|
||||||
|
/projects/*/src/test/generated_tests/
|
||||||
/buildSrc/build
|
/buildSrc/build
|
||||||
/out
|
/out
|
||||||
/buildSrc/out
|
/buildSrc/out
|
||||||
@@ -25,6 +27,7 @@
|
|||||||
*.iml
|
*.iml
|
||||||
.idea
|
.idea
|
||||||
.gradle
|
.gradle
|
||||||
|
.kotlin
|
||||||
*.DS_Store
|
*.DS_Store
|
||||||
|
|
||||||
/.classpath
|
/.classpath
|
||||||
|
26
.gitpod.yml
26
.gitpod.yml
@@ -1,26 +0,0 @@
|
|||||||
# SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
|
||||||
#
|
|
||||||
# SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
image:
|
|
||||||
file: config/gitpod/Dockerfile
|
|
||||||
|
|
||||||
ports:
|
|
||||||
- port: 25565
|
|
||||||
onOpen: notify
|
|
||||||
|
|
||||||
vscode:
|
|
||||||
extensions:
|
|
||||||
- eamodio.gitlens
|
|
||||||
- github.vscode-pull-request-github
|
|
||||||
- ms-azuretools.vscode-docker
|
|
||||||
- redhat.java
|
|
||||||
- richardwillis.vscode-gradle
|
|
||||||
- vscjava.vscode-java-debug
|
|
||||||
- vscode.github
|
|
||||||
|
|
||||||
tasks:
|
|
||||||
- name: Setup pre-commit hool
|
|
||||||
init: pre-commit install --allow-missing-config
|
|
||||||
- name: Install npm packages
|
|
||||||
init: npm ci
|
|
@@ -6,7 +6,7 @@
|
|||||||
# See https://pre-commit.com/hooks.html for more hooks
|
# See https://pre-commit.com/hooks.html for more hooks
|
||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
rev: v4.4.0
|
rev: v5.0.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: trailing-whitespace
|
- id: trailing-whitespace
|
||||||
- id: end-of-file-fixer
|
- id: end-of-file-fixer
|
||||||
@@ -27,7 +27,7 @@ repos:
|
|||||||
exclude: "^(.*\\.(bat)|LICENSE)$"
|
exclude: "^(.*\\.(bat)|LICENSE)$"
|
||||||
|
|
||||||
- repo: https://github.com/fsfe/reuse-tool
|
- repo: https://github.com/fsfe/reuse-tool
|
||||||
rev: v2.1.0
|
rev: v5.0.2
|
||||||
hooks:
|
hooks:
|
||||||
- id: reuse
|
- id: reuse
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ repos:
|
|||||||
name: Check Java codestyle
|
name: Check Java codestyle
|
||||||
files: ".*\\.java$"
|
files: ".*\\.java$"
|
||||||
language: system
|
language: system
|
||||||
entry: ./gradlew checkstyleMain checkstyleTest
|
entry: ./gradlew checkstyle
|
||||||
pass_filenames: false
|
pass_filenames: false
|
||||||
require_serial: true
|
require_serial: true
|
||||||
- id: illuaminate
|
- id: illuaminate
|
||||||
@@ -58,6 +58,7 @@ repos:
|
|||||||
exclude: |
|
exclude: |
|
||||||
(?x)^(
|
(?x)^(
|
||||||
projects/[a-z]+/src/generated|
|
projects/[a-z]+/src/generated|
|
||||||
|
projects/[a-z]+/src/examples/generatedResources|
|
||||||
projects/core/src/test/resources/test-rom/data/json-parsing/|
|
projects/core/src/test/resources/test-rom/data/json-parsing/|
|
||||||
.*\.dfpwm
|
.*\.dfpwm
|
||||||
)
|
)
|
||||||
|
87
.reuse/dep5
87
.reuse/dep5
@@ -1,87 +0,0 @@
|
|||||||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
|
||||||
Source: https://github.com/cc-tweaked/cc-tweaked
|
|
||||||
Upstream-Name: CC: Tweaked
|
|
||||||
Upstream-Contact: Jonathan Coates <git@squiddev.cc>
|
|
||||||
|
|
||||||
Files:
|
|
||||||
projects/common/src/main/resources/assets/computercraft/sounds.json
|
|
||||||
projects/common/src/main/resources/assets/computercraft/sounds/empty.ogg
|
|
||||||
projects/common/src/testMod/resources/data/cctest/computercraft/turtle_upgrades/*
|
|
||||||
projects/common/src/testMod/resources/data/cctest/structures/*
|
|
||||||
projects/fabric/src/generated/*
|
|
||||||
projects/forge/src/generated/*
|
|
||||||
projects/web/src/export/index.json
|
|
||||||
projects/web/src/export/items/minecraft/*
|
|
||||||
Comment: Generated/data files are CC0.
|
|
||||||
Copyright: The CC: Tweaked Developers
|
|
||||||
License: CC0-1.0
|
|
||||||
|
|
||||||
Files:
|
|
||||||
doc/images/*
|
|
||||||
package.json
|
|
||||||
package-lock.json
|
|
||||||
projects/common/src/client/resources/computercraft-client.mixins.json
|
|
||||||
projects/common/src/main/resources/assets/minecraft/shaders/core/computercraft/monitor_tbo.json
|
|
||||||
projects/common/src/main/resources/computercraft.mixins.json
|
|
||||||
projects/common/src/testMod/resources/computercraft-gametest.mixins.json
|
|
||||||
projects/common/src/testMod/resources/data/computercraft/loot_tables/treasure_disk.json
|
|
||||||
projects/common/src/testMod/resources/pack.mcmeta
|
|
||||||
projects/core/src/main/resources/data/computercraft/lua/rom/modules/command/.ignoreme
|
|
||||||
projects/core/src/main/resources/data/computercraft/lua/rom/modules/main/.ignoreme
|
|
||||||
projects/core/src/main/resources/data/computercraft/lua/rom/modules/turtle/.ignoreme
|
|
||||||
projects/core/src/main/resources/data/computercraft/lua/rom/motd.txt
|
|
||||||
projects/fabric-api/src/main/modJson/fabric.mod.json
|
|
||||||
projects/fabric/src/client/resources/computercraft-client.fabric.mixins.json
|
|
||||||
projects/fabric/src/main/resources/computercraft.fabric.mixins.json
|
|
||||||
projects/fabric/src/main/resources/fabric.mod.json
|
|
||||||
projects/fabric/src/testMod/resources/computercraft-gametest.fabric.mixins.json
|
|
||||||
projects/fabric/src/testMod/resources/fabric.mod.json
|
|
||||||
projects/forge/src/client/resources/computercraft-client.forge.mixins.json
|
|
||||||
projects/web/src/mount/.settings
|
|
||||||
projects/web/src/mount/example.nfp
|
|
||||||
projects/web/src/mount/example.nft
|
|
||||||
projects/web/src/mount/expr_template.lua
|
|
||||||
projects/web/tsconfig.json
|
|
||||||
Comment: Several assets where it's inconvenient to create a .license file.
|
|
||||||
Copyright: The CC: Tweaked Developers
|
|
||||||
License: MPL-2.0
|
|
||||||
|
|
||||||
Files:
|
|
||||||
doc/logo.png
|
|
||||||
doc/logo-darkmode.png
|
|
||||||
projects/common/src/main/resources/assets/computercraft/models/*
|
|
||||||
projects/common/src/main/resources/assets/computercraft/textures/*
|
|
||||||
projects/common/src/main/resources/pack.mcmeta
|
|
||||||
projects/common/src/main/resources/pack.png
|
|
||||||
projects/core/src/main/resources/data/computercraft/lua/rom/autorun/.ignoreme
|
|
||||||
projects/core/src/main/resources/data/computercraft/lua/rom/help/*
|
|
||||||
projects/core/src/main/resources/data/computercraft/lua/rom/programs/fun/advanced/levels/*
|
|
||||||
projects/web/src/export/items/computercraft/*
|
|
||||||
Comment: Bulk-license original assets as CCPL.
|
|
||||||
Copyright: 2011 Daniel Ratcliffe
|
|
||||||
License: LicenseRef-CCPL
|
|
||||||
|
|
||||||
Files:
|
|
||||||
projects/common/src/main/resources/assets/computercraft/lang/*
|
|
||||||
Comment: Community-contributed license files
|
|
||||||
Copyright: 2017 The CC: Tweaked Developers
|
|
||||||
License: LicenseRef-CCPL
|
|
||||||
|
|
||||||
Files:
|
|
||||||
.github/*
|
|
||||||
Comment:
|
|
||||||
GitHub build scripts are CC0. While we could add a header to each file,
|
|
||||||
it's unclear if it will break actions or issue templates in some way.
|
|
||||||
Copyright: Jonathan Coates <git@squiddev.cc>
|
|
||||||
License: CC0-1.0
|
|
||||||
|
|
||||||
Files:
|
|
||||||
gradle/wrapper/*
|
|
||||||
gradlew
|
|
||||||
gradlew.bat
|
|
||||||
Copyright: Gradle Inc
|
|
||||||
License: Apache-2.0
|
|
||||||
|
|
||||||
Files: projects/core/src/test/resources/test-rom/data/json-parsing/*
|
|
||||||
Copyright: 2016 Nicolas Seriot
|
|
||||||
License: MIT
|
|
@@ -22,16 +22,15 @@ If you have a bug, suggestion, or other feedback, the best thing to do is [file
|
|||||||
use the issue templates - they provide a useful hint on what information to provide.
|
use the issue templates - they provide a useful hint on what information to provide.
|
||||||
|
|
||||||
## Translations
|
## Translations
|
||||||
Translations are managed through [Weblate], an online interface for managing language strings. This is synced
|
Translations are managed through [CrowdIn], an online interface for managing language strings.
|
||||||
automatically with GitHub, so please don't submit PRs adding/changing translations!
|
|
||||||
|
|
||||||
## Setting up a development environment
|
## Setting up a development environment
|
||||||
In order to develop CC: Tweaked, you'll need to download the source code and then run it.
|
In order to develop CC: Tweaked, you'll need to download the source code and then run it.
|
||||||
|
|
||||||
- Make sure you've got the following software installed:
|
- Make sure you've got the following software installed:
|
||||||
- Java Development Kit (JDK) installed. This can be downloaded from [Adoptium].
|
- Java Development Kit 21 (JDK). This can be downloaded from [Adoptium].
|
||||||
- [Git](https://git-scm.com/).
|
- [Git](https://git-scm.com/).
|
||||||
- If you want to work on documentation, [NodeJS][node].
|
- [NodeJS 20 or later][node].
|
||||||
|
|
||||||
- Download CC: Tweaked's source code:
|
- Download CC: Tweaked's source code:
|
||||||
```
|
```
|
||||||
@@ -49,9 +48,12 @@ If you want to run CC:T in a normal Minecraft instance, run `./gradlew assemble`
|
|||||||
`projects/forge/build/libs` (for Forge) or `projects/fabric/build/libs` (for Fabric).
|
`projects/forge/build/libs` (for Forge) or `projects/fabric/build/libs` (for Fabric).
|
||||||
|
|
||||||
## Developing CC: Tweaked
|
## Developing CC: Tweaked
|
||||||
Before making any major changes to CC: Tweaked, I'd recommend you have a read of the [the architecture
|
Before making any major changes to CC: Tweaked, I'd recommend starting opening an issue or starting a discussion on
|
||||||
document][architecture] first. While it's not a comprehensive document, it gives a good hint of where you should start
|
GitHub first. It's often helpful to discuss features before spending time developing them!
|
||||||
looking to make your changes. As always, if you're not sure, [do ask the community][community]!
|
|
||||||
|
Once you're ready to start programming, have a read of the [the architecture document][architecture] first. While it's
|
||||||
|
not a comprehensive document, it gives a good hint of where you should start looking to make your changes. As always, if
|
||||||
|
you're not sure, [do ask the community][community]!
|
||||||
|
|
||||||
### Testing
|
### Testing
|
||||||
When making larger changes, it may be useful to write a test to make sure your code works as expected.
|
When making larger changes, it may be useful to write a test to make sure your code works as expected.
|
||||||
@@ -86,8 +88,8 @@ You'll first need to [set up a development environment as above](#setting-up-a-d
|
|||||||
|
|
||||||
Once this is set up, you can now run `./gradlew docWebsite`. This generates documentation from our Lua and Java code,
|
Once this is set up, you can now run `./gradlew docWebsite`. This generates documentation from our Lua and Java code,
|
||||||
writing the resulting HTML into `./projects/web/build/site`, which can then be opened in a browser. When iterating on
|
writing the resulting HTML into `./projects/web/build/site`, which can then be opened in a browser. When iterating on
|
||||||
documentation, you can instead run `./gradlew docWebsite -t`, which will rebuild documentation every time you change a
|
documentation, you can instead run `./gradlew :web:assemble -x :web:compileTeaVM -t`, which will rebuild documentation
|
||||||
file.
|
every time you change a file.
|
||||||
|
|
||||||
Documentation is built using [illuaminate] which, while not currently documented (somewhat ironic), is largely the same
|
Documentation is built using [illuaminate] which, while not currently documented (somewhat ironic), is largely the same
|
||||||
as [ldoc][ldoc]. Documentation comments are written in Markdown, though note that we do not support many GitHub-specific
|
as [ldoc][ldoc]. Documentation comments are written in Markdown, though note that we do not support many GitHub-specific
|
||||||
@@ -100,12 +102,11 @@ about how you can build on that until you've covered everything!
|
|||||||
[new-issue]: https://github.com/cc-tweaked/CC-Tweaked/issues/new/choose "Create a new issue"
|
[new-issue]: https://github.com/cc-tweaked/CC-Tweaked/issues/new/choose "Create a new issue"
|
||||||
[community]: README.md#community "Get in touch with the community."
|
[community]: README.md#community "Get in touch with the community."
|
||||||
[Adoptium]: https://adoptium.net/temurin/releases?version=17 "Download OpenJDK 17"
|
[Adoptium]: https://adoptium.net/temurin/releases?version=17 "Download OpenJDK 17"
|
||||||
[checkstyle]: https://checkstyle.org/
|
|
||||||
[illuaminate]: https://github.com/SquidDev/illuaminate/ "Illuaminate on GitHub"
|
[illuaminate]: https://github.com/SquidDev/illuaminate/ "Illuaminate on GitHub"
|
||||||
[weblate]: https://i18n.tweaked.cc/projects/cc-tweaked/minecraft/ "CC: Tweaked weblate instance"
|
|
||||||
[docs]: https://tweaked.cc/ "CC: Tweaked documentation"
|
[docs]: https://tweaked.cc/ "CC: Tweaked documentation"
|
||||||
[ldoc]: http://stevedonovan.github.io/ldoc/ "ldoc, a Lua documentation generator."
|
[ldoc]: http://stevedonovan.github.io/ldoc/ "ldoc, a Lua documentation generator."
|
||||||
[mc-test]: https://www.youtube.com/watch?v=vXaWOJTCYNg
|
[mc-test]: https://www.youtube.com/watch?v=vXaWOJTCYNg
|
||||||
[busted]: https://github.com/Olivine-Labs/busted "busted: Elegant Lua unit testing."
|
[busted]: https://github.com/Olivine-Labs/busted "busted: Elegant Lua unit testing."
|
||||||
[node]: https://nodejs.org/en/ "Node.js"
|
[node]: https://nodejs.org/en/ "Node.js"
|
||||||
[architecture]: projects/ARCHITECTURE.md
|
[architecture]: projects/ARCHITECTURE.md
|
||||||
|
[Crowdin]: https://crowdin.com/project/cc-tweaked/
|
||||||
|
38
README.md
38
README.md
@@ -11,14 +11,13 @@ SPDX-License-Identifier: MPL-2.0
|
|||||||
</picture>
|
</picture>
|
||||||
|
|
||||||
[](https://github.com/cc-tweaked/CC-Tweaked/actions "Current build status")
|
[](https://github.com/cc-tweaked/CC-Tweaked/actions "Current build status")
|
||||||
[][CurseForge]
|
|
||||||
[][Modrinth]
|
[][Modrinth]
|
||||||
|
|
||||||
CC: Tweaked is a mod for Minecraft which adds programmable computers, turtles and more to the game. A fork of the
|
CC: Tweaked is a mod for Minecraft which adds programmable computers, turtles and more to the game. A fork of the
|
||||||
much-beloved [ComputerCraft], it continues its legacy with improved performance and stability, along with a wealth of
|
much-beloved [ComputerCraft], it continues its legacy with improved performance and stability, along with a wealth of
|
||||||
new features.
|
new features.
|
||||||
|
|
||||||
CC: Tweaked can be installed from [CurseForge] or [Modrinth]. It runs on both [Minecraft Forge] and [Fabric].
|
CC: Tweaked can be installed from [Modrinth]. It runs on both [Minecraft Forge] and [Fabric].
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
Any contribution is welcome, be that using the mod, reporting bugs or contributing code. If you want to get started
|
Any contribution is welcome, be that using the mod, reporting bugs or contributing code. If you want to get started
|
||||||
@@ -26,8 +25,9 @@ developing the mod, [check out the instructions here](CONTRIBUTING.md#developing
|
|||||||
|
|
||||||
## Community
|
## Community
|
||||||
If you need help getting started with CC: Tweaked, want to show off your latest project, or just want to chat about
|
If you need help getting started with CC: Tweaked, want to show off your latest project, or just want to chat about
|
||||||
ComputerCraft, do check out our [forum] and [GitHub discussions page][GitHub discussions]! There's also a fairly
|
ComputerCraft, do check out our [GitHub discussions page][GitHub discussions]! There's also a fairly populated,
|
||||||
populated, albeit quiet [IRC channel][irc], if that's more your cup of tea.
|
albeit quiet IRC channel on [EsperNet], if that's more your cup of tea. You can join `#computercraft` through your
|
||||||
|
desktop client, or online using [KiwiIRC].
|
||||||
|
|
||||||
We also host fairly comprehensive documentation at [tweaked.cc](https://tweaked.cc/ "The CC: Tweaked website").
|
We also host fairly comprehensive documentation at [tweaked.cc](https://tweaked.cc/ "The CC: Tweaked website").
|
||||||
|
|
||||||
@@ -39,10 +39,9 @@ on is present.
|
|||||||
```groovy
|
```groovy
|
||||||
repositories {
|
repositories {
|
||||||
maven {
|
maven {
|
||||||
url "https://squiddev.cc/maven/"
|
url "https://maven.squiddev.cc"
|
||||||
content {
|
content {
|
||||||
includeGroup("cc.tweaked")
|
includeGroup("cc.tweaked")
|
||||||
includeModule("org.squiddev", "Cobalt")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -52,9 +51,8 @@ dependencies {
|
|||||||
compileOnly("cc.tweaked:cc-tweaked-$mcVersion-common-api:$cctVersion")
|
compileOnly("cc.tweaked:cc-tweaked-$mcVersion-common-api:$cctVersion")
|
||||||
|
|
||||||
// Forge Gradle
|
// Forge Gradle
|
||||||
compileOnly("cc.tweaked:cc-tweaked-$mcVersion-core-api:$cctVersion")
|
compileOnly("cc.tweaked:cc-tweaked-$mcVersion-forge-api:$cctVersion")
|
||||||
compileOnly(fg.deobf("cc.tweaked:cc-tweaked-$mcVersion-forge-api:$cctVersion"))
|
runtimeOnly("cc.tweaked:cc-tweaked-$mcVersion-forge:$cctVersion")
|
||||||
runtimeOnly(fg.deobf("cc.tweaked:cc-tweaked-$mcVersion-forge:$cctVersion"))
|
|
||||||
|
|
||||||
// Fabric Loom
|
// Fabric Loom
|
||||||
modCompileOnly("cc.tweaked:cc-tweaked-$mcVersion-fabric-api:$cctVersion")
|
modCompileOnly("cc.tweaked:cc-tweaked-$mcVersion-fabric-api:$cctVersion")
|
||||||
@@ -62,31 +60,17 @@ dependencies {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
When using ForgeGradle, you may also need to add the following:
|
|
||||||
|
|
||||||
```groovy
|
|
||||||
minecraft {
|
|
||||||
runs {
|
|
||||||
configureEach {
|
|
||||||
property 'mixin.env.remapRefMap', 'true'
|
|
||||||
property 'mixin.env.refMapRemappingFile', "${buildDir}/createSrgToMcp/output.srg"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
You should also be careful to only use classes within the `dan200.computercraft.api` package. Non-API classes are
|
You should also be careful to only use classes within the `dan200.computercraft.api` package. Non-API classes are
|
||||||
subject to change at any point. If you depend on functionality outside the API, file an issue, and we can look into
|
subject to change at any point. If you depend on functionality outside the API (or need to mixin to CC:T), please file
|
||||||
exposing more features.
|
an issue to let me know!
|
||||||
|
|
||||||
We bundle the API sources with the jar, so documentation should be easily viewable within your editor. Alternatively,
|
We bundle the API sources with the jar, so documentation should be easily viewable within your editor. Alternatively,
|
||||||
the generated documentation [can be browsed online](https://tweaked.cc/javadoc/).
|
the generated documentation [can be browsed online](https://tweaked.cc/javadoc/).
|
||||||
|
|
||||||
[computercraft]: https://github.com/dan200/ComputerCraft "ComputerCraft on GitHub"
|
[computercraft]: https://github.com/dan200/ComputerCraft "ComputerCraft on GitHub"
|
||||||
[curseforge]: https://minecraft.curseforge.com/projects/cc-tweaked "Download CC: Tweaked from CurseForge"
|
|
||||||
[modrinth]: https://modrinth.com/mod/gu7yAYhd "Download CC: Tweaked from Modrinth"
|
[modrinth]: https://modrinth.com/mod/gu7yAYhd "Download CC: Tweaked from Modrinth"
|
||||||
[Minecraft Forge]: https://files.minecraftforge.net/ "Download Minecraft Forge."
|
[Minecraft Forge]: https://files.minecraftforge.net/ "Download Minecraft Forge."
|
||||||
[Fabric]: https://fabricmc.net/use/installer/ "Download Fabric."
|
[Fabric]: https://fabricmc.net/use/installer/ "Download Fabric."
|
||||||
[forum]: https://forums.computercraft.cc/
|
|
||||||
[GitHub Discussions]: https://github.com/cc-tweaked/CC-Tweaked/discussions
|
[GitHub Discussions]: https://github.com/cc-tweaked/CC-Tweaked/discussions
|
||||||
[IRC]: https://webchat.esper.net/?channels=computercraft "#computercraft on EsperNet"
|
[EsperNet]: https://www.esper.net/
|
||||||
|
[KiwiIRC]: https://kiwiirc.com/nextclient/#irc://irc.esper.net:+6697/#computercraft "#computercraft on EsperNet"
|
||||||
|
100
REUSE.toml
Normal file
100
REUSE.toml
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2017 The CC: Tweaked Developers
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
version = 1
|
||||||
|
SPDX-PackageName = "CC: Tweaked"
|
||||||
|
SPDX-PackageSupplier = "Jonathan Coates <git@squiddev.cc>"
|
||||||
|
SPDX-PackageDownloadLocation = "https://github.com/cc-tweaked/cc-tweaked"
|
||||||
|
|
||||||
|
[[annotations]]
|
||||||
|
SPDX-FileCopyrightText = "The CC: Tweaked Developers"
|
||||||
|
SPDX-License-Identifier = "CC0-1.0"
|
||||||
|
path = [
|
||||||
|
# Generated/data files are CC0.
|
||||||
|
"gradle/gradle-daemon-jvm.properties",
|
||||||
|
"projects/common/src/main/resources/assets/computercraft/sounds.json",
|
||||||
|
"projects/common/src/main/resources/assets/computercraft/sounds/empty.ogg",
|
||||||
|
"projects/common/src/testMod/resources/data/cctest/computercraft/turtle_upgrade/**",
|
||||||
|
"projects/common/src/testMod/resources/data/cctest/structures/**",
|
||||||
|
"projects/*/src/generated/**",
|
||||||
|
"projects/web/src/htmlTransform/export/index.json",
|
||||||
|
"projects/web/src/htmlTransform/export/items/minecraft/**",
|
||||||
|
# GitHub build scripts are CC0. While we could add a header to each file,
|
||||||
|
# it's unclear if it will break actions or issue templates in some way.
|
||||||
|
".github/**",
|
||||||
|
# Example mod is CC0.
|
||||||
|
"projects/*/src/examples/**"
|
||||||
|
]
|
||||||
|
|
||||||
|
[[annotations]]
|
||||||
|
# Several assets where it's inconvenient to create a .license file.
|
||||||
|
SPDX-FileCopyrightText = "The CC: Tweaked Developers"
|
||||||
|
SPDX-License-Identifier = "MPL-2.0"
|
||||||
|
path = [
|
||||||
|
"doc/images/**",
|
||||||
|
"package.json",
|
||||||
|
"package-lock.json",
|
||||||
|
"projects/*/src/*/resources/*.mixins.json",
|
||||||
|
"projects/fabric/src/*/resources/fabric.mod.json",
|
||||||
|
"projects/common/src/main/resources/assets/minecraft/shaders/core/computercraft/monitor_tbo.json",
|
||||||
|
"projects/common/src/testMod/resources/data/computercraft/loot_tables/treasure_disk.json",
|
||||||
|
"projects/common/src/testMod/resources/pack.mcmeta",
|
||||||
|
"projects/core/src/main/resources/data/computercraft/lua/rom/modules/command/.ignoreme",
|
||||||
|
"projects/core/src/main/resources/data/computercraft/lua/rom/modules/main/.ignoreme",
|
||||||
|
"projects/core/src/main/resources/data/computercraft/lua/rom/modules/turtle/.ignoreme",
|
||||||
|
"projects/core/src/main/resources/data/computercraft/lua/rom/motd.txt",
|
||||||
|
"projects/web/src/frontend/mount/.settings",
|
||||||
|
"projects/web/src/frontend/mount/example.nfp",
|
||||||
|
"projects/web/src/frontend/mount/example.nft",
|
||||||
|
"projects/web/src/frontend/mount/expr_template.lua",
|
||||||
|
"projects/web/tsconfig.json",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[annotations]]
|
||||||
|
# Bulk-license original assets as CCPL.
|
||||||
|
SPDX-FileCopyrightText = "2011 Daniel Ratcliffe"
|
||||||
|
SPDX-License-Identifier = "LicenseRef-CCPL"
|
||||||
|
path = [
|
||||||
|
"doc/logo.png",
|
||||||
|
"doc/logo-darkmode.png",
|
||||||
|
"projects/common/src/main/resources/assets/computercraft/models/**",
|
||||||
|
"projects/common/src/main/resources/assets/computercraft/textures/**",
|
||||||
|
"projects/common/src/main/resources/pack.mcmeta",
|
||||||
|
"projects/common/src/main/resources/pack.png",
|
||||||
|
"projects/core/src/main/resources/assets/computercraft/textures/gui/term_font.png",
|
||||||
|
"projects/core/src/main/resources/data/computercraft/lua/rom/autorun/.ignoreme",
|
||||||
|
"projects/core/src/main/resources/data/computercraft/lua/rom/help/**",
|
||||||
|
"projects/core/src/main/resources/data/computercraft/lua/rom/programs/fun/advanced/levels/**",
|
||||||
|
"projects/web/src/htmlTransform/export/items/computercraft/**",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[annotations]]
|
||||||
|
# Community-contributed language files
|
||||||
|
SPDX-FileCopyrightText = "2017 The CC: Tweaked Developers"
|
||||||
|
SPDX-License-Identifier = "LicenseRef-CCPL"
|
||||||
|
path = [
|
||||||
|
"projects/common/src/main/resources/assets/computercraft/lang/cs_cz.json",
|
||||||
|
"projects/common/src/main/resources/assets/computercraft/lang/ko_kr.json",
|
||||||
|
"projects/common/src/main/resources/assets/computercraft/lang/pl_pl.json",
|
||||||
|
"projects/common/src/main/resources/assets/computercraft/lang/pt_br.json",
|
||||||
|
"projects/common/src/main/resources/assets/computercraft/lang/ru_ru.json",
|
||||||
|
"projects/common/src/main/resources/assets/computercraft/lang/uk_ua.json",
|
||||||
|
"projects/common/src/main/resources/assets/computercraft/lang/zh_cn.json",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[annotations]]
|
||||||
|
# Community-contributed language files
|
||||||
|
SPDX-FileCopyrightText = "2017 The CC: Tweaked Developers"
|
||||||
|
SPDX-License-Identifier = "MPL-2.0"
|
||||||
|
path = "projects/common/src/main/resources/assets/computercraft/lang/**"
|
||||||
|
|
||||||
|
[[annotations]]
|
||||||
|
path = ["gradle/wrapper/**"]
|
||||||
|
SPDX-FileCopyrightText = "Gradle Inc"
|
||||||
|
SPDX-License-Identifier = "Apache-2.0"
|
||||||
|
|
||||||
|
[[annotations]]
|
||||||
|
path = "projects/core/src/test/resources/test-rom/data/json-parsing/**"
|
||||||
|
SPDX-FileCopyrightText = "2016 Nicolas Seriot"
|
||||||
|
SPDX-License-Identifier = "MIT"
|
@@ -2,13 +2,18 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
import org.jetbrains.gradle.ext.compiler
|
import cc.tweaked.gradle.JUnitExt
|
||||||
import org.jetbrains.gradle.ext.settings
|
import net.fabricmc.loom.api.LoomGradleExtensionAPI
|
||||||
|
import net.fabricmc.loom.util.gradle.SourceSetHelper
|
||||||
|
import org.jetbrains.gradle.ext.*
|
||||||
|
import org.jetbrains.gradle.ext.Application
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
publishing
|
publishing
|
||||||
alias(libs.plugins.taskTree)
|
alias(libs.plugins.taskTree)
|
||||||
alias(libs.plugins.githubRelease)
|
alias(libs.plugins.githubRelease)
|
||||||
|
alias(libs.plugins.gradleVersions)
|
||||||
|
alias(libs.plugins.versionCatalogUpdate)
|
||||||
id("org.jetbrains.gradle.plugin.idea-ext")
|
id("org.jetbrains.gradle.plugin.idea-ext")
|
||||||
id("cc-tweaked")
|
id("cc-tweaked")
|
||||||
}
|
}
|
||||||
@@ -19,25 +24,80 @@ val mcVersion: String by extra
|
|||||||
|
|
||||||
githubRelease {
|
githubRelease {
|
||||||
token(findProperty("githubApiKey") as String? ?: "")
|
token(findProperty("githubApiKey") as String? ?: "")
|
||||||
owner.set("cc-tweaked")
|
owner = "cc-tweaked"
|
||||||
repo.set("CC-Tweaked")
|
repo = "CC-Tweaked"
|
||||||
targetCommitish.set(cct.gitBranch)
|
targetCommitish = cct.gitBranch
|
||||||
|
|
||||||
tagName.set("v$mcVersion-$modVersion")
|
tagName = "v$mcVersion-$modVersion"
|
||||||
releaseName.set("[$mcVersion] $modVersion")
|
releaseName = "[$mcVersion] $modVersion"
|
||||||
body.set(
|
body = provider {
|
||||||
provider {
|
"## " + project(":core").file("src/main/resources/data/computercraft/lua/rom/help/whatsnew.md")
|
||||||
"## " + project(":core").file("src/main/resources/data/computercraft/lua/rom/help/whatsnew.md")
|
.readLines()
|
||||||
.readLines()
|
.takeWhile { it != "Type \"help changelog\" to see the full version history." }
|
||||||
.takeWhile { it != "Type \"help changelog\" to see the full version history." }
|
.joinToString("\n").trim()
|
||||||
.joinToString("\n").trim()
|
}
|
||||||
},
|
prerelease = isUnstable
|
||||||
)
|
|
||||||
prerelease.set(isUnstable)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.publish { dependsOn(tasks.githubRelease) }
|
tasks.publish { dependsOn(tasks.githubRelease) }
|
||||||
|
|
||||||
|
idea.project.settings.runConfigurations {
|
||||||
|
register<JUnitExt>("Core Tests") {
|
||||||
|
vmParameters = "-ea"
|
||||||
|
moduleName = "${idea.project.name}.core.test"
|
||||||
|
packageName = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
register<JUnitExt>("CraftOS Tests") {
|
||||||
|
vmParameters = "-ea"
|
||||||
|
moduleName = "${idea.project.name}.core.test"
|
||||||
|
className = "dan200.computercraft.core.ComputerTestDelegate"
|
||||||
|
}
|
||||||
|
|
||||||
|
register<JUnitExt>("CraftOS Tests (Fast)") {
|
||||||
|
vmParameters = "-ea -Dcc.skip_keywords=slow"
|
||||||
|
moduleName = "${idea.project.name}.core.test"
|
||||||
|
className = "dan200.computercraft.core.ComputerTestDelegate"
|
||||||
|
}
|
||||||
|
|
||||||
|
register<JUnitExt>("Common Tests") {
|
||||||
|
vmParameters = "-ea"
|
||||||
|
moduleName = "${idea.project.name}.common.test"
|
||||||
|
packageName = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
register<JUnitExt>("Fabric Tests") {
|
||||||
|
val fabricProject = evaluationDependsOn(":fabric")
|
||||||
|
val classPathGroup = fabricProject.extensions.getByType<LoomGradleExtensionAPI>().mods
|
||||||
|
.joinToString(File.pathSeparator + File.pathSeparator) { modSettings ->
|
||||||
|
SourceSetHelper.getClasspath(modSettings, project).joinToString(File.pathSeparator) { it.absolutePath }
|
||||||
|
}
|
||||||
|
|
||||||
|
vmParameters = "-ea -Dfabric.classPathGroups=$classPathGroup"
|
||||||
|
moduleName = "${idea.project.name}.fabric.test"
|
||||||
|
packageName = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
register<JUnitExt>("Forge Tests") {
|
||||||
|
vmParameters = "-ea"
|
||||||
|
moduleName = "${idea.project.name}.forge.test"
|
||||||
|
packageName = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
register<Application>("Standalone") {
|
||||||
|
moduleName = "${idea.project.name}.standalone.main"
|
||||||
|
mainClass = "cc.tweaked.standalone.Main"
|
||||||
|
programParameters = "--resources=projects/core/src/main/resources --term=80x30 --allow-local-domains"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build with the IntelliJ, rather than through Gradle. This may require setting the "Compiler Output" option in
|
||||||
|
// "Project Structure".
|
||||||
|
idea.project.settings.delegateActions {
|
||||||
|
delegateBuildRunToGradle = false
|
||||||
|
testRunner = ActionDelegationConfig.TestRunner.PLATFORM
|
||||||
|
}
|
||||||
|
|
||||||
idea.project.settings.compiler.javac {
|
idea.project.settings.compiler.javac {
|
||||||
// We want ErrorProne to be present when compiling via IntelliJ, as it offers some helpful warnings
|
// We want ErrorProne to be present when compiling via IntelliJ, as it offers some helpful warnings
|
||||||
// and errors. Loop through our source sets and find the appropriate flags.
|
// and errors. Loop through our source sets and find the appropriate flags.
|
||||||
@@ -54,3 +114,9 @@ idea.project.settings.compiler.javac {
|
|||||||
}
|
}
|
||||||
.toMap()
|
.toMap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
versionCatalogUpdate {
|
||||||
|
sortByKey = false
|
||||||
|
pin { versions.addAll("fastutil", "guava", "netty", "slf4j") }
|
||||||
|
keep { keepUnusedLibraries = true }
|
||||||
|
}
|
||||||
|
@@ -5,6 +5,8 @@
|
|||||||
plugins {
|
plugins {
|
||||||
`java-gradle-plugin`
|
`java-gradle-plugin`
|
||||||
`kotlin-dsl`
|
`kotlin-dsl`
|
||||||
|
alias(libs.plugins.gradleVersions)
|
||||||
|
alias(libs.plugins.versionCatalogUpdate)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Duplicated in settings.gradle.kts
|
// Duplicated in settings.gradle.kts
|
||||||
@@ -12,25 +14,10 @@ repositories {
|
|||||||
mavenCentral()
|
mavenCentral()
|
||||||
gradlePluginPortal()
|
gradlePluginPortal()
|
||||||
|
|
||||||
maven("https://maven.minecraftforge.net") {
|
maven("https://maven.neoforged.net") {
|
||||||
name = "Forge"
|
name = "NeoForge"
|
||||||
content {
|
content {
|
||||||
includeGroup("net.minecraftforge")
|
includeGroup("net.neoforged")
|
||||||
includeGroup("net.minecraftforge.gradle")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
maven("https://maven.parchmentmc.org") {
|
|
||||||
name = "Librarian"
|
|
||||||
content {
|
|
||||||
includeGroupByRegex("^org\\.parchmentmc.*")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
maven("https://repo.spongepowered.org/repository/maven-public/") {
|
|
||||||
name = "Sponge"
|
|
||||||
content {
|
|
||||||
includeGroup("org.spongepowered")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,6 +27,13 @@ repositories {
|
|||||||
includeGroup("net.fabricmc")
|
includeGroup("net.fabricmc")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
maven("https://maven.squiddev.cc") {
|
||||||
|
name = "SquidDev"
|
||||||
|
content {
|
||||||
|
includeGroup("cc.tweaked.vanilla-extract")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
@@ -47,13 +41,11 @@ dependencies {
|
|||||||
implementation(libs.kotlin.plugin)
|
implementation(libs.kotlin.plugin)
|
||||||
implementation(libs.spotless)
|
implementation(libs.spotless)
|
||||||
|
|
||||||
implementation(libs.curseForgeGradle)
|
|
||||||
implementation(libs.fabric.loom)
|
implementation(libs.fabric.loom)
|
||||||
implementation(libs.forgeGradle)
|
implementation(libs.ideaExt)
|
||||||
implementation(libs.librarian)
|
|
||||||
implementation(libs.minotaur)
|
implementation(libs.minotaur)
|
||||||
implementation(libs.vineflower)
|
implementation(libs.modDevGradle)
|
||||||
implementation(libs.vanillaGradle)
|
implementation(libs.vanillaExtract)
|
||||||
}
|
}
|
||||||
|
|
||||||
gradlePlugin {
|
gradlePlugin {
|
||||||
@@ -74,3 +66,9 @@ gradlePlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
versionCatalogUpdate {
|
||||||
|
sortByKey = false
|
||||||
|
keep { keepUnusedLibraries = true }
|
||||||
|
catalogFile = file("../gradle/libs.versions.toml")
|
||||||
|
}
|
||||||
|
@@ -12,7 +12,6 @@ import cc.tweaked.gradle.MinecraftConfigurations
|
|||||||
plugins {
|
plugins {
|
||||||
`java-library`
|
`java-library`
|
||||||
id("fabric-loom")
|
id("fabric-loom")
|
||||||
id("io.github.juuxel.loom-vineflower")
|
|
||||||
id("cc-tweaked.java-convention")
|
id("cc-tweaked.java-convention")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,7 +30,7 @@ repositories {
|
|||||||
|
|
||||||
loom {
|
loom {
|
||||||
splitEnvironmentSourceSets()
|
splitEnvironmentSourceSets()
|
||||||
splitModDependencies.set(true)
|
splitModDependencies = true
|
||||||
}
|
}
|
||||||
|
|
||||||
MinecraftConfigurations.setup(project)
|
MinecraftConfigurations.setup(project)
|
||||||
|
@@ -6,25 +6,25 @@
|
|||||||
|
|
||||||
import cc.tweaked.gradle.CCTweakedExtension
|
import cc.tweaked.gradle.CCTweakedExtension
|
||||||
import cc.tweaked.gradle.CCTweakedPlugin
|
import cc.tweaked.gradle.CCTweakedPlugin
|
||||||
import cc.tweaked.gradle.IdeaRunConfigurations
|
|
||||||
import cc.tweaked.gradle.MinecraftConfigurations
|
import cc.tweaked.gradle.MinecraftConfigurations
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("net.minecraftforge.gradle")
|
|
||||||
// We must apply java-convention after Forge, as we need the fg extension to be present.
|
|
||||||
id("cc-tweaked.java-convention")
|
id("cc-tweaked.java-convention")
|
||||||
id("org.parchmentmc.librarian.forgegradle")
|
id("net.neoforged.moddev")
|
||||||
}
|
}
|
||||||
|
|
||||||
plugins.apply(CCTweakedPlugin::class.java)
|
plugins.apply(CCTweakedPlugin::class.java)
|
||||||
|
|
||||||
val mcVersion: String by extra
|
val mcVersion: String by extra
|
||||||
|
|
||||||
minecraft {
|
neoForge {
|
||||||
val libs = project.extensions.getByType<VersionCatalogsExtension>().named("libs")
|
val libs = project.extensions.getByType<VersionCatalogsExtension>().named("libs")
|
||||||
mappings("parchment", "${libs.findVersion("parchmentMc").get()}-${libs.findVersion("parchment").get()}-$mcVersion")
|
version = libs.findVersion("neoForge").get().toString()
|
||||||
|
|
||||||
accessTransformer(project(":forge").file("src/main/resources/META-INF/accesstransformer.cfg"))
|
parchment {
|
||||||
|
minecraftVersion = libs.findVersion("parchmentMc").get().toString()
|
||||||
|
mappingsVersion = libs.findVersion("parchment").get().toString()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MinecraftConfigurations.setup(project)
|
MinecraftConfigurations.setup(project)
|
||||||
@@ -32,13 +32,3 @@ MinecraftConfigurations.setup(project)
|
|||||||
extensions.configure(CCTweakedExtension::class.java) {
|
extensions.configure(CCTweakedExtension::class.java) {
|
||||||
linters(minecraft = true, loader = "forge")
|
linters(minecraft = true, loader = "forge")
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
|
||||||
val libs = project.extensions.getByType<VersionCatalogsExtension>().named("libs")
|
|
||||||
"minecraft"("net.minecraftforge:forge:$mcVersion-${libs.findVersion("forge").get()}")
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.configureEach {
|
|
||||||
// genIntellijRuns isn't registered until much later, so we need this silly hijinks.
|
|
||||||
if (name == "genIntellijRuns") doLast { IdeaRunConfigurations(project).patch() }
|
|
||||||
}
|
|
||||||
|
@@ -29,7 +29,7 @@ base.archivesName.convention("cc-tweaked-$mcVersion-${project.name}")
|
|||||||
|
|
||||||
java {
|
java {
|
||||||
toolchain {
|
toolchain {
|
||||||
languageVersion.set(CCTweakedPlugin.JAVA_VERSION)
|
languageVersion = CCTweakedPlugin.JAVA_VERSION
|
||||||
}
|
}
|
||||||
|
|
||||||
withSourcesJar()
|
withSourcesJar()
|
||||||
@@ -38,36 +38,25 @@ java {
|
|||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
|
||||||
val mainMaven = maven("https://squiddev.cc/maven") {
|
val mainMaven = maven("https://maven.squiddev.cc/mirror") {
|
||||||
name = "SquidDev"
|
name = "SquidDev"
|
||||||
content {
|
|
||||||
// Until https://github.com/SpongePowered/Mixin/pull/593 is merged
|
|
||||||
includeModule("org.spongepowered", "mixin")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
exclusiveContent {
|
exclusiveContent {
|
||||||
forRepositories(mainMaven)
|
forRepositories(mainMaven)
|
||||||
|
|
||||||
// Include the ForgeGradle repository if present. This requires that ForgeGradle is already present, which we
|
|
||||||
// enforce in our Forge overlay.
|
|
||||||
val fg =
|
|
||||||
project.extensions.findByType(net.minecraftforge.gradle.userdev.DependencyManagementExtension::class.java)
|
|
||||||
if (fg != null) forRepositories(fg.repository)
|
|
||||||
|
|
||||||
filter {
|
filter {
|
||||||
includeGroup("cc.tweaked")
|
includeGroup("cc.tweaked")
|
||||||
includeModule("org.squiddev", "Cobalt")
|
|
||||||
// Things we mirror
|
// Things we mirror
|
||||||
includeGroup("commoble.morered")
|
includeGroup("com.simibubi.create")
|
||||||
|
includeGroup("net.commoble.morered")
|
||||||
includeGroup("dev.architectury")
|
includeGroup("dev.architectury")
|
||||||
includeGroup("dev.emi")
|
includeGroup("dev.emi")
|
||||||
includeGroup("maven.modrinth")
|
includeGroup("maven.modrinth")
|
||||||
includeGroup("me.shedaniel.cloth")
|
includeGroup("me.shedaniel.cloth")
|
||||||
includeGroup("me.shedaniel")
|
includeGroup("me.shedaniel")
|
||||||
includeGroup("mezz.jei")
|
includeGroup("mezz.jei")
|
||||||
|
includeGroup("org.teavm")
|
||||||
includeModule("com.terraformersmc", "modmenu")
|
includeModule("com.terraformersmc", "modmenu")
|
||||||
includeModule("me.lucko", "fabric-permissions-api")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -76,6 +65,12 @@ dependencies {
|
|||||||
val libs = project.extensions.getByType<VersionCatalogsExtension>().named("libs")
|
val libs = project.extensions.getByType<VersionCatalogsExtension>().named("libs")
|
||||||
checkstyle(libs.findLibrary("checkstyle").get())
|
checkstyle(libs.findLibrary("checkstyle").get())
|
||||||
|
|
||||||
|
constraints {
|
||||||
|
checkstyle("org.codehaus.plexus:plexus-container-default:2.1.1") {
|
||||||
|
because("2.1.0 depends on deprecated Google collections module")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
errorprone(libs.findLibrary("errorProne-core").get())
|
errorprone(libs.findLibrary("errorProne-core").get())
|
||||||
errorprone(libs.findLibrary("nullAway").get())
|
errorprone(libs.findLibrary("nullAway").get())
|
||||||
}
|
}
|
||||||
@@ -83,27 +78,40 @@ dependencies {
|
|||||||
// Configure default JavaCompile tasks with our arguments.
|
// Configure default JavaCompile tasks with our arguments.
|
||||||
sourceSets.all {
|
sourceSets.all {
|
||||||
tasks.named(compileJavaTaskName, JavaCompile::class.java) {
|
tasks.named(compileJavaTaskName, JavaCompile::class.java) {
|
||||||
// Processing just gives us "No processor claimed any of these annotations", so skip that!
|
|
||||||
options.compilerArgs.addAll(listOf("-Xlint", "-Xlint:-processing"))
|
options.compilerArgs.addAll(
|
||||||
|
listOf(
|
||||||
|
"-Xlint",
|
||||||
|
// Processing just gives us "No processor claimed any of these annotations", so skip that!
|
||||||
|
"-Xlint:-processing",
|
||||||
|
// We violate this pattern too often for it to be a helpful warning. Something to improve one day!
|
||||||
|
"-Xlint:-this-escape",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
options.errorprone {
|
options.errorprone {
|
||||||
check("InvalidBlockTag", CheckSeverity.OFF) // Broken by @cc.xyz
|
check("InvalidBlockTag", CheckSeverity.OFF) // Broken by @cc.xyz
|
||||||
check("InvalidParam", CheckSeverity.OFF) // Broken by records.
|
|
||||||
check("InlineMeSuggester", CheckSeverity.OFF) // Minecraft uses @Deprecated liberally
|
check("InlineMeSuggester", CheckSeverity.OFF) // Minecraft uses @Deprecated liberally
|
||||||
// Too many false positives right now. Maybe we need an indirection for it later on.
|
// Too many false positives right now. Maybe we need an indirection for it later on.
|
||||||
|
check("AssignmentExpression", CheckSeverity.OFF) // I'm a bad person.
|
||||||
check("ReferenceEquality", CheckSeverity.OFF)
|
check("ReferenceEquality", CheckSeverity.OFF)
|
||||||
check("UnusedVariable", CheckSeverity.OFF) // Too many false positives with records.
|
check("EnumOrdinal", CheckSeverity.OFF) // For now. We could replace most of these with EnumMap.
|
||||||
check("OperatorPrecedence", CheckSeverity.OFF) // For now.
|
check("OperatorPrecedence", CheckSeverity.OFF) // For now.
|
||||||
check("AlreadyChecked", CheckSeverity.OFF) // Seems to be broken?
|
|
||||||
check("NonOverridingEquals", CheckSeverity.OFF) // Peripheral.equals makes this hard to avoid
|
check("NonOverridingEquals", CheckSeverity.OFF) // Peripheral.equals makes this hard to avoid
|
||||||
check("FutureReturnValueIgnored", CheckSeverity.OFF) // Too many false positives with Netty
|
check("FutureReturnValueIgnored", CheckSeverity.OFF) // Too many false positives with Netty
|
||||||
|
check("InvalidInlineTag", CheckSeverity.OFF) // Triggered by @snippet. Can be removed on Java 21.
|
||||||
|
|
||||||
check("NullAway", CheckSeverity.ERROR)
|
check("NullAway", CheckSeverity.ERROR)
|
||||||
option("NullAway:AnnotatedPackages", listOf("dan200.computercraft", "net.fabricmc.fabric.api").joinToString(","))
|
option(
|
||||||
|
"NullAway:AnnotatedPackages",
|
||||||
|
listOf("dan200.computercraft", "cc.tweaked", "net.fabricmc.fabric.api").joinToString(","),
|
||||||
|
)
|
||||||
option("NullAway:ExcludedFieldAnnotations", listOf("org.spongepowered.asm.mixin.Shadow").joinToString(","))
|
option("NullAway:ExcludedFieldAnnotations", listOf("org.spongepowered.asm.mixin.Shadow").joinToString(","))
|
||||||
option("NullAway:CastToNonNullMethod", "dan200.computercraft.core.util.Nullability.assertNonNull")
|
option("NullAway:CastToNonNullMethod", "dan200.computercraft.core.util.Nullability.assertNonNull")
|
||||||
option("NullAway:CheckOptionalEmptiness")
|
option("NullAway:CheckOptionalEmptiness")
|
||||||
option("NullAway:AcknowledgeRestrictiveAnnotations")
|
option("NullAway:AcknowledgeRestrictiveAnnotations")
|
||||||
|
|
||||||
|
excludedPaths = ".*/jmh_generated/.*"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -114,7 +122,6 @@ tasks.compileTestJava {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
tasks.withType(JavaCompile::class.java).configureEach {
|
tasks.withType(JavaCompile::class.java).configureEach {
|
||||||
options.encoding = "UTF-8"
|
options.encoding = "UTF-8"
|
||||||
}
|
}
|
||||||
@@ -127,8 +134,8 @@ tasks.processResources {
|
|||||||
tasks.withType(AbstractArchiveTask::class.java).configureEach {
|
tasks.withType(AbstractArchiveTask::class.java).configureEach {
|
||||||
isPreserveFileTimestamps = false
|
isPreserveFileTimestamps = false
|
||||||
isReproducibleFileOrder = true
|
isReproducibleFileOrder = true
|
||||||
dirMode = Integer.valueOf("755", 8)
|
filePermissions {}
|
||||||
fileMode = Integer.valueOf("664", 8)
|
dirPermissions {}
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.jar {
|
tasks.jar {
|
||||||
@@ -148,7 +155,7 @@ tasks.javadoc {
|
|||||||
options {
|
options {
|
||||||
val stdOptions = this as StandardJavadocDocletOptions
|
val stdOptions = this as StandardJavadocDocletOptions
|
||||||
stdOptions.addBooleanOption("Xdoclint:all,-missing", true)
|
stdOptions.addBooleanOption("Xdoclint:all,-missing", true)
|
||||||
stdOptions.links("https://docs.oracle.com/en/java/javase/17/docs/api/")
|
stdOptions.links("https://docs.oracle.com/en/java/javase/21/docs/api/")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,8 +169,8 @@ tasks.test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType(JacocoReport::class.java).configureEach {
|
tasks.withType(JacocoReport::class.java).configureEach {
|
||||||
reports.xml.required.set(true)
|
reports.xml.required = true
|
||||||
reports.html.required.set(true)
|
reports.html.required = true
|
||||||
}
|
}
|
||||||
|
|
||||||
project.plugins.withType(CCTweakedPlugin::class.java) {
|
project.plugins.withType(CCTweakedPlugin::class.java) {
|
||||||
@@ -174,6 +181,12 @@ project.plugins.withType(CCTweakedPlugin::class.java) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tasks.register("checkstyle") {
|
||||||
|
description = "Run Checkstyle on all sources"
|
||||||
|
group = LifecycleBasePlugin.VERIFICATION_GROUP
|
||||||
|
dependsOn(tasks.withType(Checkstyle::class.java))
|
||||||
|
}
|
||||||
|
|
||||||
spotless {
|
spotless {
|
||||||
encoding = StandardCharsets.UTF_8
|
encoding = StandardCharsets.UTF_8
|
||||||
lineEndings = LineEnding.UNIX
|
lineEndings = LineEnding.UNIX
|
||||||
@@ -181,29 +194,23 @@ spotless {
|
|||||||
fun FormatExtension.defaults() {
|
fun FormatExtension.defaults() {
|
||||||
endWithNewline()
|
endWithNewline()
|
||||||
trimTrailingWhitespace()
|
trimTrailingWhitespace()
|
||||||
indentWithSpaces(4)
|
leadingTabsToSpaces(4)
|
||||||
}
|
}
|
||||||
|
|
||||||
java {
|
java {
|
||||||
defaults()
|
defaults()
|
||||||
|
importOrder("", "javax|java", "\\#")
|
||||||
removeUnusedImports()
|
removeUnusedImports()
|
||||||
}
|
}
|
||||||
|
|
||||||
val ktlintConfig = mapOf(
|
|
||||||
"ktlint_standard_no-wildcard-imports" to "disabled",
|
|
||||||
"ktlint_standard_class-naming" to "disabled",
|
|
||||||
"ij_kotlin_allow_trailing_comma" to "true",
|
|
||||||
"ij_kotlin_allow_trailing_comma_on_call_site" to "true",
|
|
||||||
)
|
|
||||||
|
|
||||||
kotlinGradle {
|
kotlinGradle {
|
||||||
defaults()
|
defaults()
|
||||||
ktlint().editorConfigOverride(ktlintConfig)
|
ktlint()
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
defaults()
|
defaults()
|
||||||
ktlint().editorConfigOverride(ktlintConfig)
|
ktlint()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,6 +219,5 @@ idea.module {
|
|||||||
|
|
||||||
// Force Gradle to write to inherit the output directory from the parent, instead of writing to out/xxx/classes.
|
// Force Gradle to write to inherit the output directory from the parent, instead of writing to out/xxx/classes.
|
||||||
// This is required for Loom, and we patch Forge's run configurations to work there.
|
// This is required for Loom, and we patch Forge's run configurations to work there.
|
||||||
// TODO: Submit a patch to Forge to support ProjectRootManager.
|
|
||||||
inheritOutputDirs = true
|
inheritOutputDirs = true
|
||||||
}
|
}
|
||||||
|
@@ -1,25 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2022 The CC: Tweaked Developers
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
import cc.tweaked.gradle.CCTweakedPlugin
|
|
||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
|
||||||
|
|
||||||
plugins {
|
|
||||||
kotlin("jvm")
|
|
||||||
}
|
|
||||||
|
|
||||||
kotlin {
|
|
||||||
jvmToolchain {
|
|
||||||
languageVersion.set(CCTweakedPlugin.JAVA_VERSION)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.withType(KotlinCompile::class.java).configureEach {
|
|
||||||
// So technically we shouldn't need to do this as the toolchain sets it above. However, the option only appears
|
|
||||||
// to be set when the task executes, so doesn't get picked up by IDEs.
|
|
||||||
kotlinOptions.jvmTarget = when {
|
|
||||||
CCTweakedPlugin.JAVA_VERSION.asInt() > 8 -> CCTweakedPlugin.JAVA_VERSION.toString()
|
|
||||||
else -> "1.${CCTweakedPlugin.JAVA_VERSION.asInt()}"
|
|
||||||
}
|
|
||||||
}
|
|
@@ -2,11 +2,9 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
import net.darkhax.curseforgegradle.TaskPublishCurseForge
|
|
||||||
import cc.tweaked.gradle.setProvider
|
import cc.tweaked.gradle.setProvider
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("net.darkhax.curseforgegradle")
|
|
||||||
id("com.modrinth.minotaur")
|
id("com.modrinth.minotaur")
|
||||||
id("cc-tweaked.publishing")
|
id("cc-tweaked.publishing")
|
||||||
}
|
}
|
||||||
@@ -25,34 +23,17 @@ val isUnstable = project.properties["isUnstable"] == "true"
|
|||||||
val modVersion: String by extra
|
val modVersion: String by extra
|
||||||
val mcVersion: String by extra
|
val mcVersion: String by extra
|
||||||
|
|
||||||
val publishCurseForge by tasks.registering(TaskPublishCurseForge::class) {
|
|
||||||
group = PublishingPlugin.PUBLISH_TASK_GROUP
|
|
||||||
description = "Upload artifacts to CurseForge"
|
|
||||||
|
|
||||||
apiToken = findProperty("curseForgeApiKey") ?: ""
|
|
||||||
enabled = apiToken != ""
|
|
||||||
|
|
||||||
val mainFile = upload("282001", modPublishing.output.get().archiveFile)
|
|
||||||
mainFile.changelog =
|
|
||||||
"Release notes can be found on the [GitHub repository](https://github.com/cc-tweaked/CC-Tweaked/releases/tag/v$mcVersion-$modVersion)."
|
|
||||||
mainFile.changelogType = "markdown"
|
|
||||||
mainFile.releaseType = if (isUnstable) "alpha" else "release"
|
|
||||||
mainFile.gameVersions.add(mcVersion)
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.publish { dependsOn(publishCurseForge) }
|
|
||||||
|
|
||||||
modrinth {
|
modrinth {
|
||||||
token.set(findProperty("modrinthApiKey") as String? ?: "")
|
token = findProperty("modrinthApiKey") as String? ?: ""
|
||||||
projectId.set("gu7yAYhd")
|
projectId = "gu7yAYhd"
|
||||||
versionNumber.set(modVersion)
|
versionNumber = modVersion
|
||||||
versionName.set(modVersion)
|
versionName = modVersion
|
||||||
versionType.set(if (isUnstable) "alpha" else "release")
|
versionType = if (isUnstable) "alpha" else "release"
|
||||||
uploadFile.setProvider(modPublishing.output)
|
uploadFile.setProvider(modPublishing.output)
|
||||||
gameVersions.add(mcVersion)
|
gameVersions.add(mcVersion)
|
||||||
changelog.set("Release notes can be found on the [GitHub repository](https://github.com/cc-tweaked/CC-Tweaked/releases/tag/v$mcVersion-$modVersion).")
|
changelog = "Release notes can be found on the [GitHub repository](https://github.com/cc-tweaked/CC-Tweaked/releases/tag/v$mcVersion-$modVersion)."
|
||||||
|
|
||||||
syncBodyFrom.set(provider { rootProject.file("doc/mod-page.md").readText() })
|
syncBodyFrom = provider { rootProject.file("doc/mod-page.md").readText() }
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.publish { dependsOn(tasks.modrinth) }
|
tasks.publish { dependsOn(tasks.modrinth) }
|
||||||
|
@@ -2,44 +2,34 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
import cc.tweaked.gradle.clientClasses
|
|
||||||
import cc.tweaked.gradle.commonClasses
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up the configurations for writing game tests.
|
* Sets up the configurations for writing game tests.
|
||||||
*
|
*
|
||||||
* See notes in [cc.tweaked.gradle.MinecraftConfigurations] for the general design behind these cursed ideas.
|
* See notes in [cc.tweaked.gradle.MinecraftConfigurations] for the general design behind these cursed ideas.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import cc.tweaked.gradle.MinecraftConfigurations
|
||||||
|
import cc.tweaked.gradle.clientClasses
|
||||||
|
import cc.tweaked.gradle.commonClasses
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("cc-tweaked.kotlin-convention")
|
kotlin("jvm")
|
||||||
id("cc-tweaked.java-convention")
|
id("cc-tweaked.java-convention")
|
||||||
}
|
}
|
||||||
|
|
||||||
val main = sourceSets["main"]
|
val main = sourceSets["main"]
|
||||||
val client = sourceSets["client"]
|
val client = sourceSets["client"]
|
||||||
|
|
||||||
// Both testMod and testFixtures inherit from the main and client classpath, just so we have access to Minecraft classes.
|
MinecraftConfigurations.createDerivedConfiguration(project, MinecraftConfigurations.DATAGEN)
|
||||||
val testMod by sourceSets.creating {
|
MinecraftConfigurations.createDerivedConfiguration(project, MinecraftConfigurations.EXAMPLES)
|
||||||
compileClasspath += main.compileClasspath + client.compileClasspath
|
MinecraftConfigurations.createDerivedConfiguration(project, MinecraftConfigurations.TEST_MOD)
|
||||||
runtimeClasspath += main.runtimeClasspath + client.runtimeClasspath
|
|
||||||
}
|
|
||||||
|
|
||||||
configurations {
|
// Set up generated resources
|
||||||
named(testMod.compileClasspathConfigurationName) {
|
sourceSets.main { resources.srcDir("src/generated/resources") }
|
||||||
shouldResolveConsistentlyWith(compileClasspath.get())
|
sourceSets.named("examples") { resources.srcDir("src/examples/generatedResources") }
|
||||||
}
|
|
||||||
|
|
||||||
named(testMod.runtimeClasspathConfigurationName) {
|
// Make sure our examples compile.
|
||||||
shouldResolveConsistentlyWith(runtimeClasspath.get())
|
tasks.check { dependsOn(tasks.named("compileExamplesJava")) }
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Like the main test configurations, we're safe to depend on source set outputs.
|
|
||||||
dependencies {
|
|
||||||
add(testMod.implementationConfigurationName, main.output)
|
|
||||||
add(testMod.implementationConfigurationName, client.output)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Similar to java-test-fixtures, but tries to avoid putting the obfuscated jar on the classpath.
|
// Similar to java-test-fixtures, but tries to avoid putting the obfuscated jar on the classpath.
|
||||||
|
|
@@ -12,25 +12,26 @@ publishing {
|
|||||||
register<MavenPublication>("maven") {
|
register<MavenPublication>("maven") {
|
||||||
artifactId = base.archivesName.get()
|
artifactId = base.archivesName.get()
|
||||||
from(components["java"])
|
from(components["java"])
|
||||||
|
suppressAllPomMetadataWarnings()
|
||||||
|
|
||||||
pom {
|
pom {
|
||||||
name.set("CC: Tweaked")
|
name = "CC: Tweaked"
|
||||||
description.set("CC: Tweaked is a fork of ComputerCraft, adding programmable computers, turtles and more to Minecraft.")
|
description = "CC: Tweaked is a fork of ComputerCraft, adding programmable computers, turtles and more to Minecraft."
|
||||||
url.set("https://github.com/cc-tweaked/CC-Tweaked")
|
url = "https://github.com/cc-tweaked/CC-Tweaked"
|
||||||
|
|
||||||
scm {
|
scm {
|
||||||
url.set("https://github.com/cc-tweaked/CC-Tweaked.git")
|
url = "https://github.com/cc-tweaked/CC-Tweaked.git"
|
||||||
}
|
}
|
||||||
|
|
||||||
issueManagement {
|
issueManagement {
|
||||||
system.set("github")
|
system = "github"
|
||||||
url.set("https://github.com/cc-tweaked/CC-Tweaked/issues")
|
url = "https://github.com/cc-tweaked/CC-Tweaked/issues"
|
||||||
}
|
}
|
||||||
|
|
||||||
licenses {
|
licenses {
|
||||||
license {
|
license {
|
||||||
name.set("ComputerCraft Public License, Version 1.0")
|
name = "ComputerCraft Public License, Version 1.0"
|
||||||
url.set("https://github.com/cc-tweaked/CC-Tweaked/blob/HEAD/LICENSE")
|
url = "https://github.com/cc-tweaked/CC-Tweaked/blob/HEAD/LICENSE"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -38,7 +39,7 @@ publishing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
maven("https://squiddev.cc/maven") {
|
maven("https://maven.squiddev.cc") {
|
||||||
name = "SquidDev"
|
name = "SquidDev"
|
||||||
|
|
||||||
credentials(PasswordCredentials::class)
|
credentials(PasswordCredentials::class)
|
||||||
|
@@ -10,25 +10,31 @@ import cc.tweaked.gradle.MinecraftConfigurations
|
|||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("cc-tweaked.java-convention")
|
id("cc-tweaked.java-convention")
|
||||||
id("org.spongepowered.gradle.vanilla")
|
id("cc.tweaked.vanilla-extract")
|
||||||
}
|
}
|
||||||
|
|
||||||
plugins.apply(CCTweakedPlugin::class.java)
|
plugins.apply(CCTweakedPlugin::class.java)
|
||||||
|
|
||||||
val mcVersion: String by extra
|
val mcVersion: String by extra
|
||||||
|
|
||||||
|
val libs = project.extensions.getByType<VersionCatalogsExtension>().named("libs")
|
||||||
|
|
||||||
minecraft {
|
minecraft {
|
||||||
version(mcVersion)
|
version(mcVersion)
|
||||||
|
|
||||||
|
mappings {
|
||||||
|
parchment(libs.findVersion("parchmentMc").get().toString(), libs.findVersion("parchment").get().toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
unpick(libs.findLibrary("yarn").get())
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
val libs = project.extensions.getByType<VersionCatalogsExtension>().named("libs")
|
|
||||||
|
|
||||||
// Depend on error prone annotations to silence a lot of compile warnings.
|
// Depend on error prone annotations to silence a lot of compile warnings.
|
||||||
compileOnlyApi(libs.findLibrary("errorProne.annotations").get())
|
compileOnly(libs.findLibrary("errorProne.annotations").get())
|
||||||
}
|
}
|
||||||
|
|
||||||
MinecraftConfigurations.setup(project)
|
MinecraftConfigurations.setupBasic(project)
|
||||||
|
|
||||||
extensions.configure(CCTweakedExtension::class.java) {
|
extensions.configure(CCTweakedExtension::class.java) {
|
||||||
linters(minecraft = true, loader = null)
|
linters(minecraft = true, loader = null)
|
||||||
|
@@ -10,21 +10,16 @@ import org.gradle.api.GradleException
|
|||||||
import org.gradle.api.NamedDomainObjectProvider
|
import org.gradle.api.NamedDomainObjectProvider
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.Task
|
import org.gradle.api.Task
|
||||||
import org.gradle.api.attributes.TestSuiteType
|
|
||||||
import org.gradle.api.file.FileSystemOperations
|
|
||||||
import org.gradle.api.plugins.JavaPluginExtension
|
import org.gradle.api.plugins.JavaPluginExtension
|
||||||
import org.gradle.api.provider.Provider
|
import org.gradle.api.provider.Provider
|
||||||
import org.gradle.api.provider.SetProperty
|
import org.gradle.api.provider.SetProperty
|
||||||
import org.gradle.api.reporting.ReportingExtension
|
|
||||||
import org.gradle.api.tasks.SourceSet
|
import org.gradle.api.tasks.SourceSet
|
||||||
import org.gradle.api.tasks.bundling.Jar
|
import org.gradle.api.tasks.bundling.Jar
|
||||||
import org.gradle.api.tasks.compile.JavaCompile
|
import org.gradle.api.tasks.compile.JavaCompile
|
||||||
import org.gradle.api.tasks.javadoc.Javadoc
|
import org.gradle.api.tasks.javadoc.Javadoc
|
||||||
import org.gradle.configurationcache.extensions.capitalized
|
|
||||||
import org.gradle.language.base.plugins.LifecycleBasePlugin
|
import org.gradle.language.base.plugins.LifecycleBasePlugin
|
||||||
import org.gradle.language.jvm.tasks.ProcessResources
|
import org.gradle.language.jvm.tasks.ProcessResources
|
||||||
import org.gradle.process.JavaForkOptions
|
import org.gradle.process.JavaForkOptions
|
||||||
import org.gradle.testing.jacoco.plugins.JacocoCoverageReport
|
|
||||||
import org.gradle.testing.jacoco.plugins.JacocoPluginExtension
|
import org.gradle.testing.jacoco.plugins.JacocoPluginExtension
|
||||||
import org.gradle.testing.jacoco.plugins.JacocoTaskExtension
|
import org.gradle.testing.jacoco.plugins.JacocoTaskExtension
|
||||||
import org.gradle.testing.jacoco.tasks.JacocoReport
|
import org.gradle.testing.jacoco.tasks.JacocoReport
|
||||||
@@ -33,40 +28,31 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
import java.net.URL
|
|
||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
|
|
||||||
abstract class CCTweakedExtension(
|
abstract class CCTweakedExtension(private val project: Project) {
|
||||||
private val project: Project,
|
|
||||||
private val fs: FileSystemOperations,
|
|
||||||
) {
|
|
||||||
/** Get the hash of the latest git commit. */
|
/** Get the hash of the latest git commit. */
|
||||||
val gitHash: Provider<String> = gitProvider(project, "<no git hash>") {
|
val gitHash: Provider<String> =
|
||||||
ProcessHelpers.captureOut("git", "-C", project.rootProject.projectDir.absolutePath, "rev-parse", "HEAD").trim()
|
gitProvider("<no git commit>", listOf("rev-parse", "HEAD")) { it.trim() }
|
||||||
}
|
|
||||||
|
|
||||||
/** Get the current git branch. */
|
/** Get the current git branch. */
|
||||||
val gitBranch: Provider<String> = gitProvider(project, "<no git branch>") {
|
val gitBranch: Provider<String> =
|
||||||
ProcessHelpers.captureOut("git", "-C", project.rootProject.projectDir.absolutePath, "rev-parse", "--abbrev-ref", "HEAD")
|
gitProvider("<no git branch>", listOf("rev-parse", "--abbrev-ref", "HEAD")) { it.trim() }
|
||||||
.trim()
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a list of all contributors to the project. */
|
/** Get a list of all contributors to the project. */
|
||||||
val gitContributors: Provider<List<String>> = gitProvider(project, listOf()) {
|
val gitContributors: Provider<List<String>> =
|
||||||
ProcessHelpers.captureLines(
|
gitProvider(listOf(), listOf("shortlog", "-ns", "--group=author", "--group=trailer:co-authored-by", "HEAD")) { input ->
|
||||||
"git", "-C", project.rootProject.projectDir.absolutePath, "shortlog", "-ns",
|
input.lineSequence()
|
||||||
"--group=author", "--group=trailer:co-authored-by", "HEAD",
|
.filter { it.isNotEmpty() }
|
||||||
)
|
.map {
|
||||||
.asSequence()
|
val matcher = COMMIT_COUNTS.matcher(it)
|
||||||
.map {
|
matcher.find()
|
||||||
val matcher = COMMIT_COUNTS.matcher(it)
|
matcher.group(1)
|
||||||
matcher.find()
|
}
|
||||||
matcher.group(1)
|
.filter { !IGNORED_USERS.contains(it) }
|
||||||
}
|
.toList()
|
||||||
.filter { !IGNORED_USERS.contains(it) }
|
.sortedWith(String.CASE_INSENSITIVE_ORDER)
|
||||||
.toList()
|
}
|
||||||
.sortedWith(String.CASE_INSENSITIVE_ORDER)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* References to other sources
|
* References to other sources
|
||||||
@@ -103,14 +89,13 @@ abstract class CCTweakedExtension(
|
|||||||
val otherJava = otherProject.extensions.getByType(JavaPluginExtension::class.java)
|
val otherJava = otherProject.extensions.getByType(JavaPluginExtension::class.java)
|
||||||
val main = otherJava.sourceSets.getByName("main")
|
val main = otherJava.sourceSets.getByName("main")
|
||||||
val client = otherJava.sourceSets.getByName("client")
|
val client = otherJava.sourceSets.getByName("client")
|
||||||
val testMod = otherJava.sourceSets.findByName("testMod")
|
|
||||||
val testFixtures = otherJava.sourceSets.findByName("testFixtures")
|
|
||||||
|
|
||||||
// Pull in sources from the other project.
|
// Pull in sources from the other project.
|
||||||
extendSourceSet(otherProject, main)
|
extendSourceSet(otherProject, main)
|
||||||
extendSourceSet(otherProject, client)
|
extendSourceSet(otherProject, client)
|
||||||
if (testMod != null) extendSourceSet(otherProject, testMod)
|
for (sourceSet in listOf(MinecraftConfigurations.DATAGEN, MinecraftConfigurations.EXAMPLES, MinecraftConfigurations.TEST_MOD, "testFixtures")) {
|
||||||
if (testFixtures != null) extendSourceSet(otherProject, testFixtures)
|
otherJava.sourceSets.findByName(sourceSet)?.let { extendSourceSet(otherProject, it) }
|
||||||
|
}
|
||||||
|
|
||||||
// The extra source-processing tasks should include these files too.
|
// The extra source-processing tasks should include these files too.
|
||||||
project.tasks.named(main.javadocTaskName, Javadoc::class.java) { source(main.allJava, client.allJava) }
|
project.tasks.named(main.javadocTaskName, Javadoc::class.java) { source(main.allJava, client.allJava) }
|
||||||
@@ -173,23 +158,19 @@ abstract class CCTweakedExtension(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun <T> jacoco(task: NamedDomainObjectProvider<T>) where T : Task, T : JavaForkOptions {
|
fun <T> jacoco(task: NamedDomainObjectProvider<T>) where T : Task, T : JavaForkOptions {
|
||||||
val classDump = project.buildDir.resolve("jacocoClassDump/${task.name}")
|
val reportTaskName = "jacoco${task.name.capitalise()}Report"
|
||||||
val reportTaskName = "jacoco${task.name.capitalized()}Report"
|
|
||||||
|
|
||||||
val jacoco = project.extensions.getByType(JacocoPluginExtension::class.java)
|
val jacoco = project.extensions.getByType(JacocoPluginExtension::class.java)
|
||||||
task.configure {
|
task.configure {
|
||||||
finalizedBy(reportTaskName)
|
finalizedBy(reportTaskName)
|
||||||
|
|
||||||
doFirst("Clean class dump directory") { fs.delete { delete(classDump) } }
|
|
||||||
|
|
||||||
jacoco.applyTo(this)
|
jacoco.applyTo(this)
|
||||||
|
|
||||||
extensions.configure(JacocoTaskExtension::class.java) {
|
extensions.configure(JacocoTaskExtension::class.java) {
|
||||||
includes = listOf("dan200.computercraft.*")
|
includes = listOf("dan200.computercraft.*")
|
||||||
classDumpDir = classDump
|
excludes = listOf(
|
||||||
|
"dan200.computercraft.mixin.*", // Exclude mixins, as they're not executed at runtime.
|
||||||
// Older versions of modlauncher don't include a protection domain (and thus no code
|
"dan200.computercraft.shared.Capabilities$*", // Exclude capability tokens, as Forge rewrites them.
|
||||||
// source). Jacoco skips such classes by default, so we need to explicitly include them.
|
)
|
||||||
isIncludeNoLocationClasses = true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,15 +179,11 @@ abstract class CCTweakedExtension(
|
|||||||
description = "Generates code coverage report for the ${task.name} task."
|
description = "Generates code coverage report for the ${task.name} task."
|
||||||
|
|
||||||
executionData(task.get())
|
executionData(task.get())
|
||||||
classDirectories.from(classDump)
|
|
||||||
|
|
||||||
// Don't want to use sourceSets(...) here as we have a custom class directory.
|
// Don't want to use sourceSets(...) here as we don't use all class directories.
|
||||||
for (ref in sourceSets.get()) sourceDirectories.from(ref.allSource.sourceDirectories)
|
for (ref in this@CCTweakedExtension.sourceDirectories.get()) {
|
||||||
}
|
sourceDirectories.from(ref.sourceSet.allSource.sourceDirectories)
|
||||||
|
if (ref.classes) classDirectories.from(ref.sourceSet.output)
|
||||||
project.extensions.configure(ReportingExtension::class.java) {
|
|
||||||
reports.register("${task.name}CodeCoverageReport", JacocoCoverageReport::class.java) {
|
|
||||||
testType.set(TestSuiteType.INTEGRATION_TEST)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -218,12 +195,12 @@ abstract class CCTweakedExtension(
|
|||||||
* where possible.
|
* where possible.
|
||||||
*/
|
*/
|
||||||
fun downloadFile(label: String, url: String): File {
|
fun downloadFile(label: String, url: String): File {
|
||||||
val url = URL(url)
|
val uri = URI(url)
|
||||||
val path = File(url.path)
|
val path = File(uri.path)
|
||||||
|
|
||||||
project.repositories.ivy {
|
project.repositories.ivy {
|
||||||
name = label
|
name = label
|
||||||
setUrl(URI(url.protocol, url.userInfo, url.host, url.port, path.parent, null, null))
|
setUrl(URI(uri.scheme, uri.userInfo, uri.host, uri.port, path.parent, null, null))
|
||||||
patternLayout {
|
patternLayout {
|
||||||
artifact("[artifact].[ext]")
|
artifact("[artifact].[ext]")
|
||||||
}
|
}
|
||||||
@@ -246,26 +223,31 @@ abstract class CCTweakedExtension(
|
|||||||
).resolve().single()
|
).resolve().single()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun <T> gitProvider(default: T, command: List<String>, process: (String) -> T): Provider<T> {
|
||||||
|
val baseResult = project.providers.exec {
|
||||||
|
commandLine = listOf("git", "-C", project.rootDir.absolutePath) + command
|
||||||
|
}
|
||||||
|
|
||||||
|
return project.provider {
|
||||||
|
val res = try {
|
||||||
|
baseResult.standardOutput.asText.get()
|
||||||
|
} catch (e: IOException) {
|
||||||
|
project.logger.error("Cannot read Git repository: ${e.message}", e)
|
||||||
|
return@provider default
|
||||||
|
} catch (e: GradleException) {
|
||||||
|
project.logger.error("Cannot read Git repository: ${e.message}", e)
|
||||||
|
return@provider default
|
||||||
|
}
|
||||||
|
process(res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val COMMIT_COUNTS = Pattern.compile("""^\s*[0-9]+\s+(.*)$""")
|
private val COMMIT_COUNTS = Pattern.compile("""^\s*[0-9]+\s+(.*)$""")
|
||||||
private val IGNORED_USERS = setOf(
|
private val IGNORED_USERS = setOf(
|
||||||
"GitHub", "Daniel Ratcliffe", "Weblate",
|
"GitHub", "Daniel Ratcliffe", "NotSquidDev", "Weblate",
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun <T> gitProvider(project: Project, default: T, supplier: () -> T): Provider<T> {
|
|
||||||
return project.provider {
|
|
||||||
try {
|
|
||||||
supplier()
|
|
||||||
} catch (e: IOException) {
|
|
||||||
project.logger.error("Cannot read Git repository: ${e.message}")
|
|
||||||
default
|
|
||||||
} catch (e: GradleException) {
|
|
||||||
project.logger.error("Cannot read Git repository: ${e.message}")
|
|
||||||
default
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val isIdeSync: Boolean
|
private val isIdeSync: Boolean
|
||||||
get() = java.lang.Boolean.parseBoolean(System.getProperty("idea.sync.active", "false"))
|
get() = java.lang.Boolean.parseBoolean(System.getProperty("idea.sync.active", "false"))
|
||||||
}
|
}
|
||||||
|
@@ -9,6 +9,10 @@ import org.gradle.api.Project
|
|||||||
import org.gradle.api.plugins.JavaPlugin
|
import org.gradle.api.plugins.JavaPlugin
|
||||||
import org.gradle.api.plugins.JavaPluginExtension
|
import org.gradle.api.plugins.JavaPluginExtension
|
||||||
import org.gradle.jvm.toolchain.JavaLanguageVersion
|
import org.gradle.jvm.toolchain.JavaLanguageVersion
|
||||||
|
import org.gradle.plugins.ide.idea.model.IdeaModel
|
||||||
|
import org.jetbrains.gradle.ext.IdeaExtPlugin
|
||||||
|
import org.jetbrains.gradle.ext.runConfigurations
|
||||||
|
import org.jetbrains.gradle.ext.settings
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures projects to match a shared configuration.
|
* Configures projects to match a shared configuration.
|
||||||
@@ -21,9 +25,23 @@ class CCTweakedPlugin : Plugin<Project> {
|
|||||||
val sourceSets = project.extensions.getByType(JavaPluginExtension::class.java).sourceSets
|
val sourceSets = project.extensions.getByType(JavaPluginExtension::class.java).sourceSets
|
||||||
cct.sourceDirectories.add(SourceSetReference.internal(sourceSets.getByName("main")))
|
cct.sourceDirectories.add(SourceSetReference.internal(sourceSets.getByName("main")))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
project.plugins.withType(IdeaExtPlugin::class.java) { extendIdea(project) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extend the [IdeaExtPlugin] plugin's `runConfiguration` container to also support [JUnitExt].
|
||||||
|
*/
|
||||||
|
private fun extendIdea(project: Project) {
|
||||||
|
val ideaModel = project.extensions.findByName("idea") as IdeaModel? ?: return
|
||||||
|
val ideaProject = ideaModel.project ?: return
|
||||||
|
|
||||||
|
ideaProject.settings.runConfigurations {
|
||||||
|
registerFactory(JUnitExt::class.java) { name -> project.objects.newInstance(JUnitExt::class.java, name) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val JAVA_VERSION = JavaLanguageVersion.of(17)
|
val JAVA_VERSION = JavaLanguageVersion.of(21)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,98 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2023 The CC: Tweaked Developers
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
package cc.tweaked.gradle
|
||||||
|
|
||||||
|
import org.gradle.api.DefaultTask
|
||||||
|
import org.gradle.api.GradleException
|
||||||
|
import org.gradle.api.artifacts.Configuration
|
||||||
|
import org.gradle.api.artifacts.MinimalExternalModuleDependency
|
||||||
|
import org.gradle.api.artifacts.component.ModuleComponentIdentifier
|
||||||
|
import org.gradle.api.artifacts.component.ModuleComponentSelector
|
||||||
|
import org.gradle.api.artifacts.component.ProjectComponentIdentifier
|
||||||
|
import org.gradle.api.artifacts.result.DependencyResult
|
||||||
|
import org.gradle.api.artifacts.result.ResolvedDependencyResult
|
||||||
|
import org.gradle.api.provider.ListProperty
|
||||||
|
import org.gradle.api.provider.MapProperty
|
||||||
|
import org.gradle.api.provider.Provider
|
||||||
|
import org.gradle.api.tasks.Input
|
||||||
|
import org.gradle.api.tasks.TaskAction
|
||||||
|
import org.gradle.language.base.plugins.LifecycleBasePlugin
|
||||||
|
|
||||||
|
abstract class DependencyCheck : DefaultTask() {
|
||||||
|
@get:Input
|
||||||
|
protected abstract val dependencies: ListProperty<DependencyResult>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A mapping of module coordinates (`group:module`) to versions, overriding the requested version.
|
||||||
|
*/
|
||||||
|
@get:Input
|
||||||
|
protected abstract val overrides: MapProperty<String, String>
|
||||||
|
|
||||||
|
init {
|
||||||
|
description = "Check :core's dependencies are consistent with Minecraft's."
|
||||||
|
group = LifecycleBasePlugin.VERIFICATION_GROUP
|
||||||
|
|
||||||
|
dependencies.finalizeValueOnRead()
|
||||||
|
overrides.finalizeValueOnRead()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override a module with a different version.
|
||||||
|
*/
|
||||||
|
fun override(module: Provider<MinimalExternalModuleDependency>, version: String) {
|
||||||
|
overrides.putAll(project.provider { mutableMapOf(module.get().module.toString() to version) })
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a configuration to check.
|
||||||
|
*/
|
||||||
|
fun configuration(configuration: Provider<Configuration>) {
|
||||||
|
// We can't store the Configuration in the cache, so store the resolved dependencies instead.
|
||||||
|
dependencies.addAll(configuration.map { it.incoming.resolutionResult.allDependencies })
|
||||||
|
}
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
fun run() {
|
||||||
|
var ok = true
|
||||||
|
for (configuration in dependencies.get()) {
|
||||||
|
if (!check(configuration)) ok = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ok) {
|
||||||
|
throw GradleException("Mismatched versions in Minecraft dependencies. gradle/libs.versions.toml may need updating.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun check(dependency: DependencyResult): Boolean {
|
||||||
|
if (dependency !is ResolvedDependencyResult) {
|
||||||
|
logger.warn("Found unexpected dependency result {}", dependency)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip dependencies on non-modules.
|
||||||
|
val requested = dependency.requested
|
||||||
|
if (requested !is ModuleComponentSelector) return true
|
||||||
|
|
||||||
|
// If this dependency is specified within some project (so is non-transitive), or is pulled in via Minecraft,
|
||||||
|
// then check for consistency.
|
||||||
|
// It would be nice to be smarter about transitive dependencies, but avoiding false positives is hard.
|
||||||
|
val from = dependency.from.id
|
||||||
|
if (
|
||||||
|
from is ProjectComponentIdentifier ||
|
||||||
|
from is ModuleComponentIdentifier && (from.group == "net.minecraft" || from.group == "io.netty")
|
||||||
|
) {
|
||||||
|
// If the version is different between the requested and selected version, report an error.
|
||||||
|
val selected = dependency.selected.moduleVersion!!.version
|
||||||
|
val requestedVersion = overrides.get()["${requested.group}:${requested.module}"] ?: requested.version
|
||||||
|
if (requestedVersion != selected) {
|
||||||
|
logger.error("Requested dependency {} (via {}) but got version {}", requested, from, selected)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
@@ -4,12 +4,11 @@
|
|||||||
|
|
||||||
package cc.tweaked.gradle
|
package cc.tweaked.gradle
|
||||||
|
|
||||||
import org.gradle.api.provider.Property
|
import org.gradle.api.file.DirectoryProperty
|
||||||
import org.gradle.api.tasks.AbstractExecTask
|
import org.gradle.api.tasks.AbstractExecTask
|
||||||
import org.gradle.api.tasks.OutputDirectory
|
import org.gradle.api.tasks.OutputDirectory
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
abstract class ExecToDir : AbstractExecTask<ExecToDir>(ExecToDir::class.java) {
|
abstract class ExecToDir : AbstractExecTask<ExecToDir>(ExecToDir::class.java) {
|
||||||
@get:OutputDirectory
|
@get:OutputDirectory
|
||||||
abstract val output: Property<File>
|
abstract val output: DirectoryProperty
|
||||||
}
|
}
|
||||||
|
@@ -5,9 +5,11 @@
|
|||||||
package cc.tweaked.gradle
|
package cc.tweaked.gradle
|
||||||
|
|
||||||
import org.gradle.api.artifacts.dsl.DependencyHandler
|
import org.gradle.api.artifacts.dsl.DependencyHandler
|
||||||
|
import org.gradle.api.file.FileSystemLocation
|
||||||
import org.gradle.api.provider.Property
|
import org.gradle.api.provider.Property
|
||||||
import org.gradle.api.provider.Provider
|
import org.gradle.api.provider.Provider
|
||||||
import org.gradle.api.tasks.JavaExec
|
import org.gradle.api.tasks.JavaExec
|
||||||
|
import org.gradle.kotlin.dsl.getByName
|
||||||
import org.gradle.process.BaseExecSpec
|
import org.gradle.process.BaseExecSpec
|
||||||
import org.gradle.process.JavaExecSpec
|
import org.gradle.process.JavaExecSpec
|
||||||
import org.gradle.process.ProcessForkOptions
|
import org.gradle.process.ProcessForkOptions
|
||||||
@@ -45,6 +47,21 @@ fun JavaExec.copyToFull(spec: JavaExec) {
|
|||||||
copyToExec(spec)
|
copyToExec(spec)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base this [JavaExec] task on an existing task.
|
||||||
|
*/
|
||||||
|
fun JavaExec.copyFromTask(task: JavaExec) {
|
||||||
|
for (dep in task.dependsOn) dependsOn(dep)
|
||||||
|
task.copyToFull(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base this [JavaExec] task on an existing task.
|
||||||
|
*/
|
||||||
|
fun JavaExec.copyFromTask(task: String) {
|
||||||
|
copyFromTask(project.tasks.getByName<JavaExec>(task))
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copy additional [BaseExecSpec] options which aren't handled by [ProcessForkOptions.copyTo].
|
* Copy additional [BaseExecSpec] options which aren't handled by [ProcessForkOptions.copyTo].
|
||||||
*/
|
*/
|
||||||
@@ -124,3 +141,45 @@ class CloseScope : AutoCloseable {
|
|||||||
|
|
||||||
/** Proxy method to avoid overload ambiguity. */
|
/** Proxy method to avoid overload ambiguity. */
|
||||||
fun <T> Property<T>.setProvider(provider: Provider<out T>) = set(provider)
|
fun <T> Property<T>.setProvider(provider: Provider<out T>) = set(provider)
|
||||||
|
|
||||||
|
/** Short-cut method to get the absolute path of a [FileSystemLocation] provider. */
|
||||||
|
fun Provider<out FileSystemLocation>.getAbsolutePath(): String = get().asFile.absolutePath
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the version immediately after the provided version.
|
||||||
|
*
|
||||||
|
* For example, given "1.2.3", this will return "1.2.4".
|
||||||
|
*/
|
||||||
|
fun getNextVersion(version: String): String {
|
||||||
|
// Split a version like x.y.z-SNAPSHOT into x.y.z and -SNAPSHOT
|
||||||
|
val dashIndex = version.indexOf('-')
|
||||||
|
val mainVersion = if (dashIndex < 0) version else version.substring(0, dashIndex)
|
||||||
|
|
||||||
|
// Find the last component in x.y.z and increment it.
|
||||||
|
val lastIndex = mainVersion.lastIndexOf('.')
|
||||||
|
if (lastIndex < 0) throw IllegalArgumentException("Cannot parse version format \"$version\"")
|
||||||
|
val lastVersion = try {
|
||||||
|
mainVersion.substring(lastIndex + 1).toInt()
|
||||||
|
} catch (e: NumberFormatException) {
|
||||||
|
throw IllegalArgumentException("Cannot parse version format \"$version\"", e)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then append all components together.
|
||||||
|
val out = StringBuilder()
|
||||||
|
out.append(version, 0, lastIndex + 1)
|
||||||
|
out.append(lastVersion + 1)
|
||||||
|
if (dashIndex >= 0) out.append(version, dashIndex, version.length)
|
||||||
|
return out.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Capitalise the first letter of the string.
|
||||||
|
*
|
||||||
|
* This is a replacement for the now deprecated [String.capitalize].
|
||||||
|
*/
|
||||||
|
fun String.capitalise(): String {
|
||||||
|
if (isEmpty()) return this
|
||||||
|
val first = this[0]
|
||||||
|
val firstTitle = first.titlecaseChar()
|
||||||
|
return if (first == firstTitle) this else firstTitle + substring(1)
|
||||||
|
}
|
||||||
|
@@ -1,26 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2023 The CC: Tweaked Developers
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
package cc.tweaked.gradle
|
|
||||||
|
|
||||||
import net.minecraftforge.gradle.common.util.RunConfig
|
|
||||||
import net.minecraftforge.gradle.common.util.runs.setRunConfigInternal
|
|
||||||
import org.gradle.api.plugins.JavaPluginExtension
|
|
||||||
import org.gradle.api.tasks.JavaExec
|
|
||||||
import org.gradle.jvm.toolchain.JavaToolchainService
|
|
||||||
import java.nio.file.Files
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set [JavaExec] task to run a given [RunConfig].
|
|
||||||
*/
|
|
||||||
fun JavaExec.setRunConfig(config: RunConfig) {
|
|
||||||
dependsOn("prepareRuns")
|
|
||||||
setRunConfigInternal(project, this, config)
|
|
||||||
doFirst("Create working directory") { Files.createDirectories(workingDir.toPath()) }
|
|
||||||
|
|
||||||
javaLauncher.set(
|
|
||||||
project.extensions.getByType(JavaToolchainService::class.java)
|
|
||||||
.launcherFor(project.extensions.getByType(JavaPluginExtension::class.java).toolchain),
|
|
||||||
)
|
|
||||||
}
|
|
23
buildSrc/src/main/kotlin/cc/tweaked/gradle/IdeaExt.kt
Normal file
23
buildSrc/src/main/kotlin/cc/tweaked/gradle/IdeaExt.kt
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2023 The CC: Tweaked Developers
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
package cc.tweaked.gradle
|
||||||
|
|
||||||
|
import org.jetbrains.gradle.ext.JUnit
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A version of [JUnit] with a functional [className].
|
||||||
|
*
|
||||||
|
* See [#92](https://github.com/JetBrains/gradle-idea-ext-plugin/issues/92).
|
||||||
|
*/
|
||||||
|
open class JUnitExt @Inject constructor(nameParam: String) : JUnit(nameParam) {
|
||||||
|
override fun toMap(): MutableMap<String, *> {
|
||||||
|
val map = HashMap(super.toMap())
|
||||||
|
// Should be "class" instead of "className".
|
||||||
|
// See https://github.com/JetBrains/intellij-community/blob/9ba394021dc73a3926f13d6d6cdf434f9ee7046d/plugins/junit/src/com/intellij/execution/junit/JUnitRunConfigurationImporter.kt#L39
|
||||||
|
map["class"] = className
|
||||||
|
return map
|
||||||
|
}
|
||||||
|
}
|
@@ -25,7 +25,6 @@ import javax.xml.xpath.XPathFactory
|
|||||||
* Would be good to PR some (or all) of these changes upstream at some point.
|
* Would be good to PR some (or all) of these changes upstream at some point.
|
||||||
*
|
*
|
||||||
* @see net.fabricmc.loom.configuration.ide.idea.IdeaSyncTask
|
* @see net.fabricmc.loom.configuration.ide.idea.IdeaSyncTask
|
||||||
* @see net.minecraftforge.gradle.common.util.runs.IntellijRunGenerator
|
|
||||||
*/
|
*/
|
||||||
internal class IdeaRunConfigurations(project: Project) {
|
internal class IdeaRunConfigurations(project: Project) {
|
||||||
private val rootProject = project.rootProject
|
private val rootProject = project.rootProject
|
||||||
@@ -35,22 +34,6 @@ internal class IdeaRunConfigurations(project: Project) {
|
|||||||
private val writer = TransformerFactory.newInstance().newTransformer()
|
private val writer = TransformerFactory.newInstance().newTransformer()
|
||||||
|
|
||||||
private val ideaDir = rootProject.file(".idea/")
|
private val ideaDir = rootProject.file(".idea/")
|
||||||
private val buildDir: Lazy<String?> = lazy {
|
|
||||||
val ideaMisc = ideaDir.resolve("misc.xml")
|
|
||||||
|
|
||||||
try {
|
|
||||||
val doc = Files.newBufferedReader(ideaMisc.toPath()).use {
|
|
||||||
documentBuilder.parse(InputSource(it))
|
|
||||||
}
|
|
||||||
val node =
|
|
||||||
xpath.evaluate("//component[@name=\"ProjectRootManager\"]/output", doc, XPathConstants.NODE) as Node
|
|
||||||
val attr = node.attributes.getNamedItem("url") as Attr
|
|
||||||
attr.value.removePrefix("file://")
|
|
||||||
} catch (e: Exception) {
|
|
||||||
LOGGER.error("Failed to find root directory", e)
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun patch() = synchronized(LOCK) {
|
fun patch() = synchronized(LOCK) {
|
||||||
val runConfigDir = ideaDir.resolve("runConfigurations")
|
val runConfigDir = ideaDir.resolve("runConfigurations")
|
||||||
@@ -58,10 +41,9 @@ internal class IdeaRunConfigurations(project: Project) {
|
|||||||
|
|
||||||
Files.list(runConfigDir.toPath()).use {
|
Files.list(runConfigDir.toPath()).use {
|
||||||
for (configuration in it) {
|
for (configuration in it) {
|
||||||
val filename = configuration.fileName.toString();
|
val filename = configuration.fileName.toString()
|
||||||
when {
|
when {
|
||||||
filename.endsWith("_fabric.xml") -> patchFabric(configuration)
|
filename.endsWith("_fabric.xml") -> patchFabric(configuration)
|
||||||
filename.startsWith("forge_") && filename.endsWith(".xml") -> patchForge(configuration)
|
|
||||||
else -> {}
|
else -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -72,65 +54,6 @@ internal class IdeaRunConfigurations(project: Project) {
|
|||||||
setXml("//configuration", "folderName") { "Fabric" }
|
setXml("//configuration", "folderName") { "Fabric" }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun patchForge(path: Path) = withXml(path) {
|
|
||||||
val configId = path.fileName.toString().removePrefix("forge_").removeSuffix(".xml")
|
|
||||||
val sourceSet = forgeConfigs[configId]
|
|
||||||
if (sourceSet == null) {
|
|
||||||
LOGGER.error("[{}] Cannot map run configuration to a known source set", path)
|
|
||||||
return@withXml
|
|
||||||
}
|
|
||||||
|
|
||||||
setXml("//configuration", "folderName") { "Forge" }
|
|
||||||
setXml("//configuration/module", "name") { "${rootProject.name}.forge.$sourceSet" }
|
|
||||||
|
|
||||||
if (buildDir.value == null) return@withXml
|
|
||||||
setXml("//configuration/envs/env[@name=\"MOD_CLASSES\"]", "value") { classpath ->
|
|
||||||
val classes = classpath!!.split(':')
|
|
||||||
val newClasses = mutableListOf<String>()
|
|
||||||
fun appendUnique(x: String) {
|
|
||||||
if (!newClasses.contains(x)) newClasses.add(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (entry in classes) {
|
|
||||||
if (!entry.contains("/out/")) {
|
|
||||||
appendUnique(entry)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
val match = CLASSPATH_ENTRY.matchEntire(entry)
|
|
||||||
if (match != null) {
|
|
||||||
val modId = match.groups["modId"]!!.value
|
|
||||||
val proj = match.groups["proj"]!!.value
|
|
||||||
var component = match.groups["component"]!!.value
|
|
||||||
if (component == "production") component = "main"
|
|
||||||
|
|
||||||
appendUnique(forgeModEntry(modId, proj, component))
|
|
||||||
} else {
|
|
||||||
LOGGER.warn("[{}] Unknown classpath entry {}", path, entry)
|
|
||||||
appendUnique(entry)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure common code is on the classpath
|
|
||||||
for (proj in listOf("common", "common-api")) {
|
|
||||||
for (component in listOf("main", "client")) {
|
|
||||||
appendUnique(forgeModEntry("computercraft", proj, component))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newClasses.any { it.startsWith("cctest%%") }) {
|
|
||||||
appendUnique(forgeModEntry("cctest", "core", "testFixtures"))
|
|
||||||
appendUnique(forgeModEntry("cctest", "common", "testFixtures"))
|
|
||||||
appendUnique(forgeModEntry("cctest", "common", "testMod"))
|
|
||||||
}
|
|
||||||
|
|
||||||
newClasses.joinToString(":")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun forgeModEntry(mod: String, project: String, component: String) =
|
|
||||||
"$mod%%${buildDir.value}/production/${rootProject.name}.$project.$component"
|
|
||||||
|
|
||||||
private fun LocatedDocument.setXml(xpath: String, attribute: String, value: (String?) -> String) {
|
private fun LocatedDocument.setXml(xpath: String, attribute: String, value: (String?) -> String) {
|
||||||
val node = this@IdeaRunConfigurations.xpath.evaluate(xpath, document, XPathConstants.NODE) as Node?
|
val node = this@IdeaRunConfigurations.xpath.evaluate(xpath, document, XPathConstants.NODE) as Node?
|
||||||
if (node == null) {
|
if (node == null) {
|
||||||
@@ -159,16 +82,5 @@ internal class IdeaRunConfigurations(project: Project) {
|
|||||||
companion object {
|
companion object {
|
||||||
private val LOGGER = Logging.getLogger(IdeaRunConfigurations::class.java)
|
private val LOGGER = Logging.getLogger(IdeaRunConfigurations::class.java)
|
||||||
private val LOCK = Any()
|
private val LOCK = Any()
|
||||||
|
|
||||||
private val CLASSPATH_ENTRY =
|
|
||||||
Regex("(?<modId>[a-z]+)%%\\\$PROJECT_DIR\\\$/projects/(?<proj>[a-z-]+)/out/(?<component>\\w+)/(?<type>[a-z]+)\$")
|
|
||||||
|
|
||||||
private val forgeConfigs = mapOf(
|
|
||||||
"runClient" to "client",
|
|
||||||
"runData" to "main",
|
|
||||||
"runGameTestServer" to "testMod",
|
|
||||||
"runServer" to "main",
|
|
||||||
"runTestClient" to "testMod",
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,66 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2022 The CC: Tweaked Developers
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
package cc.tweaked.gradle
|
|
||||||
|
|
||||||
import org.gradle.api.artifacts.Dependency
|
|
||||||
import org.gradle.api.artifacts.MinimalExternalModuleDependency
|
|
||||||
import org.gradle.api.publish.maven.MavenPublication
|
|
||||||
import org.gradle.api.specs.Spec
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A dependency in a POM file.
|
|
||||||
*/
|
|
||||||
data class MavenDependency(val groupId: String?, val artifactId: String?, val version: String?, val scope: String?)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A spec specifying which dependencies to include/exclude.
|
|
||||||
*/
|
|
||||||
class MavenDependencySpec {
|
|
||||||
private val excludeSpecs = mutableListOf<Spec<MavenDependency>>()
|
|
||||||
|
|
||||||
fun exclude(spec: Spec<MavenDependency>) {
|
|
||||||
excludeSpecs.add(spec)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun exclude(dep: Dependency) {
|
|
||||||
exclude {
|
|
||||||
(dep.group.isNullOrEmpty() || dep.group == it.groupId) &&
|
|
||||||
(dep.name.isNullOrEmpty() || dep.name == it.artifactId) &&
|
|
||||||
(dep.version.isNullOrEmpty() || dep.version == it.version)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun exclude(dep: MinimalExternalModuleDependency) {
|
|
||||||
exclude {
|
|
||||||
dep.module.group == it.groupId && dep.module.name == it.artifactId
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isIncluded(dep: MavenDependency) = !excludeSpecs.any { it.isSatisfiedBy(dep) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configure dependencies present in this publication's POM file.
|
|
||||||
*
|
|
||||||
* While this approach is very ugly, it's the easiest way to handle it!
|
|
||||||
*/
|
|
||||||
fun MavenPublication.mavenDependencies(action: MavenDependencySpec.() -> Unit) {
|
|
||||||
val spec = MavenDependencySpec()
|
|
||||||
action(spec)
|
|
||||||
|
|
||||||
pom.withXml {
|
|
||||||
val dependencies = XmlUtil.findChild(asNode(), "dependencies") ?: return@withXml
|
|
||||||
dependencies.children().map { it as groovy.util.Node }.forEach {
|
|
||||||
val dep = MavenDependency(
|
|
||||||
groupId = XmlUtil.findChild(it, "groupId")?.text(),
|
|
||||||
artifactId = XmlUtil.findChild(it, "artifactId")?.text(),
|
|
||||||
version = XmlUtil.findChild(it, "version")?.text(),
|
|
||||||
scope = XmlUtil.findChild(it, "scope")?.text(),
|
|
||||||
)
|
|
||||||
|
|
||||||
if (!spec.isIncluded(dep)) it.parent().remove(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
120
buildSrc/src/main/kotlin/cc/tweaked/gradle/MergeTrees.kt
Normal file
120
buildSrc/src/main/kotlin/cc/tweaked/gradle/MergeTrees.kt
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
package cc.tweaked.gradle
|
||||||
|
|
||||||
|
import cc.tweaked.vanillaextract.core.util.MoreFiles
|
||||||
|
import org.gradle.api.Action
|
||||||
|
import org.gradle.api.DefaultTask
|
||||||
|
import org.gradle.api.GradleException
|
||||||
|
import org.gradle.api.file.*
|
||||||
|
import org.gradle.api.model.ObjectFactory
|
||||||
|
import org.gradle.api.provider.ListProperty
|
||||||
|
import org.gradle.api.tasks.*
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merge common files across multiple directories into one destination directory.
|
||||||
|
*
|
||||||
|
* This is intended for merging the generated resources from the Forge and Fabric projects. Files common between the two
|
||||||
|
* are written to the global [output] directory, while distinct files are written to the per-source
|
||||||
|
* [MergeTrees.Source.output] directory.
|
||||||
|
*/
|
||||||
|
abstract class MergeTrees : DefaultTask() {
|
||||||
|
/**
|
||||||
|
* A source directory to read from.
|
||||||
|
*/
|
||||||
|
interface Source {
|
||||||
|
/**
|
||||||
|
* The folder contianing all input files.
|
||||||
|
*/
|
||||||
|
@get:InputFiles
|
||||||
|
@get:PathSensitive(PathSensitivity.RELATIVE)
|
||||||
|
val input: ConfigurableFileTree
|
||||||
|
|
||||||
|
fun input(configure: Action<ConfigurableFileTree>) {
|
||||||
|
configure.execute(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The folder to write files unique to this folder to.
|
||||||
|
*/
|
||||||
|
@get:OutputDirectory
|
||||||
|
val output: DirectoryProperty
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The list of sources.
|
||||||
|
*/
|
||||||
|
@get:Nested
|
||||||
|
abstract val sources: ListProperty<Source>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add and configure a new source.
|
||||||
|
*/
|
||||||
|
fun source(configure: Action<Source>) {
|
||||||
|
val instance = objectFactory.newInstance(Source::class.java)
|
||||||
|
configure.execute(instance)
|
||||||
|
instance.output.disallowChanges()
|
||||||
|
sources.add(instance)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The directory to write common files to.
|
||||||
|
*/
|
||||||
|
@get:OutputDirectory
|
||||||
|
abstract val output: DirectoryProperty
|
||||||
|
|
||||||
|
@get:Inject
|
||||||
|
protected abstract val objectFactory: ObjectFactory
|
||||||
|
|
||||||
|
@get:Inject
|
||||||
|
protected abstract val fsOperations: FileSystemOperations
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
fun run() {
|
||||||
|
val sources = this.sources.get()
|
||||||
|
if (sources.isEmpty()) throw GradleException("Cannot have an empty list of sources")
|
||||||
|
|
||||||
|
val files = mutableMapOf<String, SharedFile>()
|
||||||
|
for (source in sources) {
|
||||||
|
source.input.visit(
|
||||||
|
object : FileVisitor {
|
||||||
|
override fun visitDir(dirDetails: FileVisitDetails) = Unit
|
||||||
|
override fun visitFile(fileDetails: FileVisitDetails) {
|
||||||
|
val path = fileDetails.file.toRelativeString(source.input.dir)
|
||||||
|
val hash = MoreFiles.computeSha1(fileDetails.file.toPath())
|
||||||
|
|
||||||
|
val existing = files[path]
|
||||||
|
if (existing == null) {
|
||||||
|
files[path] = SharedFile(hash, 1)
|
||||||
|
} else if (existing.hash == hash) {
|
||||||
|
existing.found++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val sharedFiles = files.entries.asSequence().filter { (_, v) -> v.found == sources.size }.map { (k, _) -> k }.toList()
|
||||||
|
|
||||||
|
// Copy shared files to the common directory
|
||||||
|
fsOperations.sync {
|
||||||
|
from(sources[0].input)
|
||||||
|
into(output)
|
||||||
|
include(sharedFiles)
|
||||||
|
}
|
||||||
|
|
||||||
|
// And all other files to their per-source directory
|
||||||
|
for (source in sources) {
|
||||||
|
fsOperations.sync {
|
||||||
|
from(source.input)
|
||||||
|
into(source.output)
|
||||||
|
exclude(sharedFiles)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SharedFile(val hash: String, var found: Int)
|
||||||
|
}
|
@@ -4,23 +4,17 @@
|
|||||||
|
|
||||||
package cc.tweaked.gradle
|
package cc.tweaked.gradle
|
||||||
|
|
||||||
|
import cc.tweaked.vanillaextract.configurations.Capabilities
|
||||||
|
import cc.tweaked.vanillaextract.configurations.MinecraftSetup
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.artifacts.Configuration
|
|
||||||
import org.gradle.api.artifacts.ModuleDependency
|
import org.gradle.api.artifacts.ModuleDependency
|
||||||
import org.gradle.api.artifacts.dsl.DependencyHandler
|
import org.gradle.api.artifacts.dsl.DependencyHandler
|
||||||
import org.gradle.api.attributes.Bundling
|
|
||||||
import org.gradle.api.attributes.Category
|
|
||||||
import org.gradle.api.attributes.LibraryElements
|
|
||||||
import org.gradle.api.attributes.Usage
|
|
||||||
import org.gradle.api.attributes.java.TargetJvmVersion
|
|
||||||
import org.gradle.api.capabilities.Capability
|
|
||||||
import org.gradle.api.plugins.BasePlugin
|
import org.gradle.api.plugins.BasePlugin
|
||||||
import org.gradle.api.plugins.JavaPluginExtension
|
import org.gradle.api.plugins.JavaPluginExtension
|
||||||
import org.gradle.api.tasks.SourceSet
|
import org.gradle.api.tasks.SourceSet
|
||||||
import org.gradle.api.tasks.bundling.Jar
|
import org.gradle.api.tasks.bundling.Jar
|
||||||
import org.gradle.api.tasks.javadoc.Javadoc
|
import org.gradle.api.tasks.javadoc.Javadoc
|
||||||
import org.gradle.kotlin.dsl.get
|
import org.gradle.kotlin.dsl.get
|
||||||
import org.gradle.kotlin.dsl.named
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This sets up a separate client-only source set, and extends that and the main/common source set with additional
|
* This sets up a separate client-only source set, and extends that and the main/common source set with additional
|
||||||
@@ -30,7 +24,6 @@ class MinecraftConfigurations private constructor(private val project: Project)
|
|||||||
private val java = project.extensions.getByType(JavaPluginExtension::class.java)
|
private val java = project.extensions.getByType(JavaPluginExtension::class.java)
|
||||||
private val sourceSets = java.sourceSets
|
private val sourceSets = java.sourceSets
|
||||||
private val configurations = project.configurations
|
private val configurations = project.configurations
|
||||||
private val objects = project.objects
|
|
||||||
|
|
||||||
private val main = sourceSets[SourceSet.MAIN_SOURCE_SET_NAME]
|
private val main = sourceSets[SourceSet.MAIN_SOURCE_SET_NAME]
|
||||||
private val test = sourceSets[SourceSet.TEST_SOURCE_SET_NAME]
|
private val test = sourceSets[SourceSet.TEST_SOURCE_SET_NAME]
|
||||||
@@ -43,13 +36,7 @@ class MinecraftConfigurations private constructor(private val project: Project)
|
|||||||
val client = sourceSets.maybeCreate("client")
|
val client = sourceSets.maybeCreate("client")
|
||||||
|
|
||||||
// Ensure the client classpaths behave the same as the main ones.
|
// Ensure the client classpaths behave the same as the main ones.
|
||||||
configurations.named(client.compileClasspathConfigurationName) {
|
consistentWithMain(client)
|
||||||
shouldResolveConsistentlyWith(configurations[main.compileClasspathConfigurationName])
|
|
||||||
}
|
|
||||||
|
|
||||||
configurations.named(client.runtimeClasspathConfigurationName) {
|
|
||||||
shouldResolveConsistentlyWith(configurations[main.runtimeClasspathConfigurationName])
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set up an API configuration for clients (to ensure it's consistent with the main source set).
|
// Set up an API configuration for clients (to ensure it's consistent with the main source set).
|
||||||
val clientApi = configurations.maybeCreate(client.apiConfigurationName).apply {
|
val clientApi = configurations.maybeCreate(client.apiConfigurationName).apply {
|
||||||
@@ -59,31 +46,13 @@ class MinecraftConfigurations private constructor(private val project: Project)
|
|||||||
}
|
}
|
||||||
configurations.named(client.implementationConfigurationName) { extendsFrom(clientApi) }
|
configurations.named(client.implementationConfigurationName) { extendsFrom(clientApi) }
|
||||||
|
|
||||||
/*
|
|
||||||
Now add outgoing variants for the main and common source sets that we can consume downstream. This is possibly
|
|
||||||
the worst way to do things, but unfortunately the alternatives don't actually work very well:
|
|
||||||
|
|
||||||
- Just using source set outputs: This means dependencies don't propagate, which means when :fabric depends
|
|
||||||
on :fabric-api, we don't inherit the fake :common-api in IDEA.
|
|
||||||
|
|
||||||
- Having separate common/main jars: Nice in principle, but unfortunately Forge needs a separate deobf jar
|
|
||||||
task (as the original jar is obfuscated), and IDEA is not able to map its output back to a source set.
|
|
||||||
|
|
||||||
This works for now, but is incredibly brittle. It's part of the reason we can't use testFixtures inside our
|
|
||||||
MC projects, as that adds a project(self) -> test dependency, which would pull in the jar instead.
|
|
||||||
|
|
||||||
Note we register a fake client jar here. It's not actually needed, but is there to make sure IDEA has
|
|
||||||
a way to tell that client classes are needed at runtime.
|
|
||||||
|
|
||||||
I'm so sorry, deeply aware how cursed this is.
|
|
||||||
*/
|
|
||||||
setupOutgoing(main, "CommonOnly")
|
|
||||||
project.tasks.register(client.jarTaskName, Jar::class.java) {
|
project.tasks.register(client.jarTaskName, Jar::class.java) {
|
||||||
description = "An empty jar standing in for the client classes."
|
description = "An empty jar standing in for the client classes."
|
||||||
group = BasePlugin.BUILD_GROUP
|
group = BasePlugin.BUILD_GROUP
|
||||||
archiveClassifier.set("client")
|
archiveClassifier.set("client")
|
||||||
}
|
}
|
||||||
setupOutgoing(client)
|
|
||||||
|
MinecraftSetup(project).setupOutgoingConfigurations()
|
||||||
|
|
||||||
// Reset the client classpath (Loom configures it slightly differently to this) and add a main -> client
|
// Reset the client classpath (Loom configures it slightly differently to this) and add a main -> client
|
||||||
// dependency. Here we /can/ use source set outputs as we add transitive deps by patching the classpath. Nasty,
|
// dependency. Here we /can/ use source set outputs as we add transitive deps by patching the classpath. Nasty,
|
||||||
@@ -106,88 +75,70 @@ class MinecraftConfigurations private constructor(private val project: Project)
|
|||||||
project.tasks.named("jar", Jar::class.java) { from(client.output) }
|
project.tasks.named("jar", Jar::class.java) { from(client.output) }
|
||||||
project.tasks.named("sourcesJar", Jar::class.java) { from(client.allSource) }
|
project.tasks.named("sourcesJar", Jar::class.java) { from(client.allSource) }
|
||||||
|
|
||||||
|
setupBasic()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun consistentWithMain(sourceSet: SourceSet) {
|
||||||
|
configurations.named(sourceSet.compileClasspathConfigurationName) {
|
||||||
|
shouldResolveConsistentlyWith(configurations[main.compileClasspathConfigurationName])
|
||||||
|
}
|
||||||
|
|
||||||
|
configurations.named(sourceSet.runtimeClasspathConfigurationName) {
|
||||||
|
shouldResolveConsistentlyWith(configurations[main.runtimeClasspathConfigurationName])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupBasic() {
|
||||||
|
val client = sourceSets["client"]
|
||||||
|
|
||||||
project.extensions.configure(CCTweakedExtension::class.java) {
|
project.extensions.configure(CCTweakedExtension::class.java) {
|
||||||
sourceDirectories.add(SourceSetReference.internal(client))
|
sourceDirectories.add(SourceSetReference.internal(client))
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private fun setupOutgoing(sourceSet: SourceSet, suffix: String = "") {
|
// Register a task to check there are no conflicts with the core project.
|
||||||
setupOutgoing("${sourceSet.apiElementsConfigurationName}$suffix", sourceSet, objects.named(Usage.JAVA_API)) {
|
val checkDependencyConsistency =
|
||||||
description = "API elements for ${sourceSet.name}"
|
project.tasks.register("checkDependencyConsistency", DependencyCheck::class.java) {
|
||||||
extendsFrom(configurations[sourceSet.apiConfigurationName])
|
// We need to check both the main and client classpath *configurations*, as the actual configuration
|
||||||
}
|
configuration(configurations.named(main.runtimeClasspathConfigurationName))
|
||||||
|
configuration(configurations.named(client.runtimeClasspathConfigurationName))
|
||||||
setupOutgoing("${sourceSet.runtimeElementsConfigurationName}$suffix", sourceSet, objects.named(Usage.JAVA_RUNTIME)) {
|
}
|
||||||
description = "Runtime elements for ${sourceSet.name}"
|
project.tasks.named("check") { dependsOn(checkDependencyConsistency) }
|
||||||
extendsFrom(configurations[sourceSet.implementationConfigurationName], configurations[sourceSet.runtimeOnlyConfigurationName])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set up an outgoing configuration for a specific source set. We set an additional "main" or "client" capability
|
* Create a new configuration that pulls in the main and client classes from the mod.
|
||||||
* (depending on the source set name) which allows downstream projects to consume them separately (see
|
|
||||||
* [DependencyHandler.commonClasses] and [DependencyHandler.clientClasses]).
|
|
||||||
*/
|
*/
|
||||||
private fun setupOutgoing(name: String, sourceSet: SourceSet, usage: Usage, configure: Configuration.() -> Unit) {
|
private fun createDerivedConfiguration(name: String) {
|
||||||
configurations.register(name) {
|
val client = sourceSets["client"]
|
||||||
isVisible = false
|
val sourceSet = sourceSets.create(name)
|
||||||
isCanBeConsumed = true
|
sourceSet.compileClasspath += main.compileClasspath + client.compileClasspath
|
||||||
isCanBeResolved = false
|
sourceSet.runtimeClasspath += main.runtimeClasspath + client.runtimeClasspath
|
||||||
|
consistentWithMain(sourceSet)
|
||||||
configure(this)
|
project.dependencies.add(sourceSet.implementationConfigurationName, main.output)
|
||||||
|
project.dependencies.add(sourceSet.implementationConfigurationName, client.output)
|
||||||
attributes {
|
|
||||||
attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.LIBRARY))
|
|
||||||
attribute(Usage.USAGE_ATTRIBUTE, usage)
|
|
||||||
attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling.EXTERNAL))
|
|
||||||
attributeProvider(
|
|
||||||
TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE,
|
|
||||||
java.toolchain.languageVersion.map { it.asInt() },
|
|
||||||
)
|
|
||||||
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements.JAR))
|
|
||||||
}
|
|
||||||
|
|
||||||
outgoing {
|
|
||||||
capability(BasicOutgoingCapability(project, sourceSet.name))
|
|
||||||
|
|
||||||
// We have two outgoing variants here: the original jar and the classes.
|
|
||||||
artifact(project.tasks.named(sourceSet.jarTaskName))
|
|
||||||
|
|
||||||
variants.create("classes") {
|
|
||||||
attributes.attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements.CLASSES))
|
|
||||||
sourceSet.output.classesDirs.forEach { artifact(it) { builtBy(sourceSet.output) } }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
const val DATAGEN = "datagen"
|
||||||
|
const val EXAMPLES = "examples"
|
||||||
|
const val TEST_MOD = "testMod"
|
||||||
|
|
||||||
|
fun setupBasic(project: Project) {
|
||||||
|
MinecraftConfigurations(project).setupBasic()
|
||||||
|
}
|
||||||
|
|
||||||
fun setup(project: Project) {
|
fun setup(project: Project) {
|
||||||
MinecraftConfigurations(project).setup()
|
MinecraftConfigurations(project).setup()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun createDerivedConfiguration(project: Project, name: String) {
|
||||||
|
MinecraftConfigurations(project).createDerivedConfiguration(name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class BasicIncomingCapability(private val module: ModuleDependency, private val name: String) : Capability {
|
fun DependencyHandler.clientClasses(notation: Any): ModuleDependency =
|
||||||
override fun getGroup(): String = module.group!!
|
Capabilities.clientClasses(create(notation) as ModuleDependency)
|
||||||
override fun getName(): String = "${module.name}-$name"
|
|
||||||
override fun getVersion(): String? = null
|
|
||||||
}
|
|
||||||
|
|
||||||
private class BasicOutgoingCapability(private val project: Project, private val name: String) : Capability {
|
fun DependencyHandler.commonClasses(notation: Any): ModuleDependency =
|
||||||
override fun getGroup(): String = project.group.toString()
|
Capabilities.commonClasses(create(notation) as ModuleDependency)
|
||||||
override fun getName(): String = "${project.name}-$name"
|
|
||||||
override fun getVersion(): String = project.version.toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun DependencyHandler.clientClasses(notation: Any): ModuleDependency {
|
|
||||||
val dep = create(notation) as ModuleDependency
|
|
||||||
dep.capabilities { requireCapability(BasicIncomingCapability(dep, "client")) }
|
|
||||||
return dep
|
|
||||||
}
|
|
||||||
|
|
||||||
fun DependencyHandler.commonClasses(notation: Any): ModuleDependency {
|
|
||||||
val dep = create(notation) as ModuleDependency
|
|
||||||
dep.capabilities { requireCapability(BasicIncomingCapability(dep, "main")) }
|
|
||||||
return dep
|
|
||||||
}
|
|
||||||
|
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
package cc.tweaked.gradle
|
package cc.tweaked.gradle
|
||||||
|
|
||||||
import net.minecraftforge.gradle.common.util.RunConfig
|
import net.neoforged.moddevgradle.internal.RunGameTask
|
||||||
import org.gradle.api.GradleException
|
import org.gradle.api.GradleException
|
||||||
import org.gradle.api.file.FileSystemOperations
|
import org.gradle.api.file.FileSystemOperations
|
||||||
import org.gradle.api.invocation.Gradle
|
import org.gradle.api.invocation.Gradle
|
||||||
@@ -19,6 +19,7 @@ import java.nio.file.Files
|
|||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import java.util.function.Supplier
|
import java.util.function.Supplier
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
import kotlin.collections.set
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -58,18 +59,26 @@ abstract class ClientJavaExec : JavaExec() {
|
|||||||
if (!clientDebug) systemProperty("cctest.client", "")
|
if (!clientDebug) systemProperty("cctest.client", "")
|
||||||
if (renderdoc) environment("LD_PRELOAD", "/usr/lib/librenderdoc.so")
|
if (renderdoc) environment("LD_PRELOAD", "/usr/lib/librenderdoc.so")
|
||||||
systemProperty("cctest.gametest-report", testResults.get().asFile.absoluteFile)
|
systemProperty("cctest.gametest-report", testResults.get().asFile.absoluteFile)
|
||||||
workingDir(project.buildDir.resolve("gametest").resolve(name))
|
workingDir(project.layout.buildDirectory.dir("gametest/$name"))
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
setTestProperties()
|
setTestProperties()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun copyFromForge(path: String) = copyFromForge(project.tasks.getByName(path, RunGameTask::class))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set this task to run a given [RunConfig].
|
* Set this task to run a given [RunGameTask].
|
||||||
*/
|
*/
|
||||||
fun setRunConfig(config: RunConfig) {
|
fun copyFromForge(task: RunGameTask) {
|
||||||
(this as JavaExec).setRunConfig(config)
|
copyFrom(task)
|
||||||
|
|
||||||
|
// Eagerly evaluate the behaviour of RunGameTask.exec
|
||||||
|
environment.putAll(task.environmentProperty.get())
|
||||||
|
classpath(task.classpathProvider)
|
||||||
|
workingDir = task.gameDirectory.get().asFile
|
||||||
|
|
||||||
setTestProperties() // setRunConfig may clobber some properties, ensure everything is set.
|
setTestProperties() // setRunConfig may clobber some properties, ensure everything is set.
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,6 +126,23 @@ abstract class ClientJavaExec : JavaExec() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure Iris to use Complementary Shaders.
|
||||||
|
*/
|
||||||
|
fun withComplementaryShaders() {
|
||||||
|
val cct = project.extensions.getByType(CCTweakedExtension::class.java)
|
||||||
|
|
||||||
|
withFileFrom(workingDir.resolve("shaderpacks/ComplementaryShaders_v4.6.zip")) {
|
||||||
|
cct.downloadFile("Complementary Shaders", "https://edge.forgecdn.net/files/3951/170/ComplementaryShaders_v4.6.zip")
|
||||||
|
}
|
||||||
|
withFileContents(workingDir.resolve("config/iris.properties")) {
|
||||||
|
"""
|
||||||
|
enableShaders=true
|
||||||
|
shaderPack=ComplementaryShaders_v4.6.zip
|
||||||
|
""".trimIndent()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TaskAction
|
@TaskAction
|
||||||
override fun exec() {
|
override fun exec() {
|
||||||
Files.createDirectories(workingDir.toPath())
|
Files.createDirectories(workingDir.toPath())
|
||||||
|
@@ -11,7 +11,9 @@ import org.gradle.api.file.Directory
|
|||||||
import org.gradle.api.file.DirectoryProperty
|
import org.gradle.api.file.DirectoryProperty
|
||||||
import org.gradle.api.provider.Provider
|
import org.gradle.api.provider.Provider
|
||||||
import org.gradle.api.tasks.*
|
import org.gradle.api.tasks.*
|
||||||
|
import org.gradle.process.ExecOperations
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
class NodePlugin : Plugin<Project> {
|
class NodePlugin : Plugin<Project> {
|
||||||
override fun apply(project: Project) {
|
override fun apply(project: Project) {
|
||||||
@@ -43,10 +45,13 @@ abstract class NpmInstall : DefaultTask() {
|
|||||||
@get:OutputDirectory
|
@get:OutputDirectory
|
||||||
val nodeModules: Provider<Directory> = projectRoot.dir("node_modules")
|
val nodeModules: Provider<Directory> = projectRoot.dir("node_modules")
|
||||||
|
|
||||||
|
@get:Inject
|
||||||
|
protected abstract val execOperations: ExecOperations
|
||||||
|
|
||||||
@TaskAction
|
@TaskAction
|
||||||
fun install() {
|
fun install() {
|
||||||
project.exec {
|
execOperations.exec {
|
||||||
commandLine("npm", "ci")
|
commandLine(ProcessHelpers.getExecutable("npm"), "ci")
|
||||||
workingDir = projectRoot.get().asFile
|
workingDir = projectRoot.get().asFile
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -59,6 +64,6 @@ abstract class NpmInstall : DefaultTask() {
|
|||||||
abstract class NpxExecToDir : ExecToDir() {
|
abstract class NpxExecToDir : ExecToDir() {
|
||||||
init {
|
init {
|
||||||
dependsOn(NpmInstall.TASK_NAME)
|
dependsOn(NpmInstall.TASK_NAME)
|
||||||
executable = "npx"
|
executable = ProcessHelpers.getExecutable("npx")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,48 +4,36 @@
|
|||||||
|
|
||||||
package cc.tweaked.gradle
|
package cc.tweaked.gradle
|
||||||
|
|
||||||
import org.codehaus.groovy.runtime.ProcessGroovyMethods
|
|
||||||
import org.gradle.api.GradleException
|
import org.gradle.api.GradleException
|
||||||
import java.io.BufferedReader
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.InputStreamReader
|
|
||||||
|
|
||||||
internal object ProcessHelpers {
|
internal object ProcessHelpers {
|
||||||
fun startProcess(vararg command: String): Process {
|
|
||||||
// Something randomly passes in "GIT_DIR=" as an environment variable which clobbers everything else. Don't
|
|
||||||
// inherit the environment array!
|
|
||||||
return ProcessBuilder()
|
|
||||||
.command(*command)
|
|
||||||
.redirectError(ProcessBuilder.Redirect.INHERIT)
|
|
||||||
.also { it.environment().clear() }
|
|
||||||
.start()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun captureOut(vararg command: String): String {
|
|
||||||
val process = startProcess(*command)
|
|
||||||
process.outputStream.close()
|
|
||||||
|
|
||||||
val result = ProcessGroovyMethods.getText(process)
|
|
||||||
process.waitForOrThrow("Failed to run command")
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
fun captureLines(vararg command: String): List<String> {
|
|
||||||
val process = startProcess(*command)
|
|
||||||
process.outputStream.close()
|
|
||||||
|
|
||||||
val out = BufferedReader(InputStreamReader(process.inputStream)).use { reader ->
|
|
||||||
reader.lines().filter { it.isNotEmpty() }.toList()
|
|
||||||
}
|
|
||||||
ProcessGroovyMethods.closeStreams(process)
|
|
||||||
process.waitForOrThrow("Failed to run command")
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onPath(name: String): Boolean {
|
fun onPath(name: String): Boolean {
|
||||||
val path = System.getenv("PATH") ?: return false
|
val path = System.getenv("PATH") ?: return false
|
||||||
return path.splitToSequence(File.pathSeparator).any { File(it, name).exists() }
|
return path.splitToSequence(File.pathSeparator).any { File(it, name).exists() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search for an executable on the `PATH` if required.
|
||||||
|
*
|
||||||
|
* [Process]/[ProcessBuilder] does not handle all executable file extensions on Windows (such as `.com). When on
|
||||||
|
* Windows, this function searches `PATH` and `PATHEXT` for an executable matching [name].
|
||||||
|
*/
|
||||||
|
fun getExecutable(name: String): String {
|
||||||
|
if (!System.getProperty("os.name").lowercase().contains("windows")) return name
|
||||||
|
|
||||||
|
val path = (System.getenv("PATH") ?: return name).split(File.pathSeparator)
|
||||||
|
val pathExt = (System.getenv("PATHEXT") ?: return name).split(File.pathSeparator)
|
||||||
|
|
||||||
|
for (pathEntry in path) {
|
||||||
|
for (ext in pathExt) {
|
||||||
|
val resolved = File(pathEntry, name + ext)
|
||||||
|
if (resolved.exists()) return resolved.getAbsolutePath()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return name
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun Process.waitForOrThrow(message: String) {
|
internal fun Process.waitForOrThrow(message: String) {
|
||||||
|
@@ -1,16 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2022 The CC: Tweaked Developers
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
package cc.tweaked.gradle
|
|
||||||
|
|
||||||
import groovy.util.Node
|
|
||||||
import groovy.util.NodeList
|
|
||||||
|
|
||||||
object XmlUtil {
|
|
||||||
fun findChild(node: Node, name: String): Node? = when (val child = node.get(name)) {
|
|
||||||
is Node -> child
|
|
||||||
is NodeList -> child.singleOrNull() as Node?
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,51 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2023 The CC: Tweaked Developers
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
package net.minecraftforge.gradle.common.util.runs
|
|
||||||
|
|
||||||
import net.minecraftforge.gradle.common.util.RunConfig
|
|
||||||
import org.gradle.api.Project
|
|
||||||
import org.gradle.process.CommandLineArgumentProvider
|
|
||||||
import org.gradle.process.JavaExecSpec
|
|
||||||
import java.io.File
|
|
||||||
import java.util.function.Supplier
|
|
||||||
import java.util.stream.Collectors
|
|
||||||
import java.util.stream.Stream
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set up a [JavaExecSpec] to execute a [RunConfig].
|
|
||||||
*
|
|
||||||
* [MinecraftRunTask] sets up all its properties when the task is executed, rather than when configured. As such, it's
|
|
||||||
* not possible to use [cc.tweaked.gradle.copyToFull] like we do for Fabric. Instead, we set up the task manually.
|
|
||||||
*
|
|
||||||
* Unfortunately most of the functionality we need is package-private, and so we have to put our code into the package.
|
|
||||||
*/
|
|
||||||
internal fun setRunConfigInternal(project: Project, spec: JavaExecSpec, config: RunConfig) {
|
|
||||||
spec.workingDir = File(config.workingDirectory)
|
|
||||||
|
|
||||||
spec.mainClass.set(config.main)
|
|
||||||
for (source in config.allSources) spec.classpath(source.runtimeClasspath)
|
|
||||||
|
|
||||||
val originalTask = project.tasks.named(config.taskName, MinecraftRunTask::class.java)
|
|
||||||
|
|
||||||
// Add argument and JVM argument via providers, to be as lazy as possible with fetching artifacts.
|
|
||||||
val lazyTokens = RunConfigGenerator.configureTokensLazy(
|
|
||||||
project, config, RunConfigGenerator.mapModClassesToGradle(project, config),
|
|
||||||
originalTask.get().minecraftArtifacts,
|
|
||||||
originalTask.get().runtimeClasspathArtifacts,
|
|
||||||
)
|
|
||||||
spec.argumentProviders.add(
|
|
||||||
CommandLineArgumentProvider {
|
|
||||||
RunConfigGenerator.getArgsStream(config, lazyTokens, false).toList()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
spec.jvmArgumentProviders.add(
|
|
||||||
CommandLineArgumentProvider {
|
|
||||||
(if (config.isClient) config.jvmArgs + originalTask.get().additionalClientArgs.get() else config.jvmArgs).map { config.replace(lazyTokens, it) } +
|
|
||||||
config.properties.map { (k, v) -> "-D${k}=${config.replace(lazyTokens, v)}" }
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
for ((key, value) in config.environment) spec.environment(key, config.replace(lazyTokens, value))
|
|
||||||
}
|
|
@@ -13,8 +13,21 @@ SPDX-License-Identifier: MPL-2.0
|
|||||||
<property name="tabWidth" value="4"/>
|
<property name="tabWidth" value="4"/>
|
||||||
<property name="charset" value="UTF-8" />
|
<property name="charset" value="UTF-8" />
|
||||||
|
|
||||||
|
<module name="BeforeExecutionExclusionFileFilter">
|
||||||
|
<property name="fileNamePattern" value="module\-info\.java$"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
<module name="SuppressionFilter">
|
<module name="SuppressionFilter">
|
||||||
<property name="file" value="${config_loc}/suppressions.xml" />
|
<property name="file" value="${config_loc}/suppressions.xml" />
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Checkstyle doesn't support @snippet (https://github.com/checkstyle/checkstyle/issues/11455),
|
||||||
|
so suppress warnings nearby
|
||||||
|
-->
|
||||||
|
<module name="SuppressWithNearbyTextFilter">
|
||||||
|
<property name="nearbyTextPattern" value="@snippet" />
|
||||||
|
<property name="lineRange" value="20" />
|
||||||
</module>
|
</module>
|
||||||
|
|
||||||
<module name="BeforeExecutionExclusionFileFilter">
|
<module name="BeforeExecutionExclusionFileFilter">
|
||||||
@@ -88,7 +101,10 @@ SPDX-License-Identifier: MPL-2.0
|
|||||||
<module name="InvalidJavadocPosition" />
|
<module name="InvalidJavadocPosition" />
|
||||||
<module name="JavadocBlockTagLocation" />
|
<module name="JavadocBlockTagLocation" />
|
||||||
<module name="JavadocMethod"/>
|
<module name="JavadocMethod"/>
|
||||||
<module name="JavadocType"/>
|
<module name="JavadocType">
|
||||||
|
<!-- Seems to complain about @hidden!? -->
|
||||||
|
<property name="allowUnknownTags" value="true" />
|
||||||
|
</module>
|
||||||
<module name="JavadocStyle">
|
<module name="JavadocStyle">
|
||||||
<property name="checkHtml" value="false" />
|
<property name="checkHtml" value="false" />
|
||||||
</module>
|
</module>
|
||||||
@@ -112,17 +128,19 @@ SPDX-License-Identifier: MPL-2.0
|
|||||||
<module name="LambdaParameterName" />
|
<module name="LambdaParameterName" />
|
||||||
<module name="LocalFinalVariableName" />
|
<module name="LocalFinalVariableName" />
|
||||||
<module name="LocalVariableName" />
|
<module name="LocalVariableName" />
|
||||||
<module name="MemberName" />
|
<module name="MemberName">
|
||||||
|
<property name="format" value="^\$?[a-z][a-zA-Z0-9]*$" />
|
||||||
|
</module>
|
||||||
<module name="MethodName">
|
<module name="MethodName">
|
||||||
<property name="format" value="^(computercraft\$)?[a-z][a-zA-Z0-9]*$" />
|
<property name="format" value="^(computercraft\$)?[a-z][a-zA-Z0-9]*$" />
|
||||||
</module>
|
</module>
|
||||||
<module name="MethodTypeParameterName" />
|
<module name="MethodTypeParameterName" />
|
||||||
<module name="PackageName">
|
<module name="PackageName">
|
||||||
<property name="format" value="^(dan200\.computercraft|cc\.tweaked)(\.[a-z][a-z0-9]*)*" />
|
<property name="format" value="^(dan200\.computercraft|cc\.tweaked|com\.example\.examplemod)(\.[a-z][a-z0-9]*)*" />
|
||||||
</module>
|
</module>
|
||||||
<module name="ParameterName" />
|
<module name="ParameterName" />
|
||||||
<module name="StaticVariableName">
|
<module name="StaticVariableName">
|
||||||
<property name="format" value="^[a-z][a-zA-Z0-9]*|CAPABILITY(_[A-Z_]+)?$" />
|
<property name="format" value="^[a-z][a-zA-Z0-9]*$" />
|
||||||
</module>
|
</module>
|
||||||
<module name="TypeName" />
|
<module name="TypeName" />
|
||||||
|
|
||||||
@@ -137,7 +155,10 @@ SPDX-License-Identifier: MPL-2.0
|
|||||||
<module name="NoWhitespaceAfter">
|
<module name="NoWhitespaceAfter">
|
||||||
<property name="tokens" value="AT,INC,DEC,UNARY_MINUS,UNARY_PLUS,BNOT,LNOT,DOT,ARRAY_DECLARATOR,INDEX_OP,METHOD_REF" />
|
<property name="tokens" value="AT,INC,DEC,UNARY_MINUS,UNARY_PLUS,BNOT,LNOT,DOT,ARRAY_DECLARATOR,INDEX_OP,METHOD_REF" />
|
||||||
</module>
|
</module>
|
||||||
<module name="NoWhitespaceBefore" />
|
<module name="NoWhitespaceBefore">
|
||||||
|
<!-- Allow whitespace before "..." for @Nullable annotations -->
|
||||||
|
<property name="tokens" value="COMMA,SEMI,POST_INC,POST_DEC,LABELED_STAT" />
|
||||||
|
</module>
|
||||||
<!-- TODO: Decide on an OperatorWrap style. -->
|
<!-- TODO: Decide on an OperatorWrap style. -->
|
||||||
<module name="ParenPad" />
|
<module name="ParenPad" />
|
||||||
<module name="SeparatorWrap">
|
<module name="SeparatorWrap">
|
||||||
|
@@ -16,4 +16,13 @@ SPDX-License-Identifier: MPL-2.0
|
|||||||
|
|
||||||
<!-- The commands API is documented in Lua. -->
|
<!-- The commands API is documented in Lua. -->
|
||||||
<suppress checks="SummaryJavadocCheck" files=".*[\\/]CommandAPI.java" />
|
<suppress checks="SummaryJavadocCheck" files=".*[\\/]CommandAPI.java" />
|
||||||
|
|
||||||
|
<!-- Allow putting files in other packages if they look like our TeaVM stubs. -->
|
||||||
|
<suppress checks="PackageName" files=".*[\\/]T[A-Za-z]+.java" />
|
||||||
|
|
||||||
|
<!-- Allow underscores in our test classes. -->
|
||||||
|
<suppress checks="MethodName" files=".*(Contract|Test).java" />
|
||||||
|
|
||||||
|
<!-- Allow underscores in Mixin classes -->
|
||||||
|
<suppress checks="TypeName" files=".*[\\/]mixin[\\/].*.java" />
|
||||||
</suppressions>
|
</suppressions>
|
||||||
|
@@ -1,12 +0,0 @@
|
|||||||
# SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
|
||||||
#
|
|
||||||
# SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
FROM gitpod/workspace-base
|
|
||||||
|
|
||||||
USER gitpod
|
|
||||||
|
|
||||||
RUN sudo apt-get -q update \
|
|
||||||
&& sudo apt-get install -yq openjdk-16-jdk python3-pip npm \
|
|
||||||
&& sudo pip3 install pre-commit \
|
|
||||||
&& sudo update-java-alternatives --set java-1.16.0-openjdk-amd64
|
|
28
crowdin.yml
Normal file
28
crowdin.yml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2017 The CC: Tweaked Developers
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
files:
|
||||||
|
- source: projects/common/src/generated/resources/assets/computercraft/lang/en_us.json
|
||||||
|
translation: /projects/common/src/main/resources/assets/computercraft/lang/%locale_with_underscore%.json
|
||||||
|
languages_mapping:
|
||||||
|
locale_with_underscore:
|
||||||
|
cs: cs_cz # Czech
|
||||||
|
da: da_dk # Danish
|
||||||
|
de: de_de # German
|
||||||
|
es-ES: es_es # Spanish
|
||||||
|
fr: fr_fr # French
|
||||||
|
it: it_it # Italian
|
||||||
|
ja: ja_jp # Japanese
|
||||||
|
ko: ko_kr # Korean
|
||||||
|
nb: nb_no # Norwegian Bokmal
|
||||||
|
nl: nl_nl # Dutch
|
||||||
|
pl: pl_pl # Polish
|
||||||
|
pt-BR: pt_br # Portuguese, Brazilian
|
||||||
|
ru: ru_ru # Russian
|
||||||
|
sv-SE: sv_se # Sweedish
|
||||||
|
tok: tok # Toki Pona
|
||||||
|
tr: tr_tr # Turkish
|
||||||
|
uk: uk_ua # Ukraine
|
||||||
|
vi: vi_vn # Vietnamese
|
||||||
|
zh-CN: zh_cn # Chinese Simplified
|
@@ -6,7 +6,7 @@ see: key To listen to any key press.
|
|||||||
<!--
|
<!--
|
||||||
SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
||||||
|
|
||||||
SPDX-License-Identifier: LicenseRef-CCPL
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
The [`char`] event is fired when a character is typed on the keyboard.
|
The [`char`] event is fired when a character is typed on the keyboard.
|
||||||
|
@@ -12,7 +12,7 @@ SPDX-License-Identifier: MPL-2.0
|
|||||||
The [`file_transfer`] event is queued when a user drags-and-drops a file on an open computer.
|
The [`file_transfer`] event is queued when a user drags-and-drops a file on an open computer.
|
||||||
|
|
||||||
This event contains a single argument of type [`TransferredFiles`], which can be used to [get the files to be
|
This event contains a single argument of type [`TransferredFiles`], which can be used to [get the files to be
|
||||||
transferred][`TransferredFiles.getFiles`]. Each file returned is a [binary file handle][`fs.BinaryReadHandle`] with an
|
transferred][`TransferredFiles.getFiles`]. Each file returned is a [binary file handle][`fs.ReadHandle`] with an
|
||||||
additional [getName][`TransferredFile.getName`] method.
|
additional [getName][`TransferredFile.getName`] method.
|
||||||
|
|
||||||
## Return values
|
## Return values
|
||||||
@@ -29,7 +29,7 @@ for _, file in ipairs(files.getFiles()) do
|
|||||||
local size = file.seek("end")
|
local size = file.seek("end")
|
||||||
file.seek("set", 0)
|
file.seek("set", 0)
|
||||||
|
|
||||||
print(file.getName() .. " " .. file.getSize())
|
print(file.getName() .. " " .. size)
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@@ -5,7 +5,7 @@ module: [kind=event] key
|
|||||||
<!--
|
<!--
|
||||||
SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
||||||
|
|
||||||
SPDX-License-Identifier: LicenseRef-CCPL
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
This event is fired when any key is pressed while the terminal is focused.
|
This event is fired when any key is pressed while the terminal is focused.
|
||||||
|
@@ -6,7 +6,7 @@ see: keys For a lookup table of the given keys.
|
|||||||
<!--
|
<!--
|
||||||
SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
||||||
|
|
||||||
SPDX-License-Identifier: LicenseRef-CCPL
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
Fired whenever a key is released (or the terminal is closed while a key was being pressed).
|
Fired whenever a key is released (or the terminal is closed while a key was being pressed).
|
||||||
|
@@ -8,7 +8,7 @@ SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
|||||||
SPDX-License-Identifier: MPL-2.0
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
The [`monitor_resize`] event is fired when an adjacent or networked monitor's size is changed.
|
The [`monitor_resize`] event is fired when an adjacent or networked [monitor's][`monitor`] size is changed.
|
||||||
|
|
||||||
## Return Values
|
## Return Values
|
||||||
1. [`string`]: The event name.
|
1. [`string`]: The event name.
|
||||||
|
@@ -8,7 +8,7 @@ SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
|||||||
SPDX-License-Identifier: MPL-2.0
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
The [`monitor_touch`] event is fired when an adjacent or networked Advanced Monitor is right-clicked.
|
The [`monitor_touch`] event is fired when an adjacent or networked [Advanced Monitor][`monitor`] is right-clicked.
|
||||||
|
|
||||||
## Return Values
|
## Return Values
|
||||||
1. [`string`]: The event name.
|
1. [`string`]: The event name.
|
||||||
|
@@ -5,7 +5,7 @@ module: [kind=event] mouse_click
|
|||||||
<!--
|
<!--
|
||||||
SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
||||||
|
|
||||||
SPDX-License-Identifier: LicenseRef-CCPL
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
This event is fired when the terminal is clicked with a mouse. This event is only fired on advanced computers (including
|
This event is fired when the terminal is clicked with a mouse. This event is only fired on advanced computers (including
|
||||||
|
@@ -6,7 +6,7 @@ see: mouse_click For when a mouse button is initially pressed.
|
|||||||
<!--
|
<!--
|
||||||
SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
||||||
|
|
||||||
SPDX-License-Identifier: LicenseRef-CCPL
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
This event is fired every time the mouse is moved while a mouse button is being held.
|
This event is fired every time the mouse is moved while a mouse button is being held.
|
||||||
|
@@ -5,7 +5,7 @@ module: [kind=event] mouse_scroll
|
|||||||
<!--
|
<!--
|
||||||
SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
||||||
|
|
||||||
SPDX-License-Identifier: LicenseRef-CCPL
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
This event is fired when a mouse wheel is scrolled in the terminal.
|
This event is fired when a mouse wheel is scrolled in the terminal.
|
||||||
|
@@ -5,7 +5,7 @@ module: [kind=event] mouse_up
|
|||||||
<!--
|
<!--
|
||||||
SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
||||||
|
|
||||||
SPDX-License-Identifier: LicenseRef-CCPL
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
This event is fired when a mouse button is released or a held mouse leaves the computer's terminal.
|
This event is fired when a mouse button is released or a held mouse leaves the computer's terminal.
|
||||||
|
@@ -8,7 +8,7 @@ SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
|||||||
SPDX-License-Identifier: MPL-2.0
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
The [`event!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 or [relay][`redstone_relay`] change.
|
||||||
|
|
||||||
## Return values
|
## Return values
|
||||||
1. [`string`]: The event name.
|
1. [`string`]: The event name.
|
||||||
@@ -21,3 +21,7 @@ while true do
|
|||||||
print("A redstone input has changed!")
|
print("A redstone input has changed!")
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## See also
|
||||||
|
- [The `redstone` API on computers][`module!redstone`]
|
||||||
|
- [The `redstone_relay` peripheral][`redstone_relay`]
|
||||||
|
@@ -19,7 +19,7 @@ In order to give the best results, a GPS constellation needs at least four compu
|
|||||||
constellation is redundant, but it does not cause problems.
|
constellation is redundant, but it does not cause problems.
|
||||||
|
|
||||||
## Building a GPS constellation
|
## Building a GPS constellation
|
||||||
<img alt="An example GPS constellation." src="/images/gps-constellation-example.png" class="big-image" />
|
<img alt="An example GPS constellation." src="../images/gps-constellation-example.png" class="big-image" />
|
||||||
|
|
||||||
We are going to build our GPS constellation as shown in the image above. You will need 4 computers and either 4 wireless
|
We are going to build our GPS constellation as shown in the image above. You will need 4 computers and either 4 wireless
|
||||||
modems or 4 ender modems. Try not to mix ender and wireless modems together as you might get some odd behavior when your
|
modems or 4 ender modems. Try not to mix ender and wireless modems together as you might get some odd behavior when your
|
||||||
|
@@ -131,10 +131,10 @@ different.
|
|||||||
First, we require the dfpwm module and call [`cc.audio.dfpwm.make_decoder`] to construct a new decoder. This decoder
|
First, we require the dfpwm module and call [`cc.audio.dfpwm.make_decoder`] to construct a new decoder. This decoder
|
||||||
accepts blocks of DFPWM data and converts it to a list of 8-bit amplitudes, which we can then play with our speaker.
|
accepts blocks of DFPWM data and converts it to a list of 8-bit amplitudes, which we can then play with our speaker.
|
||||||
|
|
||||||
As mentioned above, [`speaker.playAudio`] accepts at most 128×1024 samples in one go. DFPMW uses a single bit for each
|
As mentioned above, [`speaker.playAudio`] accepts at most 128×1024 samples in one go. DFPWM uses a single bit for each
|
||||||
sample, which means we want to process our audio in chunks of 16×1024 bytes (16KiB). In order to do this, we use
|
sample, which means we want to process our audio in chunks of 16×1024 bytes (16KiB). In order to do this, we use
|
||||||
[`io.lines`], which provides a nice way to loop over chunks of a file. You can of course just use [`fs.open`] and
|
[`io.lines`], which provides a nice way to loop over chunks of a file. You can of course just use [`fs.open`] and
|
||||||
[`fs.BinaryReadHandle.read`] if you prefer.
|
[`fs.ReadHandle.read`] if you prefer.
|
||||||
|
|
||||||
## Processing audio
|
## Processing audio
|
||||||
As mentioned near the beginning of this guide, PCM audio is pretty easy to work with as it's just a list of amplitudes.
|
As mentioned near the beginning of this guide, PCM audio is pretty easy to work with as it's just a list of amplitudes.
|
||||||
@@ -191,7 +191,7 @@ end
|
|||||||
|
|
||||||
> [Confused?][!NOTE]
|
> [Confused?][!NOTE]
|
||||||
> Don't worry if you don't understand this example. It's quite advanced, and does use some ideas that this guide doesn't
|
> Don't worry if you don't understand this example. It's quite advanced, and does use some ideas that this guide doesn't
|
||||||
> cover. That said, don't be afraid to ask on [GitHub Discussions] or [IRC] either!
|
> cover. That said, don't be afraid to ask [the community for help][community].
|
||||||
|
|
||||||
It's worth noting that the examples of audio processing we've mentioned here are about manipulating the _amplitude_ of
|
It's worth noting that the examples of audio processing we've mentioned here are about manipulating the _amplitude_ of
|
||||||
the wave. If you wanted to modify the _frequency_ (for instance, shifting the pitch), things get rather more complex.
|
the wave. If you wanted to modify the _frequency_ (for instance, shifting the pitch), things get rather more complex.
|
||||||
@@ -205,5 +205,4 @@ This is, I'm afraid, left as an exercise to the reader.
|
|||||||
[PCM]: https://en.wikipedia.org/wiki/Pulse-code_modulation "Pulse-code Modulation - Wikipedia"
|
[PCM]: https://en.wikipedia.org/wiki/Pulse-code_modulation "Pulse-code Modulation - Wikipedia"
|
||||||
[Ring Buffer]: https://en.wikipedia.org/wiki/Circular_buffer "Circular buffer - Wikipedia"
|
[Ring Buffer]: https://en.wikipedia.org/wiki/Circular_buffer "Circular buffer - Wikipedia"
|
||||||
[Sine Wave]: https://en.wikipedia.org/wiki/Sine_wave "Sine wave - Wikipedia"
|
[Sine Wave]: https://en.wikipedia.org/wiki/Sine_wave "Sine wave - Wikipedia"
|
||||||
[GitHub Discussions]: https://github.com/cc-tweaked/CC-Tweaked/discussions
|
[Community]: /#community
|
||||||
[IRC]: https://webchat.esper.net/?channels=computercraft "#computercraft on EsperNet"
|
|
||||||
|
BIN
doc/images/computercraft-dump.png
Normal file
BIN
doc/images/computercraft-dump.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 254 KiB |
BIN
doc/images/computercraft-track.png
Normal file
BIN
doc/images/computercraft-track.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 304 KiB |
23
doc/index.md
23
doc/index.md
@@ -4,12 +4,19 @@ SPDX-FileCopyrightText: 2020 The CC: Tweaked Developers
|
|||||||
SPDX-License-Identifier: MPL-2.0
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
# 
|
<h1>
|
||||||
|
<picture>
|
||||||
|
<source media="(prefers-color-scheme: dark)" srcset="logo-darkmode.png">
|
||||||
|
<source media="(prefers-color-scheme: light)" srcset="logo.png">
|
||||||
|
<img alt="CC: Tweaked" src="logo.png">
|
||||||
|
</picture>
|
||||||
|
</h1>
|
||||||
|
|
||||||
CC: Tweaked is a mod for Minecraft which adds programmable computers, turtles and more to the game. A fork of the
|
CC: Tweaked is a mod for Minecraft which adds programmable computers, turtles and more to the game. A fork of the
|
||||||
much-beloved [ComputerCraft], it continues its legacy with improved performance and stability, along with a wealth of
|
much-beloved [ComputerCraft], it continues its legacy with improved performance and stability, along with a wealth of
|
||||||
new features.
|
new features.
|
||||||
|
|
||||||
CC: Tweaked can be installed from [CurseForge] or [Modrinth]. It runs on both [Minecraft Forge] and [Fabric].
|
CC: Tweaked can be installed from [Modrinth]. It runs on both [Minecraft Forge] and [Fabric].
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
Controlled using the [Lua programming language][lua], CC: Tweaked's computers provides all the tools you need to start
|
Controlled using the [Lua programming language][lua], CC: Tweaked's computers provides all the tools you need to start
|
||||||
@@ -38,12 +45,16 @@ little daunting getting started. Thankfully, there's several fantastic tutorials
|
|||||||
|
|
||||||
- [Direwolf20's ComputerCraft tutorials](https://www.youtube.com/watch?v=wrUHUhfCY5A "ComputerCraft Tutorial Episode 1 - HELP! and Hello World")
|
- [Direwolf20's ComputerCraft tutorials](https://www.youtube.com/watch?v=wrUHUhfCY5A "ComputerCraft Tutorial Episode 1 - HELP! and Hello World")
|
||||||
- [Sethbling's ComputerCraft series](https://www.youtube.com/watch?v=DSsx4VSe-Uk "Programming Tutorial with Minecraft Turtles -- Ep. 1: Intro to Turtles and If-Then-Else_End")
|
- [Sethbling's ComputerCraft series](https://www.youtube.com/watch?v=DSsx4VSe-Uk "Programming Tutorial with Minecraft Turtles -- Ep. 1: Intro to Turtles and If-Then-Else_End")
|
||||||
- [Lyqyd's Computer Basics 1](http://www.computercraft.info/forums2/index.php?/topic/15033-computer-basics-i/ "Computer Basics I")
|
- [Lyqyd's Computer Basics 1](https://ccf.squiddev.cc/forums2/index.php?/topic/15033-computer-basics-i/ "Computer Basics I")
|
||||||
|
|
||||||
Once you're a little more familiar with the mod, the sidebar and links below provide more detailed documentation on the
|
Once you're a little more familiar with the mod, the sidebar and links below provide more detailed documentation on the
|
||||||
various APIs and peripherals provided by the mod.
|
various APIs and peripherals provided by the mod.
|
||||||
|
|
||||||
If you get stuck, do [ask a question on GitHub][GitHub Discussions] or pop in to the ComputerCraft's [IRC channel][IRC].
|
<h2 id="community">Community</h2>
|
||||||
|
If you need help getting started with CC: Tweaked, want to show off your latest project, or just want to chat about
|
||||||
|
ComputerCraft, do check out our [GitHub discussions page][GitHub discussions]! There's also a fairly populated,
|
||||||
|
albeit quiet IRC channel on [EsperNet], if that's more your cup of tea. You can join `#computercraft` through your
|
||||||
|
desktop client, or online using [KiwiIRC].
|
||||||
|
|
||||||
## Get Involved
|
## Get Involved
|
||||||
CC: Tweaked lives on [GitHub]. If you've got any ideas, feedback or bugs please do [create an issue][bug].
|
CC: Tweaked lives on [GitHub]. If you've got any ideas, feedback or bugs please do [create an issue][bug].
|
||||||
@@ -51,11 +62,11 @@ CC: Tweaked lives on [GitHub]. If you've got any ideas, feedback or bugs please
|
|||||||
[github]: https://github.com/cc-tweaked/CC-Tweaked/ "CC: Tweaked on GitHub"
|
[github]: https://github.com/cc-tweaked/CC-Tweaked/ "CC: Tweaked on GitHub"
|
||||||
[bug]: https://github.com/cc-tweaked/CC-Tweaked/issues/new/choose
|
[bug]: https://github.com/cc-tweaked/CC-Tweaked/issues/new/choose
|
||||||
[computercraft]: https://github.com/dan200/ComputerCraft "ComputerCraft on GitHub"
|
[computercraft]: https://github.com/dan200/ComputerCraft "ComputerCraft on GitHub"
|
||||||
[curseforge]: https://minecraft.curseforge.com/projects/cc-tweaked "Download CC: Tweaked from CurseForge"
|
|
||||||
[modrinth]: https://modrinth.com/mod/gu7yAYhd "Download CC: Tweaked from Modrinth"
|
[modrinth]: https://modrinth.com/mod/gu7yAYhd "Download CC: Tweaked from Modrinth"
|
||||||
[forge]: https://files.minecraftforge.net/ "Download Minecraft Forge."
|
[forge]: https://files.minecraftforge.net/ "Download Minecraft Forge."
|
||||||
[Minecraft Forge]: https://files.minecraftforge.net/ "Download Minecraft Forge."
|
[Minecraft Forge]: https://files.minecraftforge.net/ "Download Minecraft Forge."
|
||||||
[Fabric]: https://fabricmc.net/use/installer/ "Download Fabric."
|
[Fabric]: https://fabricmc.net/use/installer/ "Download Fabric."
|
||||||
[lua]: https://www.lua.org/ "Lua's main website"
|
[lua]: https://www.lua.org/ "Lua's main website"
|
||||||
[GitHub Discussions]: https://github.com/cc-tweaked/CC-Tweaked/discussions
|
[GitHub Discussions]: https://github.com/cc-tweaked/CC-Tweaked/discussions
|
||||||
[IRC]: https://webchat.esper.net/?channels=computercraft "#computercraft on EsperNet"
|
[EsperNet]: https://www.esper.net/
|
||||||
|
[KiwiIRC]: https://kiwiirc.com/nextclient/#irc://irc.esper.net:+6697/#computercraft "#computercraft on EsperNet"
|
||||||
|
@@ -45,12 +45,16 @@ little daunting getting started. Thankfully, there's several fantastic tutorials
|
|||||||
|
|
||||||
- [Direwolf20's ComputerCraft tutorials](https://www.youtube.com/watch?v=wrUHUhfCY5A "ComputerCraft Tutorial Episode 1 - HELP! and Hello World")
|
- [Direwolf20's ComputerCraft tutorials](https://www.youtube.com/watch?v=wrUHUhfCY5A "ComputerCraft Tutorial Episode 1 - HELP! and Hello World")
|
||||||
- [Sethbling's ComputerCraft series](https://www.youtube.com/watch?v=DSsx4VSe-Uk "Programming Tutorial with Minecraft Turtles -- Ep. 1: Intro to Turtles and If-Then-Else_End")
|
- [Sethbling's ComputerCraft series](https://www.youtube.com/watch?v=DSsx4VSe-Uk "Programming Tutorial with Minecraft Turtles -- Ep. 1: Intro to Turtles and If-Then-Else_End")
|
||||||
- [Lyqyd's Computer Basics 1](http://www.computercraft.info/forums2/index.php?/topic/15033-computer-basics-i/ "Computer Basics I")
|
- [Lyqyd's Computer Basics 1](https://ccf.squiddev.cc/forums2/index.php?/topic/15033-computer-basics-i/ "Computer Basics I")
|
||||||
|
|
||||||
Once you're a little more familiar with the mod, the [wiki](https://tweaked.cc/) provides more detailed documentation on the
|
Once you're a little more familiar with the mod, the [wiki](https://tweaked.cc/) provides more detailed documentation on the
|
||||||
various APIs and peripherals provided by the mod.
|
various APIs and peripherals provided by the mod.
|
||||||
|
|
||||||
If you get stuck, do [ask a question on GitHub][GitHub Discussions] or pop in to the ComputerCraft's [IRC channel][IRC].
|
## Community
|
||||||
|
If you need help getting started with CC: Tweaked, want to show off your latest project, or just want to chat about
|
||||||
|
ComputerCraft, do check out our [GitHub discussions page][GitHub discussions]! There's also a fairly populated,
|
||||||
|
albeit quiet IRC channel on [EsperNet], if that's more your cup of tea. You can join `#computercraft` through your
|
||||||
|
desktop client, or online using [KiwiIRC].
|
||||||
|
|
||||||
## Get Involved
|
## Get Involved
|
||||||
CC: Tweaked lives on [GitHub]. If you've got any ideas, feedback or bugs please do [create an issue][bug].
|
CC: Tweaked lives on [GitHub]. If you've got any ideas, feedback or bugs please do [create an issue][bug].
|
||||||
@@ -60,4 +64,5 @@ CC: Tweaked lives on [GitHub]. If you've got any ideas, feedback or bugs please
|
|||||||
[computercraft]: https://github.com/dan200/ComputerCraft "ComputerCraft on GitHub"
|
[computercraft]: https://github.com/dan200/ComputerCraft "ComputerCraft on GitHub"
|
||||||
[lua]: https://www.lua.org/ "Lua's main website"
|
[lua]: https://www.lua.org/ "Lua's main website"
|
||||||
[GitHub Discussions]: https://github.com/cc-tweaked/CC-Tweaked/discussions
|
[GitHub Discussions]: https://github.com/cc-tweaked/CC-Tweaked/discussions
|
||||||
[IRC]: http://webchat.esper.net/?channels=computercraft "#computercraft on EsperNet"
|
[EsperNet]: https://www.esper.net/
|
||||||
|
[KiwiIRC]: https://kiwiirc.com/nextclient/#irc://irc.esper.net:+6697/#computercraft "#computercraft on EsperNet"
|
||||||
|
81
doc/reference/breaking_changes.md
Normal file
81
doc/reference/breaking_changes.md
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
---
|
||||||
|
module: [kind=reference] breaking_changes
|
||||||
|
---
|
||||||
|
|
||||||
|
<!--
|
||||||
|
SPDX-FileCopyrightText: 2019 The CC: Tweaked Developers
|
||||||
|
|
||||||
|
SPDX-License-Identifier: MPL-2.0
|
||||||
|
-->
|
||||||
|
|
||||||
|
# Incompatibilities between versions
|
||||||
|
|
||||||
|
CC: Tweaked tries to remain as compatible between versions as possible, meaning most programs written for older version
|
||||||
|
of the mod should run fine on later versions.
|
||||||
|
|
||||||
|
> [External peripherals][!WARNING]
|
||||||
|
>
|
||||||
|
> While CC: Tweaked is relatively stable across versions, this may not be true for other mods which add their own
|
||||||
|
> peripherals. Older programs which interact with external blocks may not work on newer versions of the game.
|
||||||
|
|
||||||
|
However, some changes to the underlying game, or CC: Tweaked's own internals may break some programs. This page serves
|
||||||
|
as documentation for breaking changes and "gotchas" one should look out for between versions.
|
||||||
|
|
||||||
|
## CC: Tweaked 1.109.0 to 1.109.3 {#cct-1.109}
|
||||||
|
|
||||||
|
- Update to Lua 5.2:
|
||||||
|
- Support for Lua 5.0's pseudo-argument `arg` has been removed. You should always use `...` for varargs.
|
||||||
|
- Environments are no longer baked into the runtime, and instead use the `_ENV` local or upvalue. [`getfenv`]/[`setfenv`]
|
||||||
|
now only work on Lua functions with an `_ENV` upvalue. [`getfenv`] will return the global environment when called
|
||||||
|
with other functions, and [`setfenv`] will have no effect.
|
||||||
|
- [`load`]/[`loadstring`] defaults to using the global environment (`_G`) rather than the current coroutine's
|
||||||
|
environment.
|
||||||
|
- Support for dumping functions ([`string.dump`]) and loading binary chunks has been removed.
|
||||||
|
- [`math.random`] now uses Lua 5.4's random number generator.
|
||||||
|
|
||||||
|
- File handles, HTTP requests and websockets now always use the original bytes rather than encoding/decoding to UTF-8.
|
||||||
|
|
||||||
|
## Minecraft 1.13 {#mc-1.13}
|
||||||
|
- The "key code" for [`key`] and [`key_up`] events has changed, due to Minecraft updating to LWJGL 3. Make sure you're
|
||||||
|
using the constants provided by the [`keys`] API, rather than hard-coding numerical values.
|
||||||
|
|
||||||
|
Related to this change, the numpad enter key now has a different key code to the enter key. You may need to adjust
|
||||||
|
your programs to handle both. (Note, the `keys.numpadEnter` constant was defined in pre-1.13 versions of CC, but the
|
||||||
|
`keys.enter` constant was queued when the key was pressed)
|
||||||
|
|
||||||
|
- Minecraft 1.13 removed the concept of item damage and block metadata (see ["The Flattening"][flattening]). As a
|
||||||
|
result [`turtle.inspect`] no longer provides block metadata, and [`turtle.getItemDetail`] no longer provides damage.
|
||||||
|
|
||||||
|
- Block states (`turtle.inspect().state`) should provide all the same information as block metadata, but in a much
|
||||||
|
more understandable format.
|
||||||
|
|
||||||
|
- Item and block names now represent a unique item type. For instance, wool is split into 16 separate items
|
||||||
|
(`minecraft:white_wool`, etc...) rather than a single `minecraft:wool` with each meta/damage value specifying the
|
||||||
|
colour.
|
||||||
|
|
||||||
|
- Custom ROMs are now provided using data packs rather than resource packs. This should mostly be a matter of renaming
|
||||||
|
the "assets" folder to "data", and placing it in "datapacks", but there are a couple of other gotchas to look out
|
||||||
|
for:
|
||||||
|
|
||||||
|
- Data packs [impose some restrictions on file names][legal_data_pack]. As a result, your programs and directories
|
||||||
|
must all be lower case.
|
||||||
|
- Due to how data packs are read by CC: Tweaked, you may need to use the `/reload` command to see changes to your
|
||||||
|
pack show up on the computer.
|
||||||
|
|
||||||
|
See [the example datapack][datapack-example] for how to get started.
|
||||||
|
|
||||||
|
- Turtles can now be waterlogged and move "through" water sources rather than breaking them.
|
||||||
|
|
||||||
|
## CC: Tweaked 1.88.0 {#cc-1.88}
|
||||||
|
- Unlabelled computers and turtles now keep their ID when broken, meaning that unlabelled computers/items do not stack.
|
||||||
|
|
||||||
|
## ComputerCraft 1.80pr1 {#cc-1.80}
|
||||||
|
- Programs run via [`shell.run`] are now started in their own isolated environment. This means globals set by programs
|
||||||
|
will not be accessible outside of this program.
|
||||||
|
|
||||||
|
- Programs containing `/` are looked up in the current directory and are no longer looked up on the path. For instance,
|
||||||
|
you can no longer type `turtle/excavate` to run `/rom/programs/turtle/excavate.lua`.
|
||||||
|
|
||||||
|
[flattening]: https://minecraft.wiki/w/Java_Edition_1.13/Flattening
|
||||||
|
[legal_data_pack]: https://minecraft.wiki/w/Tutorials/Creating_a_data_pack#Legal_characters
|
||||||
|
[datapack-example]: https://github.com/cc-tweaked/datapack-example "An example datapack for CC: Tweaked"
|
140
doc/reference/command.md
Normal file
140
doc/reference/command.md
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
---
|
||||||
|
module: [kind=reference] computercraft_command
|
||||||
|
---
|
||||||
|
|
||||||
|
<!--
|
||||||
|
SPDX-FileCopyrightText: 2023 The CC: Tweaked Developers
|
||||||
|
|
||||||
|
SPDX-License-Identifier: MPL-2.0
|
||||||
|
-->
|
||||||
|
|
||||||
|
# The `/computercraft` command
|
||||||
|
CC: Tweaked provides a `/computercraft` command for server owners to manage running computers on a server.
|
||||||
|
|
||||||
|
## Permissions {#permissions}
|
||||||
|
As the `/computercraft` command is mostly intended for debugging and administrative purposes, its sub-commands typically
|
||||||
|
require you to have op (or similar).
|
||||||
|
|
||||||
|
- All players have access to the [`queue`] sub-command.
|
||||||
|
- On a multi-player server, all other commands require op.
|
||||||
|
- On a single-player world, the player can run the [`dump`], [`turn-on`]/[`shutdown`], and [`track`] sub-commands, even
|
||||||
|
when cheats are not enabled. The [`tp`] and [`view`] commands require cheats.
|
||||||
|
|
||||||
|
If a permission mod such as [LuckPerms] is installed[^permission], you can configure access to the individual
|
||||||
|
sub-commands. Each sub-command creates a `computercraft.command.NAME` permission node to control which players can
|
||||||
|
execute it.
|
||||||
|
|
||||||
|
[LuckPerms]: https://github.com/LuckPerms/LuckPerms/ "A permissions plugin for Minecraft servers."
|
||||||
|
[fabric-permission-api]: https://github.com/lucko/fabric-permissions-api "A simple permissions API for Fabric"
|
||||||
|
|
||||||
|
[^permission]: This supports any mod which uses Forge's permission API or [fabric-permission-api].
|
||||||
|
|
||||||
|
## Computer selectors {#computer-selectors}
|
||||||
|
Some commands (such as [`tp`] or [`turn-on`]) target a specific computer, or a list of computers. To specify which
|
||||||
|
computers to operate on, you must use "computer selectors".
|
||||||
|
|
||||||
|
Computer selectors are similar to Minecraft's [entity target selectors], but targeting computers instead. They allow
|
||||||
|
you to select one or more computers, based on a set of predicates.
|
||||||
|
|
||||||
|
The following predicates are supported:
|
||||||
|
- `id=<id>`: Select computer(s) with a specific id.
|
||||||
|
- `instance=<id>`: Select the computer with the given instance id.
|
||||||
|
- `family=<normal|advanced|command>`: Select computers based on their type.
|
||||||
|
- `label=<label>`: Select computers with the given label.
|
||||||
|
- `distance=<distance>`: Select computers within a specific distance of the player executing the command. This uses
|
||||||
|
Minecraft's [float range] syntax.
|
||||||
|
|
||||||
|
`#<id>` may also be used as a shorthand for `@c[id=<id>]`, to select computer(s) with a specific id.
|
||||||
|
|
||||||
|
### Examples:
|
||||||
|
- `/computercraft turn-on #12`: Turn on the computer(s) with an id of 12.
|
||||||
|
- `/computercraft shutdown @c[distance=..100]`: Shut down all computers with 100 blocks of the player.
|
||||||
|
|
||||||
|
[entity target selectors]: https://minecraft.wiki/w/Target_selectors "Target Selectors on the Minecraft wiki"
|
||||||
|
[Float range]: https://minecraft.wiki/w/Argument_types#minecraft:float_range
|
||||||
|
|
||||||
|
## Commands {#commands}
|
||||||
|
### `/computercraft dump` {#dump}
|
||||||
|
`/computercraft dump` prints a table of currently loaded computers, including their id, position, and whether they're
|
||||||
|
running. It can also be run with a single computer argument to dump more detailed information about a computer.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Next to the computer id, there are several buttons to either [teleport][`tp`] to the computer, or [open its terminal
|
||||||
|
][`view`].
|
||||||
|
|
||||||
|
Computers are sorted by distance to the player, so nearby computers will appear earlier.
|
||||||
|
|
||||||
|
### `/computercraft turn-on [computers...]` {#turn-on}
|
||||||
|
Turn on one or more computers or, if no run with no arguments, all loaded computers.
|
||||||
|
|
||||||
|
#### Examples
|
||||||
|
- `/computercraft turn-on #0 #2`: Turn on computers with id 0 and 2.
|
||||||
|
- `/computercraft turn-on @c[family=command]`: Turn on all command computers.
|
||||||
|
|
||||||
|
### `/computercraft shutdown [computers...]` {#shutdown}
|
||||||
|
Shutdown one or more computers or, if no run with no arguments, all loaded computers.
|
||||||
|
|
||||||
|
This is sometimes useful when dealing with lag, as a way to ensure that ComputerCraft is not causing problems.
|
||||||
|
|
||||||
|
#### Examples
|
||||||
|
- `/computercraft shutdown`: Shut down all loaded computers.
|
||||||
|
- `/computercraft shutdown @c[distance=..10]`: Shut down all computers in a block radius.
|
||||||
|
|
||||||
|
### `/computercraft tp [computer]` {#tp}
|
||||||
|
Teleport to the given computer.
|
||||||
|
|
||||||
|
This is normally used from via the [`dump`] command interface rather than being invoked directly.
|
||||||
|
|
||||||
|
### `/computercraft view [computer]` {#view}
|
||||||
|
Open a terminal for the specified computer. This allows remotely viewing computers without having to interact with the
|
||||||
|
block.
|
||||||
|
|
||||||
|
This is normally used from via the [`dump`] command interface rather than being invoked directly.
|
||||||
|
|
||||||
|
### `/computercraft track` {#track}
|
||||||
|
The `/computercraft track` command allows you to enable profiling of computers. When a computer runs code, or interacts
|
||||||
|
with the Minecraft world, we time how long that takes. This timing information may then be queried, and used to find
|
||||||
|
computers which may be causing lag.
|
||||||
|
|
||||||
|
To enable the profiler, run `/computercraft track start`. Computers will then start recording metrics. Once enough data
|
||||||
|
has been gathered, run `/computercraft track stop` to stop profiling and display the recorded data.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
The table by default shows the number of times each computer has run, and how long it ran for (in total, and on
|
||||||
|
average). In the above screenshot, we can see one computer was particularly badly behaved, and ran for 7 seconds. The
|
||||||
|
buttons may be used to [teleport][`tp`] to the computer, or [open its terminal ][`view`], and inspect it further.
|
||||||
|
|
||||||
|
`/computercraft track dump` can be used to display this table at any point (including while profiling is still running).
|
||||||
|
|
||||||
|
Computers also record other information, such as how much server-thread time they consume, or their HTTP bandwidth
|
||||||
|
usage. The `dump` subcommand accepts a list of other fields to display, instead of the default timings.
|
||||||
|
|
||||||
|
#### Examples
|
||||||
|
- `/computercraft track dump server_tasks_count server_tasks`: Print the number of server-thread tasks each computer
|
||||||
|
executed, and how long they took in total.
|
||||||
|
- `/computercraft track dump http_upload http_download`: Print the number of bytes uploaded and downloaded by each
|
||||||
|
computer.
|
||||||
|
|
||||||
|
|
||||||
|
### `/computercraft queue` {#queue}
|
||||||
|
The queue subcommand allows non-operator players to queue a `computer_command` event on *command* computers.
|
||||||
|
|
||||||
|
This has a similar purpose to vanilla's [`/trigger`] command. Command computers may choose to listen to this event, and
|
||||||
|
then perform some action.
|
||||||
|
|
||||||
|
[`/trigger`]: https://minecraft.wiki/w/Commands/trigger "/trigger on the Minecraft wiki"
|
||||||
|
|
||||||
|
|
||||||
|
[`dump`]: #dump "/computercraft dump"
|
||||||
|
[`queue`]: #queue "/computercraft queue"
|
||||||
|
[`shutdown`]: #shutdown "/computercraft shutdown"
|
||||||
|
[`tp`]: #tp "/computercraft tp"
|
||||||
|
[`track`]: #track "/computercraft track"
|
||||||
|
[`turn-on`]: #turn-on "/computercraft turn-on"
|
||||||
|
[`view`]: #view "/computercraft view"
|
||||||
|
[computer selectors]: #computer-selectors "Computer selectors"
|
@@ -9,17 +9,19 @@ SPDX-License-Identifier: MPL-2.0
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
# Lua 5.2/5.3 features in CC: Tweaked
|
# Lua 5.2/5.3 features in CC: Tweaked
|
||||||
CC: Tweaked is based off of the Cobalt Lua runtime, which uses Lua 5.1. However, Cobalt and CC:T implement additional features from Lua 5.2 and 5.3 (as well as some deprecated 5.0 features) that are not available in base 5.1. This page lists all of the compatibility for these newer versions.
|
CC: Tweaked is based off of the Cobalt Lua runtime, which uses Lua 5.2. However, Cobalt and CC:T implement additional
|
||||||
|
features from Lua 5.2 and 5.3 (as well as some deprecated 5.0 and 5.1 features). This page lists all of the
|
||||||
|
compatibility for these newer versions.
|
||||||
|
|
||||||
## Lua 5.2
|
## Lua 5.2
|
||||||
| Feature | Supported? | Notes |
|
| Feature | Supported? | Notes |
|
||||||
|---------------------------------------------------------------|------------|-------------------------------------------------------------------|
|
|---------------------------------------------------------------|------------|-------------------------------------------------------------------|
|
||||||
| `goto`/labels | ❌ | |
|
| `goto`/labels | ✔ | |
|
||||||
| `_ENV` | 🔶 | The `_ENV` global points to `getfenv()`, but it cannot be set. |
|
| `_ENV` | ✔ | |
|
||||||
| `\z` escape | ✔ | |
|
| `\z` escape | ✔ | |
|
||||||
| `\xNN` escape | ✔ | |
|
| `\xNN` escape | ✔ | |
|
||||||
| Hex literal fractional/exponent parts | ✔ | |
|
| Hex literal fractional/exponent parts | ✔ | |
|
||||||
| Empty statements | ❌ | |
|
| Empty statements | ✔ | |
|
||||||
| `__len` metamethod | ✔ | |
|
| `__len` metamethod | ✔ | |
|
||||||
| `__ipairs` metamethod | ❌ | Deprecated in Lua 5.3. `ipairs` uses `__len`/`__index` instead. |
|
| `__ipairs` metamethod | ❌ | Deprecated in Lua 5.3. `ipairs` uses `__len`/`__index` instead. |
|
||||||
| `__pairs` metamethod | ✔ | |
|
| `__pairs` metamethod | ✔ | |
|
||||||
@@ -27,12 +29,12 @@ CC: Tweaked is based off of the Cobalt Lua runtime, which uses Lua 5.1. However,
|
|||||||
| `collectgarbage` isrunning, generational, incremental options | ❌ | `collectgarbage` does not exist in CC:T. |
|
| `collectgarbage` isrunning, generational, incremental options | ❌ | `collectgarbage` does not exist in CC:T. |
|
||||||
| New `load` syntax | ✔ | |
|
| New `load` syntax | ✔ | |
|
||||||
| `loadfile` mode parameter | ✔ | Supports both 5.1 and 5.2+ syntax. |
|
| `loadfile` mode parameter | ✔ | Supports both 5.1 and 5.2+ syntax. |
|
||||||
| Removed `loadstring` | 🔶 | Only if `disable_lua51_features` is enabled in the configuration. |
|
| Removed `loadstring` | ❌ | |
|
||||||
| Removed `getfenv`, `setfenv` | 🔶 | Only if `disable_lua51_features` is enabled in the configuration. |
|
| Removed `getfenv`, `setfenv` | 🔶 | Only supports closures with an `_ENV` upvalue. |
|
||||||
| `rawlen` function | ✔ | |
|
| `rawlen` function | ✔ | |
|
||||||
| Negative index to `select` | ✔ | |
|
| Negative index to `select` | ✔ | |
|
||||||
| Removed `unpack` | 🔶 | Only if `disable_lua51_features` is enabled in the configuration. |
|
| Removed `unpack` | ❌ | |
|
||||||
| Arguments to `xpcall` | ✔ | |
|
| Arguments to `xpcall` | ✔ | |
|
||||||
| Second return value from `coroutine.running` | ✔ | |
|
| Second return value from `coroutine.running` | ✔ | |
|
||||||
| Removed `module` | ✔ | |
|
| Removed `module` | ✔ | |
|
||||||
| `package.loaders` -> `package.searchers` | ❌ | |
|
| `package.loaders` -> `package.searchers` | ❌ | |
|
||||||
@@ -40,14 +42,14 @@ CC: Tweaked is based off of the Cobalt Lua runtime, which uses Lua 5.1. However,
|
|||||||
| `package.config` | ✔ | |
|
| `package.config` | ✔ | |
|
||||||
| `package.searchpath` | ✔ | |
|
| `package.searchpath` | ✔ | |
|
||||||
| Removed `package.seeall` | ✔ | |
|
| Removed `package.seeall` | ✔ | |
|
||||||
| `string.dump` on functions with upvalues (blanks them out) | ✔ | |
|
| `string.dump` on functions with upvalues (blanks them out) | ❌ | `string.dump` is not supported |
|
||||||
| `string.rep` separator | ✔ | |
|
| `string.rep` separator | ✔ | |
|
||||||
| `%g` match group | ❌ | |
|
| `%g` match group | ❌ | |
|
||||||
| Removal of `%z` match group | ❌ | |
|
| Removal of `%z` match group | ❌ | |
|
||||||
| Removed `table.maxn` | 🔶 | Only if `disable_lua51_features` is enabled in the configuration. |
|
| Removed `table.maxn` | ❌ | |
|
||||||
| `table.pack`/`table.unpack` | ✔ | |
|
| `table.pack`/`table.unpack` | ✔ | |
|
||||||
| `math.log` base argument | ✔ | |
|
| `math.log` base argument | ✔ | |
|
||||||
| Removed `math.log10` | 🔶 | Only if `disable_lua51_features` is enabled in the configuration. |
|
| Removed `math.log10` | ❌ | |
|
||||||
| `*L` mode to `file:read` | ✔ | |
|
| `*L` mode to `file:read` | ✔ | |
|
||||||
| `os.execute` exit type + return value | ❌ | `os.execute` does not exist in CC:T. |
|
| `os.execute` exit type + return value | ❌ | `os.execute` does not exist in CC:T. |
|
||||||
| `os.exit` close argument | ❌ | `os.exit` does not exist in CC:T. |
|
| `os.exit` close argument | ❌ | `os.exit` does not exist in CC:T. |
|
||||||
@@ -61,7 +63,7 @@ CC: Tweaked is based off of the Cobalt Lua runtime, which uses Lua 5.1. However,
|
|||||||
| Tail call hooks | ❌ | |
|
| Tail call hooks | ❌ | |
|
||||||
| `=` prefix for chunks | ✔ | |
|
| `=` prefix for chunks | ✔ | |
|
||||||
| Yield across C boundary | ✔ | |
|
| Yield across C boundary | ✔ | |
|
||||||
| Removal of ambiguity error | ❌ | |
|
| Removal of ambiguity error | ✔ | |
|
||||||
| Identifiers may no longer use locale-dependent letters | ✔ | |
|
| Identifiers may no longer use locale-dependent letters | ✔ | |
|
||||||
| Ephemeron tables | ❌ | |
|
| Ephemeron tables | ❌ | |
|
||||||
| Identical functions may be reused | ❌ | Removed in Lua 5.4 |
|
| Identical functions may be reused | ❌ | Removed in Lua 5.4 |
|
||||||
@@ -79,7 +81,7 @@ CC: Tweaked is based off of the Cobalt Lua runtime, which uses Lua 5.1. However,
|
|||||||
| `string.dump` strip argument | ✔ | |
|
| `string.dump` strip argument | ✔ | |
|
||||||
| `string.pack`/`string.unpack`/`string.packsize` | ✔ | |
|
| `string.pack`/`string.unpack`/`string.packsize` | ✔ | |
|
||||||
| `table.move` | ✔ | |
|
| `table.move` | ✔ | |
|
||||||
| `math.atan2` -> `math.atan` | ❌ | |
|
| `math.atan2` -> `math.atan` | 🔶 | `math.atan` supports its two argument form. |
|
||||||
| Removed `math.frexp`, `math.ldexp`, `math.pow`, `math.cosh`, `math.sinh`, `math.tanh` | ❌ | |
|
| Removed `math.frexp`, `math.ldexp`, `math.pow`, `math.cosh`, `math.sinh`, `math.tanh` | ❌ | |
|
||||||
| `math.maxinteger`/`math.mininteger` | ❌ | |
|
| `math.maxinteger`/`math.mininteger` | ❌ | |
|
||||||
| `math.tointeger` | ❌ | |
|
| `math.tointeger` | ❌ | |
|
||||||
|
@@ -95,10 +95,10 @@ function pullEventRaw(filter) end
|
|||||||
-- nearest multiple of 0.05.
|
-- nearest multiple of 0.05.
|
||||||
function sleep(time) end
|
function sleep(time) end
|
||||||
|
|
||||||
--- Get the current CraftOS version (for example, `CraftOS 1.8`).
|
--- Get the current CraftOS version (for example, `CraftOS 1.9`).
|
||||||
--
|
--
|
||||||
-- This is defined by `bios.lua`. For the current version of CC:Tweaked, this
|
-- This is defined by `bios.lua`. For the current version of CC:Tweaked, this
|
||||||
-- should return `CraftOS 1.8`.
|
-- should return `CraftOS 1.9`.
|
||||||
--
|
--
|
||||||
-- @treturn string The current CraftOS version.
|
-- @treturn string The current CraftOS version.
|
||||||
-- @usage os.version()
|
-- @usage os.version()
|
||||||
|
@@ -2,15 +2,17 @@
|
|||||||
#
|
#
|
||||||
# SPDX-License-Identifier: MPL-2.0
|
# SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
org.gradle.jvmargs=-Xmx3G
|
org.gradle.jvmargs=-Xmx3G -Dfile.encoding=UTF-8
|
||||||
org.gradle.parallel=true
|
org.gradle.parallel=true
|
||||||
|
|
||||||
kotlin.stdlib.default.dependency=false
|
kotlin.stdlib.default.dependency=false
|
||||||
kotlin.jvm.target.validation.mode=error
|
kotlin.jvm.target.validation.mode=error
|
||||||
|
|
||||||
|
neogradle.subsystems.conventions.runs.enabled=false
|
||||||
|
|
||||||
# Mod properties
|
# Mod properties
|
||||||
isUnstable=false
|
isUnstable=true
|
||||||
modVersion=1.108.1
|
modVersion=1.116.0
|
||||||
|
|
||||||
# Minecraft properties: We want to configure this here so we can read it in settings.gradle
|
# Minecraft properties: We want to configure this here so we can read it in settings.gradle
|
||||||
mcVersion=1.20.1
|
mcVersion=1.21.1
|
||||||
|
2
gradle/gradle-daemon-jvm.properties
Normal file
2
gradle/gradle-daemon-jvm.properties
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
#This file is generated by updateDaemonJvm
|
||||||
|
toolchainVersion=21
|
@@ -6,161 +6,194 @@
|
|||||||
|
|
||||||
# Minecraft
|
# Minecraft
|
||||||
# MC version is specified in gradle.properties, as we need that in settings.gradle.
|
# MC version is specified in gradle.properties, as we need that in settings.gradle.
|
||||||
# Remember to update corresponding versions in fabric.mod.json/mods.toml
|
# Remember to update corresponding versions in fabric.mod.json/neoforge.mods.toml
|
||||||
fabric-api = "0.86.1+1.20.1"
|
fabric-api = "0.102.1+1.21.1"
|
||||||
fabric-loader = "0.14.21"
|
fabric-loader = "0.15.11"
|
||||||
forge = "47.1.0"
|
neoForge = "21.1.9"
|
||||||
forgeSpi = "6.0.0"
|
neoMergeTool = "2.0.0"
|
||||||
mixin = "0.8.5"
|
mixin = "0.8.5"
|
||||||
parchment = "2023.08.20"
|
parchment = "2024.07.28"
|
||||||
parchmentMc = "1.20.1"
|
parchmentMc = "1.21"
|
||||||
|
yarn = "1.21.1+build.1"
|
||||||
|
|
||||||
# Normal dependencies
|
# Core dependencies (these versions are tied to the version Minecraft uses)
|
||||||
asm = "9.5"
|
fastutil = "8.5.12"
|
||||||
|
guava = "32.1.2-jre"
|
||||||
|
netty = "4.1.97.Final"
|
||||||
|
slf4j = "2.0.9"
|
||||||
|
|
||||||
|
# Core dependencies (independent of Minecraft)
|
||||||
|
asm = "9.6"
|
||||||
autoService = "1.1.1"
|
autoService = "1.1.1"
|
||||||
checkerFramework = "3.32.0"
|
checkerFramework = "3.42.0"
|
||||||
cobalt = "0.7.3"
|
cobalt = { strictly = "0.9.6" }
|
||||||
cobalt-next = "0.7.4" # Not a real version, used to constrain the version we accept.
|
commonsCli = "1.6.0"
|
||||||
fastutil = "8.5.9"
|
jetbrainsAnnotations = "24.1.0"
|
||||||
guava = "31.1-jre"
|
jspecify = "1.0.0"
|
||||||
jetbrainsAnnotations = "24.0.1"
|
|
||||||
jsr305 = "3.0.2"
|
|
||||||
jzlib = "1.1.3"
|
jzlib = "1.1.3"
|
||||||
kotlin = "1.8.10"
|
kotlin = "2.1.10"
|
||||||
kotlin-coroutines = "1.6.4"
|
kotlin-coroutines = "1.10.1"
|
||||||
netty = "4.1.82.Final"
|
nightConfig = "3.8.1"
|
||||||
nightConfig = "3.6.7"
|
|
||||||
slf4j = "1.7.36"
|
|
||||||
|
|
||||||
# Minecraft mods
|
# Minecraft mods
|
||||||
emi = "1.0.8+1.20.1"
|
emi = "1.1.7+1.21"
|
||||||
fabricPermissions = "0.3.20230723"
|
fabricPermissions = "0.3.1"
|
||||||
iris = "1.6.4+1.20"
|
iris-fabric = "1.8.0-beta.3+1.21-fabric"
|
||||||
jei = "15.2.0.22"
|
iris-forge = "1.8.0-beta.3+1.21-neoforge"
|
||||||
modmenu = "7.1.0"
|
jei = "19.8.2.99"
|
||||||
moreRed = "4.0.0.4"
|
modmenu = "11.0.0-rc.4"
|
||||||
oculus = "1.2.5"
|
moreRed = "6.0.0.3"
|
||||||
rei = "12.0.626"
|
rei = "16.0.729"
|
||||||
rubidium = "0.6.1"
|
sodium-fabric = "mc1.21-0.6.0-beta.1-fabric"
|
||||||
sodium = "mc1.20-0.4.10"
|
sodium-forge = "mc1.21-0.6.0-beta.1-neoforge"
|
||||||
|
mixinExtra = "0.3.5"
|
||||||
|
create-forge = "6.0.0-6"
|
||||||
|
create-fabric = "0.5.1-f-build.1467+mc1.20.1"
|
||||||
|
|
||||||
# Testing
|
# Testing
|
||||||
byteBuddy = "1.14.7"
|
|
||||||
hamcrest = "2.2"
|
hamcrest = "2.2"
|
||||||
jqwik = "1.7.4"
|
jqwik = "1.8.2"
|
||||||
junit = "5.10.0"
|
junit = "5.11.4"
|
||||||
|
junitPlatform = "1.11.4"
|
||||||
|
jmh = "1.37"
|
||||||
|
|
||||||
# Build tools
|
# Build tools
|
||||||
cctJavadoc = "1.8.0"
|
cctJavadoc = "1.8.4"
|
||||||
checkstyle = "10.12.3"
|
checkstyle = "10.23.1"
|
||||||
curseForgeGradle = "1.0.14"
|
errorProne-core = "2.38.0"
|
||||||
errorProne-core = "2.21.1"
|
errorProne-plugin = "4.1.0"
|
||||||
errorProne-plugin = "3.1.0"
|
fabric-loom = "1.10.4"
|
||||||
fabric-loom = "1.3.7"
|
githubRelease = "2.5.2"
|
||||||
forgeGradle = "6.0.8"
|
gradleVersions = "0.50.0"
|
||||||
githubRelease = "2.4.1"
|
|
||||||
ideaExt = "1.1.7"
|
ideaExt = "1.1.7"
|
||||||
illuaminate = "0.1.0-40-g975cbc3"
|
illuaminate = "0.1.0-83-g1131f68"
|
||||||
librarian = "1.+"
|
lwjgl = "3.3.3"
|
||||||
minotaur = "2.+"
|
minotaur = "2.8.7"
|
||||||
mixinGradle = "0.7.+"
|
modDevGradle = "2.0.95"
|
||||||
nullAway = "0.9.9"
|
nullAway = "0.12.7"
|
||||||
spotless = "6.21.0"
|
shadow = "8.3.1"
|
||||||
|
spotless = "7.0.2"
|
||||||
taskTree = "2.1.1"
|
taskTree = "2.1.1"
|
||||||
vanillaGradle = "0.2.1-SNAPSHOT"
|
teavm = "0.11.0-SQUID.1"
|
||||||
vineflower = "1.11.0"
|
vanillaExtract = "0.2.1"
|
||||||
|
versionCatalogUpdate = "0.8.1"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
# Normal dependencies
|
# Normal dependencies
|
||||||
asm = { module = "org.ow2.asm:asm", version.ref = "asm" }
|
asm = { module = "org.ow2.asm:asm", version.ref = "asm" }
|
||||||
|
asm-commons = { module = "org.ow2.asm:asm-commons", version.ref = "asm" }
|
||||||
autoService = { module = "com.google.auto.service:auto-service", version.ref = "autoService" }
|
autoService = { module = "com.google.auto.service:auto-service", version.ref = "autoService" }
|
||||||
checkerFramework = { module = "org.checkerframework:checker-qual", version.ref = "checkerFramework" }
|
checkerFramework = { module = "org.checkerframework:checker-qual", version.ref = "checkerFramework" }
|
||||||
cobalt = { module = "org.squiddev:Cobalt", version.ref = "cobalt" }
|
cobalt = { module = "cc.tweaked:cobalt", version.ref = "cobalt" }
|
||||||
|
commonsCli = { module = "commons-cli:commons-cli", version.ref = "commonsCli" }
|
||||||
fastutil = { module = "it.unimi.dsi:fastutil", version.ref = "fastutil" }
|
fastutil = { module = "it.unimi.dsi:fastutil", version.ref = "fastutil" }
|
||||||
forgeSpi = { module = "net.minecraftforge:forgespi", version.ref = "forgeSpi" }
|
neoMergeTool = { module = "net.neoforged:mergetool", version.ref = "neoMergeTool" }
|
||||||
guava = { module = "com.google.guava:guava", version.ref = "guava" }
|
guava = { module = "com.google.guava:guava", version.ref = "guava" }
|
||||||
jetbrainsAnnotations = { module = "org.jetbrains:annotations", version.ref = "jetbrainsAnnotations" }
|
jetbrainsAnnotations = { module = "org.jetbrains:annotations", version.ref = "jetbrainsAnnotations" }
|
||||||
jsr305 = { module = "com.google.code.findbugs:jsr305", version.ref = "jsr305" }
|
jspecify = { module = "org.jspecify:jspecify", version.ref = "jspecify" }
|
||||||
jzlib = { module = "com.jcraft:jzlib", version.ref = "jzlib" }
|
jzlib = { module = "com.jcraft:jzlib", version.ref = "jzlib" }
|
||||||
kotlin-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlin-coroutines" }
|
kotlin-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlin-coroutines" }
|
||||||
kotlin-platform = { module = "org.jetbrains.kotlin:kotlin-bom", version.ref = "kotlin" }
|
kotlin-platform = { module = "org.jetbrains.kotlin:kotlin-bom", version.ref = "kotlin" }
|
||||||
kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" }
|
kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" }
|
||||||
|
netty-codec = { module = "io.netty:netty-codec", version.ref = "netty" }
|
||||||
netty-http = { module = "io.netty:netty-codec-http", version.ref = "netty" }
|
netty-http = { module = "io.netty:netty-codec-http", version.ref = "netty" }
|
||||||
netty-socks = { module = "io.netty:netty-codec-socks", version.ref = "netty" }
|
|
||||||
netty-proxy = { module = "io.netty:netty-handler-proxy", version.ref = "netty" }
|
netty-proxy = { module = "io.netty:netty-handler-proxy", version.ref = "netty" }
|
||||||
|
netty-socks = { module = "io.netty:netty-codec-socks", version.ref = "netty" }
|
||||||
nightConfig-core = { module = "com.electronwill.night-config:core", version.ref = "nightConfig" }
|
nightConfig-core = { module = "com.electronwill.night-config:core", version.ref = "nightConfig" }
|
||||||
nightConfig-toml = { module = "com.electronwill.night-config:toml", version.ref = "nightConfig" }
|
nightConfig-toml = { module = "com.electronwill.night-config:toml", version.ref = "nightConfig" }
|
||||||
slf4j = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" }
|
slf4j = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" }
|
||||||
|
|
||||||
# Minecraft mods
|
# Minecraft mods
|
||||||
|
create-fabric = { module = "com.simibubi.create:create-fabric-1.20.1", version.ref = "create-fabric" }
|
||||||
|
create-forge = { module = "com.simibubi.create:create-1.21.1", version.ref = "create-forge" }
|
||||||
|
emi = { module = "dev.emi:emi-xplat-mojmap", version.ref = "emi" }
|
||||||
fabric-api = { module = "net.fabricmc.fabric-api:fabric-api", version.ref = "fabric-api" }
|
fabric-api = { module = "net.fabricmc.fabric-api:fabric-api", version.ref = "fabric-api" }
|
||||||
|
fabric-junit = { module = "net.fabricmc:fabric-loader-junit", version.ref = "fabric-loader" }
|
||||||
fabric-loader = { module = "net.fabricmc:fabric-loader", version.ref = "fabric-loader" }
|
fabric-loader = { module = "net.fabricmc:fabric-loader", version.ref = "fabric-loader" }
|
||||||
fabricPermissions = { module = "me.lucko:fabric-permissions-api", version.ref = "fabricPermissions" }
|
fabricPermissions = { module = "me.lucko:fabric-permissions-api", version.ref = "fabricPermissions" }
|
||||||
emi = { module = "dev.emi:emi-xplat-mojmap", version.ref = "emi" }
|
iris-fabric = { module = "maven.modrinth:iris", version.ref = "iris-fabric" }
|
||||||
iris = { module = "maven.modrinth:iris", version.ref = "iris" }
|
iris-forge = { module = "maven.modrinth:iris", version.ref = "iris-forge" }
|
||||||
jei-api = { module = "mezz.jei:jei-1.20.1-common-api", version.ref = "jei" }
|
jei-api = { module = "mezz.jei:jei-1.21-common-api", version.ref = "jei" }
|
||||||
jei-fabric = { module = "mezz.jei:jei-1.20.1-fabric", version.ref = "jei" }
|
jei-fabric = { module = "mezz.jei:jei-1.21-fabric", version.ref = "jei" }
|
||||||
jei-forge = { module = "mezz.jei:jei-1.20.1-forge", version.ref = "jei" }
|
jei-forge = { module = "mezz.jei:jei-1.21-neoforge", version.ref = "jei" }
|
||||||
mixin = { module = "org.spongepowered:mixin", version.ref = "mixin" }
|
mixin = { module = "org.spongepowered:mixin", version.ref = "mixin" }
|
||||||
|
mixinExtra = { module = "io.github.llamalad7:mixinextras-common", version.ref = "mixinExtra" }
|
||||||
modmenu = { module = "com.terraformersmc:modmenu", version.ref = "modmenu" }
|
modmenu = { module = "com.terraformersmc:modmenu", version.ref = "modmenu" }
|
||||||
moreRed = { module = "commoble.morered:morered-1.20.1", version.ref = "moreRed" }
|
moreRed = { module = "net.commoble.morered:morered-1.21.1", version.ref = "moreRed" }
|
||||||
oculus = { module = "maven.modrinth:oculus", version.ref = "oculus" }
|
|
||||||
rei-api = { module = "me.shedaniel:RoughlyEnoughItems-api", version.ref = "rei" }
|
rei-api = { module = "me.shedaniel:RoughlyEnoughItems-api", version.ref = "rei" }
|
||||||
rei-builtin = { module = "me.shedaniel:RoughlyEnoughItems-default-plugin", version.ref = "rei" }
|
rei-builtin = { module = "me.shedaniel:RoughlyEnoughItems-default-plugin", version.ref = "rei" }
|
||||||
rei-fabric = { module = "me.shedaniel:RoughlyEnoughItems-fabric", version.ref = "rei" }
|
rei-fabric = { module = "me.shedaniel:RoughlyEnoughItems-fabric", version.ref = "rei" }
|
||||||
rubidium = { module = "maven.modrinth:rubidium", version.ref = "rubidium" }
|
sodium-fabric = { module = "maven.modrinth:sodium", version.ref = "sodium.fabric" }
|
||||||
sodium = { module = "maven.modrinth:sodium", version.ref = "sodium" }
|
sodium-forge = { module = "maven.modrinth:sodium", version.ref = "sodium.forge" }
|
||||||
|
|
||||||
# Testing
|
# Testing
|
||||||
byteBuddyAgent = { module = "net.bytebuddy:byte-buddy-agent", version.ref = "byteBuddy" }
|
|
||||||
byteBuddy = { module = "net.bytebuddy:byte-buddy", version.ref = "byteBuddy" }
|
|
||||||
hamcrest = { module = "org.hamcrest:hamcrest", version.ref = "hamcrest" }
|
hamcrest = { module = "org.hamcrest:hamcrest", version.ref = "hamcrest" }
|
||||||
jqwik-api = { module = "net.jqwik:jqwik-api", version.ref = "jqwik" }
|
jqwik-api = { module = "net.jqwik:jqwik-api", version.ref = "jqwik" }
|
||||||
jqwik-engine = { module = "net.jqwik:jqwik-engine", version.ref = "jqwik" }
|
jqwik-engine = { module = "net.jqwik:jqwik-engine", version.ref = "jqwik" }
|
||||||
junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "junit" }
|
junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "junit" }
|
||||||
junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "junit" }
|
junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "junit" }
|
||||||
junit-jupiter-params = { module = "org.junit.jupiter:junit-jupiter-params", version.ref = "junit" }
|
junit-jupiter-params = { module = "org.junit.jupiter:junit-jupiter-params", version.ref = "junit" }
|
||||||
|
junit-platform-launcher = { module = "org.junit.platform:junit-platform-launcher", version.ref = "junitPlatform" }
|
||||||
slf4j-simple = { module = "org.slf4j:slf4j-simple", version.ref = "slf4j" }
|
slf4j-simple = { module = "org.slf4j:slf4j-simple", version.ref = "slf4j" }
|
||||||
|
jmh = { module = "org.openjdk.jmh:jmh-core", version.ref = "jmh" }
|
||||||
|
jmh-processor = { module = "org.openjdk.jmh:jmh-generator-annprocess", version.ref = "jmh" }
|
||||||
|
|
||||||
|
# LWJGL
|
||||||
|
lwjgl-bom = { module = "org.lwjgl:lwjgl-bom", version.ref = "lwjgl" }
|
||||||
|
lwjgl-core = { module = "org.lwjgl:lwjgl" }
|
||||||
|
lwjgl-opengl = { module = "org.lwjgl:lwjgl-opengl" }
|
||||||
|
lwjgl-glfw = { module = "org.lwjgl:lwjgl-glfw" }
|
||||||
|
|
||||||
# Build tools
|
# Build tools
|
||||||
cctJavadoc = { module = "cc.tweaked:cct-javadoc", version.ref = "cctJavadoc" }
|
cctJavadoc = { module = "cc.tweaked:cct-javadoc", version.ref = "cctJavadoc" }
|
||||||
checkstyle = { module = "com.puppycrawl.tools:checkstyle", version.ref = "checkstyle" }
|
checkstyle = { module = "com.puppycrawl.tools:checkstyle", version.ref = "checkstyle" }
|
||||||
curseForgeGradle = { module = "net.darkhax.curseforgegradle:CurseForgeGradle", version.ref = "curseForgeGradle" }
|
|
||||||
errorProne-annotations = { module = "com.google.errorprone:error_prone_annotations", version.ref = "errorProne-core" }
|
errorProne-annotations = { module = "com.google.errorprone:error_prone_annotations", version.ref = "errorProne-core" }
|
||||||
errorProne-api = { module = "com.google.errorprone:error_prone_check_api", version.ref = "errorProne-core" }
|
errorProne-api = { module = "com.google.errorprone:error_prone_check_api", version.ref = "errorProne-core" }
|
||||||
errorProne-core = { module = "com.google.errorprone:error_prone_core", version.ref = "errorProne-core" }
|
errorProne-core = { module = "com.google.errorprone:error_prone_core", version.ref = "errorProne-core" }
|
||||||
errorProne-plugin = { module = "net.ltgt.gradle:gradle-errorprone-plugin", version.ref = "errorProne-plugin" }
|
errorProne-plugin = { module = "net.ltgt.gradle:gradle-errorprone-plugin", version.ref = "errorProne-plugin" }
|
||||||
errorProne-testHelpers = { module = "com.google.errorprone:error_prone_test_helpers", version.ref = "errorProne-core" }
|
errorProne-testHelpers = { module = "com.google.errorprone:error_prone_test_helpers", version.ref = "errorProne-core" }
|
||||||
fabric-loom = { module = "net.fabricmc:fabric-loom", version.ref = "fabric-loom" }
|
fabric-loom = { module = "net.fabricmc:fabric-loom", version.ref = "fabric-loom" }
|
||||||
forgeGradle = { module = "net.minecraftforge.gradle:ForgeGradle", version.ref = "forgeGradle" }
|
ideaExt = { module = "gradle.plugin.org.jetbrains.gradle.plugin.idea-ext:gradle-idea-ext", version.ref = "ideaExt" }
|
||||||
kotlin-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
|
kotlin-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
|
||||||
librarian = { module = "org.parchmentmc:librarian", version.ref = "librarian" }
|
|
||||||
minotaur = { module = "com.modrinth.minotaur:Minotaur", version.ref = "minotaur" }
|
minotaur = { module = "com.modrinth.minotaur:Minotaur", version.ref = "minotaur" }
|
||||||
nullAway = { module = "com.uber.nullaway:nullaway", version.ref = "nullAway" }
|
nullAway = { module = "com.uber.nullaway:nullaway", version.ref = "nullAway" }
|
||||||
|
modDevGradle = { module = "net.neoforged:moddev-gradle", version.ref = "modDevGradle" }
|
||||||
spotless = { module = "com.diffplug.spotless:spotless-plugin-gradle", version.ref = "spotless" }
|
spotless = { module = "com.diffplug.spotless:spotless-plugin-gradle", version.ref = "spotless" }
|
||||||
vanillaGradle = { module = "org.spongepowered:vanillagradle", version.ref = "vanillaGradle" }
|
teavm-classlib = { module = "org.teavm:teavm-classlib", version.ref = "teavm" }
|
||||||
vineflower = { module = "io.github.juuxel:loom-vineflower", version.ref = "vineflower" }
|
teavm-core = { module = "org.teavm:teavm-core", version.ref = "teavm" }
|
||||||
|
teavm-jso = { module = "org.teavm:teavm-jso", version.ref = "teavm" }
|
||||||
|
teavm-jso-apis = { module = "org.teavm:teavm-jso-apis", version.ref = "teavm" }
|
||||||
|
teavm-jso-impl = { module = "org.teavm:teavm-jso-impl", version.ref = "teavm" }
|
||||||
|
teavm-metaprogramming-api = { module = "org.teavm:teavm-metaprogramming-api", version.ref = "teavm" }
|
||||||
|
teavm-metaprogramming-impl = { module = "org.teavm:teavm-metaprogramming-impl", version.ref = "teavm" }
|
||||||
|
teavm-platform = { module = "org.teavm:teavm-platform", version.ref = "teavm" }
|
||||||
|
teavm-tooling = { module = "org.teavm:teavm-tooling", version.ref = "teavm" }
|
||||||
|
vanillaExtract = { module = "cc.tweaked.vanilla-extract:plugin", version.ref = "vanillaExtract" }
|
||||||
|
yarn = { module = "net.fabricmc:yarn", version.ref = "yarn" }
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
forgeGradle = { id = "net.minecraftforge.gradle", version.ref = "forgeGradle" }
|
|
||||||
githubRelease = { id = "com.github.breadmoirai.github-release", version.ref = "githubRelease" }
|
githubRelease = { id = "com.github.breadmoirai.github-release", version.ref = "githubRelease" }
|
||||||
ideaExt = { id = "org.jetbrains.gradle.plugin.idea-ext", version.ref = "ideaExt" }
|
gradleVersions = { id = "com.github.ben-manes.versions", version.ref = "gradleVersions" }
|
||||||
kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
|
kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
|
||||||
librarian = { id = "org.parchmentmc.librarian.forgegradle", version.ref = "librarian" }
|
shadow = { id = "com.gradleup.shadow", version.ref = "shadow" }
|
||||||
mixinGradle = { id = "org.spongepowered.mixin", version.ref = "mixinGradle" }
|
|
||||||
taskTree = { id = "com.dorongold.task-tree", version.ref = "taskTree" }
|
taskTree = { id = "com.dorongold.task-tree", version.ref = "taskTree" }
|
||||||
|
versionCatalogUpdate = { id = "nl.littlerobots.version-catalog-update", version.ref = "versionCatalogUpdate" }
|
||||||
|
|
||||||
[bundles]
|
[bundles]
|
||||||
|
annotations = ["checkerFramework", "jetbrainsAnnotations", "jspecify"]
|
||||||
kotlin = ["kotlin-stdlib", "kotlin-coroutines"]
|
kotlin = ["kotlin-stdlib", "kotlin-coroutines"]
|
||||||
|
|
||||||
# Minecraft
|
# Minecraft
|
||||||
externalMods-common = ["jei-api", "nightConfig-core", "nightConfig-toml"]
|
externalMods-common = ["iris-forge", "jei-api", "nightConfig-core", "nightConfig-toml"]
|
||||||
externalMods-forge-compile = ["moreRed", "oculus", "jei-api"]
|
externalMods-forge-compile = ["moreRed", "iris-forge", "jei-api"]
|
||||||
externalMods-forge-runtime = ["jei-forge"]
|
externalMods-forge-runtime = ["jei-forge"]
|
||||||
externalMods-fabric = ["nightConfig-core", "nightConfig-toml"]
|
externalMods-fabric-compile = ["fabricPermissions", "iris-fabric", "jei-api", "rei-api", "rei-builtin"]
|
||||||
externalMods-fabric-compile = ["fabricPermissions", "iris", "jei-api", "rei-api", "rei-builtin"]
|
|
||||||
externalMods-fabric-runtime = ["jei-fabric", "modmenu"]
|
externalMods-fabric-runtime = ["jei-fabric", "modmenu"]
|
||||||
|
|
||||||
# Testing
|
# Testing
|
||||||
test = ["junit-jupiter-api", "junit-jupiter-params", "hamcrest", "jqwik-api"]
|
test = ["junit-jupiter-api", "junit-jupiter-params", "hamcrest", "jqwik-api"]
|
||||||
testRuntime = ["junit-jupiter-engine", "jqwik-engine"]
|
testRuntime = ["junit-jupiter-engine", "junit-platform-launcher", "jqwik-engine"]
|
||||||
|
|
||||||
|
# Build tools
|
||||||
|
teavm-api = ["teavm-jso", "teavm-jso-apis", "teavm-platform", "teavm-classlib", "teavm-metaprogramming-api"]
|
||||||
|
teavm-tooling = ["teavm-tooling", "teavm-metaprogramming-impl", "teavm-jso-impl"]
|
||||||
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
3
gradle/wrapper/gradle-wrapper.properties
vendored
3
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,7 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
26
gradlew
vendored
26
gradlew
vendored
@@ -15,6 +15,8 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
#
|
#
|
||||||
@@ -55,7 +57,7 @@
|
|||||||
# Darwin, MinGW, and NonStop.
|
# Darwin, MinGW, and NonStop.
|
||||||
#
|
#
|
||||||
# (3) This script is generated from the Groovy template
|
# (3) This script is generated from the Groovy template
|
||||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||||
# within the Gradle project.
|
# within the Gradle project.
|
||||||
#
|
#
|
||||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||||
@@ -83,7 +85,8 @@ done
|
|||||||
# This is normally unused
|
# This is normally unused
|
||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
APP_BASE_NAME=${0##*/}
|
APP_BASE_NAME=${0##*/}
|
||||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||||
|
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD=maximum
|
MAX_FD=maximum
|
||||||
@@ -130,10 +133,13 @@ location of your Java installation."
|
|||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
JAVACMD=java
|
JAVACMD=java
|
||||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
if ! command -v java >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
Please set the JAVA_HOME variable in your environment to match the
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
location of your Java installation."
|
location of your Java installation."
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Increase the maximum file descriptors if we can.
|
# Increase the maximum file descriptors if we can.
|
||||||
@@ -141,7 +147,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
|||||||
case $MAX_FD in #(
|
case $MAX_FD in #(
|
||||||
max*)
|
max*)
|
||||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||||
# shellcheck disable=SC3045
|
# shellcheck disable=SC2039,SC3045
|
||||||
MAX_FD=$( ulimit -H -n ) ||
|
MAX_FD=$( ulimit -H -n ) ||
|
||||||
warn "Could not query maximum file descriptor limit"
|
warn "Could not query maximum file descriptor limit"
|
||||||
esac
|
esac
|
||||||
@@ -149,7 +155,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
|||||||
'' | soft) :;; #(
|
'' | soft) :;; #(
|
||||||
*)
|
*)
|
||||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||||
# shellcheck disable=SC3045
|
# shellcheck disable=SC2039,SC3045
|
||||||
ulimit -n "$MAX_FD" ||
|
ulimit -n "$MAX_FD" ||
|
||||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||||
esac
|
esac
|
||||||
@@ -198,11 +204,11 @@ fi
|
|||||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
# Collect all arguments for the java command;
|
# Collect all arguments for the java command:
|
||||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||||
# shell script including quotes and variable substitutions, so put them in
|
# and any embedded shellness will be escaped.
|
||||||
# double quotes to make sure that they get re-expanded; and
|
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||||
# * put everything else in single quotes, so that it's not re-expanded.
|
# treated as '${Hostname}' itself on the command line.
|
||||||
|
|
||||||
set -- \
|
set -- \
|
||||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||||
|
22
gradlew.bat
vendored
22
gradlew.bat
vendored
@@ -13,6 +13,8 @@
|
|||||||
@rem See the License for the specific language governing permissions and
|
@rem See the License for the specific language governing permissions and
|
||||||
@rem limitations under the License.
|
@rem limitations under the License.
|
||||||
@rem
|
@rem
|
||||||
|
@rem SPDX-License-Identifier: Apache-2.0
|
||||||
|
@rem
|
||||||
|
|
||||||
@if "%DEBUG%"=="" @echo off
|
@if "%DEBUG%"=="" @echo off
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
@@ -43,11 +45,11 @@ set JAVA_EXE=java.exe
|
|||||||
%JAVA_EXE% -version >NUL 2>&1
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
if %ERRORLEVEL% equ 0 goto execute
|
if %ERRORLEVEL% equ 0 goto execute
|
||||||
|
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
echo location of your Java installation.
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
@@ -57,11 +59,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
|||||||
|
|
||||||
if exist "%JAVA_EXE%" goto execute
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
echo location of your Java installation.
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
|
@@ -2,15 +2,15 @@
|
|||||||
|
|
||||||
; SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
; SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
||||||
;
|
;
|
||||||
; SPDX-License-Identifier: LicenseRef-CCPL
|
; SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
(sources
|
(sources
|
||||||
/doc/
|
/doc/
|
||||||
/projects/forge/build/docs/luaJavadoc/
|
/projects/common/build/docs/luaJavadoc/
|
||||||
/projects/core/src/main/resources/data/computercraft/lua/bios.lua
|
/projects/core/src/main/resources/data/computercraft/lua/bios.lua
|
||||||
/projects/core/src/main/resources/data/computercraft/lua/rom/
|
/projects/core/src/main/resources/data/computercraft/lua/rom/
|
||||||
/projects/core/src/test/resources/test-rom
|
/projects/core/src/test/resources/test-rom
|
||||||
/projects/web/src/mount)
|
/projects/web/src/frontend/mount)
|
||||||
|
|
||||||
(doc
|
(doc
|
||||||
; Also defined in projects/web/build.gradle.kts
|
; Also defined in projects/web/build.gradle.kts
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
(url https://tweaked.cc/)
|
(url https://tweaked.cc/)
|
||||||
(source-link https://github.com/cc-tweaked/CC-Tweaked/blob/${commit}/${path}#L${line})
|
(source-link https://github.com/cc-tweaked/CC-Tweaked/blob/${commit}/${path}#L${line})
|
||||||
|
|
||||||
(styles /projects/web/src/styles.css)
|
(styles /projects/web/build/rollup/index.css)
|
||||||
(scripts /projects/web/build/rollup/index.js)
|
(scripts /projects/web/build/rollup/index.js)
|
||||||
(head doc/head.html))
|
(head doc/head.html))
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
|
|
||||||
(library-path
|
(library-path
|
||||||
/doc/stub/
|
/doc/stub/
|
||||||
/projects/forge/build/docs/luaJavadoc/
|
/projects/common/build/docs/luaJavadoc/
|
||||||
|
|
||||||
/projects/core/src/main/resources/data/computercraft/lua/rom/apis/
|
/projects/core/src/main/resources/data/computercraft/lua/rom/apis/
|
||||||
/projects/core/src/main/resources/data/computercraft/lua/rom/apis/command/
|
/projects/core/src/main/resources/data/computercraft/lua/rom/apis/command/
|
||||||
@@ -77,7 +77,6 @@
|
|||||||
(globals
|
(globals
|
||||||
:max
|
:max
|
||||||
_CC_DEFAULT_SETTINGS
|
_CC_DEFAULT_SETTINGS
|
||||||
_CC_DISABLE_LUA51_FEATURES
|
|
||||||
_HOST
|
_HOST
|
||||||
;; Ideally we'd pick these up from bios.lua, but illuaminate currently
|
;; Ideally we'd pick these up from bios.lua, but illuaminate currently
|
||||||
;; isn't smart enough.
|
;; isn't smart enough.
|
||||||
@@ -89,7 +88,7 @@
|
|||||||
(/doc/stub/
|
(/doc/stub/
|
||||||
/projects/core/src/main/resources/data/computercraft/lua/bios.lua
|
/projects/core/src/main/resources/data/computercraft/lua/bios.lua
|
||||||
/projects/core/src/main/resources/data/computercraft/lua/rom/apis/
|
/projects/core/src/main/resources/data/computercraft/lua/rom/apis/
|
||||||
/projects/forge/build/docs/luaJavadoc/)
|
/projects/common/build/docs/luaJavadoc/)
|
||||||
(linters -var:unused-global)
|
(linters -var:unused-global)
|
||||||
(lint (allow-toplevel-global true)))
|
(lint (allow-toplevel-global true)))
|
||||||
|
|
||||||
@@ -106,6 +105,10 @@
|
|||||||
/projects/core/src/main/resources/data/computercraft/lua/rom/apis/turtle/turtle.lua)
|
/projects/core/src/main/resources/data/computercraft/lua/rom/apis/turtle/turtle.lua)
|
||||||
(linters -var:deprecated))
|
(linters -var:deprecated))
|
||||||
|
|
||||||
|
;; Suppress unused variable warnings in the parser.
|
||||||
|
(at /projects/core/src/main/resources/data/computercraft/lua/rom/modules/main/cc/internal/syntax/parser.lua
|
||||||
|
(linters -var:unused))
|
||||||
|
|
||||||
(at /projects/core/src/test/resources/test-rom
|
(at /projects/core/src/test/resources/test-rom
|
||||||
; We should still be able to test deprecated members.
|
; We should still be able to test deprecated members.
|
||||||
(linters -var:deprecated)
|
(linters -var:deprecated)
|
||||||
@@ -115,4 +118,4 @@
|
|||||||
:max sleep write
|
:max sleep write
|
||||||
cct_test describe expect howlci fail it pending stub before_each)))
|
cct_test describe expect howlci fail it pending stub before_each)))
|
||||||
|
|
||||||
(at /projects/web/src/mount/expr_template.lua (lint (globals :max __expr__)))
|
(at /projects/web/src/frontend/mount/expr_template.lua (lint (globals :max __expr__)))
|
||||||
|
5065
package-lock.json
generated
5065
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
26
package.json
26
package.json
@@ -6,24 +6,24 @@
|
|||||||
"license": "BSD-3-Clause",
|
"license": "BSD-3-Clause",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@squid-dev/cc-web-term": "^2.0.0",
|
||||||
"preact": "^10.5.5",
|
"preact": "^10.5.5",
|
||||||
|
"setimmediate": "^1.0.5",
|
||||||
"tslib": "^2.0.3"
|
"tslib": "^2.0.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@rollup/plugin-terser": "^0.4.0",
|
"@rollup/plugin-node-resolve": "^16.0.0",
|
||||||
"@rollup/plugin-typescript": "^11.0.0",
|
"@rollup/plugin-typescript": "^12.0.0 && <12.1.3",
|
||||||
"@rollup/plugin-url": "^8.0.1",
|
"@rollup/plugin-url": "^8.0.1",
|
||||||
"@types/glob": "^8.1.0",
|
"@swc/core": "^1.3.92",
|
||||||
"@types/react-dom": "^18.0.5",
|
"@types/node": "^24.0.0",
|
||||||
"glob": "^10.3.4",
|
"lightningcss": "^1.22.0",
|
||||||
"react-dom": "^18.1.0",
|
"preact-render-to-string": "^6.2.1",
|
||||||
"react": "^18.1.0",
|
"rehype": "^13.0.0",
|
||||||
"rehype-highlight": "^6.0.0",
|
"rehype-highlight": "^7.0.0",
|
||||||
"rehype-react": "^7.1.1",
|
"rehype-react": "^8.0.0",
|
||||||
"rehype": "^12.0.0",
|
"rollup": "^4.0.0",
|
||||||
"requirejs": "^2.3.6",
|
"tsx": "^4.7.0",
|
||||||
"rollup": "^3.19.1",
|
|
||||||
"ts-node": "^10.8.0",
|
|
||||||
"typescript": "^5.2.2"
|
"typescript": "^5.2.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -62,6 +62,9 @@ mentioning:
|
|||||||
- `lints`: This defines an [ErrorProne] plugin which adds a couple of compile-time checks to our code. This is what
|
- `lints`: This defines an [ErrorProne] plugin which adds a couple of compile-time checks to our code. This is what
|
||||||
enforces that no client-specific code is used inside the `main` source set (and a couple of other things!).
|
enforces that no client-specific code is used inside the `main` source set (and a couple of other things!).
|
||||||
|
|
||||||
|
- `standalone`: This contains a standalone UI for computers, allowing debugging and development of CraftOS without
|
||||||
|
launching Minecraft.
|
||||||
|
|
||||||
- `web`: This contains the additional tooling for building [the documentation website][tweaked.cc], such as support for
|
- `web`: This contains the additional tooling for building [the documentation website][tweaked.cc], such as support for
|
||||||
rendering recipes
|
rendering recipes
|
||||||
|
|
||||||
|
@@ -8,6 +8,8 @@ plugins {
|
|||||||
id("cc-tweaked.vanilla")
|
id("cc-tweaked.vanilla")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val mcVersion: String by extra
|
||||||
|
|
||||||
java {
|
java {
|
||||||
withJavadocJar()
|
withJavadocJar()
|
||||||
}
|
}
|
||||||
@@ -16,9 +18,70 @@ dependencies {
|
|||||||
api(project(":core-api"))
|
api(project(":core-api"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val javadocOverview by tasks.registering(Copy::class) {
|
||||||
|
from("src/overview.html")
|
||||||
|
into(layout.buildDirectory.dir(name))
|
||||||
|
|
||||||
|
expand(
|
||||||
|
mapOf(
|
||||||
|
"mcVersion" to mcVersion,
|
||||||
|
"modVersion" to version,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
tasks.javadoc {
|
tasks.javadoc {
|
||||||
|
title = "CC: Tweaked $version for Minecraft $mcVersion"
|
||||||
include("dan200/computercraft/api/**/*.java")
|
include("dan200/computercraft/api/**/*.java")
|
||||||
|
|
||||||
|
options {
|
||||||
|
(this as StandardJavadocDocletOptions)
|
||||||
|
|
||||||
|
inputs.files(javadocOverview)
|
||||||
|
overview(javadocOverview.get().destinationDir.resolve("overview.html").absolutePath)
|
||||||
|
|
||||||
|
groups = mapOf(
|
||||||
|
"Common" to listOf(
|
||||||
|
"dan200.computercraft.api",
|
||||||
|
"dan200.computercraft.api.lua",
|
||||||
|
"dan200.computercraft.api.peripheral",
|
||||||
|
),
|
||||||
|
"Upgrades" to listOf(
|
||||||
|
"dan200.computercraft.api.client.turtle",
|
||||||
|
"dan200.computercraft.api.pocket",
|
||||||
|
"dan200.computercraft.api.turtle",
|
||||||
|
"dan200.computercraft.api.upgrades",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
addBooleanOption("-allow-script-in-comments", true)
|
||||||
|
bottom(
|
||||||
|
"""
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/prismjs@v1.29.0/components/prism-core.min.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/prismjs@v1.29.0/plugins/autoloader/prism-autoloader.min.js"></script>
|
||||||
|
<link href=" https://cdn.jsdelivr.net/npm/prismjs@1.29.0/themes/prism.min.css " rel="stylesheet">
|
||||||
|
""".trimIndent(),
|
||||||
|
)
|
||||||
|
|
||||||
|
val snippetSources = listOf(":common", ":fabric", ":forge").flatMap {
|
||||||
|
project(it).sourceSets["examples"].allSource.sourceDirectories
|
||||||
|
}
|
||||||
|
inputs.files(snippetSources)
|
||||||
|
addPathOption("-snippet-path").value = snippetSources
|
||||||
|
}
|
||||||
|
|
||||||
// Include the core-api in our javadoc export. This is wrong, but it means we can export a single javadoc dump.
|
// Include the core-api in our javadoc export. This is wrong, but it means we can export a single javadoc dump.
|
||||||
source(project(":core-api").sourceSets.main.map { it.allJava })
|
source(project(":core-api").sourceSets.main.map { it.allJava })
|
||||||
|
|
||||||
|
options {
|
||||||
|
this as StandardJavadocDocletOptions
|
||||||
|
addBooleanOption("-allow-script-in-comments", true)
|
||||||
|
bottom(
|
||||||
|
"""
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/prismjs@v1.29.0/components/prism-core.min.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/prismjs@v1.29.0/plugins/autoloader/prism-autoloader.min.js"></script>
|
||||||
|
<link href=" https://cdn.jsdelivr.net/npm/prismjs@1.29.0/themes/prism.min.css " rel="stylesheet">
|
||||||
|
""".trimIndent(),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,38 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2022 The CC: Tweaked Developers
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
package dan200.computercraft.api.client;
|
|
||||||
|
|
||||||
import dan200.computercraft.api.client.turtle.TurtleUpgradeModeller;
|
|
||||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
|
||||||
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
|
||||||
import dan200.computercraft.impl.client.ComputerCraftAPIClientService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The public API for client-only code.
|
|
||||||
*
|
|
||||||
* @see dan200.computercraft.api.ComputerCraftAPI The main API
|
|
||||||
*/
|
|
||||||
public final class ComputerCraftAPIClient {
|
|
||||||
private ComputerCraftAPIClient() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register a {@link TurtleUpgradeModeller} for a class of turtle upgrades.
|
|
||||||
* <p>
|
|
||||||
* This may be called at any point after registry creation, though it is recommended to call it within your client
|
|
||||||
* setup step.
|
|
||||||
*
|
|
||||||
* @param serialiser The turtle upgrade serialiser.
|
|
||||||
* @param modeller The upgrade modeller.
|
|
||||||
* @param <T> The type of the turtle upgrade.
|
|
||||||
*/
|
|
||||||
public static <T extends ITurtleUpgrade> void registerTurtleUpgradeModeller(TurtleUpgradeSerialiser<T> serialiser, TurtleUpgradeModeller<T> modeller) {
|
|
||||||
getInstance().registerTurtleUpgradeModeller(serialiser, modeller);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ComputerCraftAPIClientService getInstance() {
|
|
||||||
return ComputerCraftAPIClientService.get();
|
|
||||||
}
|
|
||||||
}
|
|
@@ -0,0 +1,84 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
package dan200.computercraft.api.client;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.client.turtle.TurtleUpgradeModeller;
|
||||||
|
import dan200.computercraft.impl.client.ClientPlatformHelper;
|
||||||
|
import net.minecraft.client.resources.model.BakedModel;
|
||||||
|
import net.minecraft.client.resources.model.ModelManager;
|
||||||
|
import net.minecraft.client.resources.model.ModelResourceLocation;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The location of a model to load. This may either be:
|
||||||
|
*
|
||||||
|
* <ul>
|
||||||
|
* <li>A {@link ModelResourceLocation}, referencing an already baked model (such as {@code minecraft:dirt#inventory}).</li>
|
||||||
|
* <li>
|
||||||
|
* A {@link ResourceLocation}, referencing a path to a model resource (such as {@code minecraft:item/dirt}.
|
||||||
|
* These models will be baked and stored in the {@link ModelManager} in a loader-specific way.
|
||||||
|
* </li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public final class ModelLocation {
|
||||||
|
/**
|
||||||
|
* The location of the model.
|
||||||
|
* <p>
|
||||||
|
* When {@link #resourceLocation} is null, this is the location of the model to load. When {@link #resourceLocation}
|
||||||
|
* is non-null, this is the "standalone" variant of the model resource — this is used by NeoForge's implementation
|
||||||
|
* of {@link ClientPlatformHelper#getModel(ModelManager, ModelResourceLocation, ResourceLocation)} to fetch the
|
||||||
|
* model from the model manger. It is not used on Fabric.
|
||||||
|
*/
|
||||||
|
private final ModelResourceLocation modelLocation;
|
||||||
|
private final @Nullable ResourceLocation resourceLocation;
|
||||||
|
|
||||||
|
private ModelLocation(ModelResourceLocation modelLocation, @Nullable ResourceLocation resourceLocation) {
|
||||||
|
this.modelLocation = modelLocation;
|
||||||
|
this.resourceLocation = resourceLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a {@link ModelLocation} from model in the model manager.
|
||||||
|
*
|
||||||
|
* @param location The name of the model to load.
|
||||||
|
* @return The new {@link ModelLocation} instance.
|
||||||
|
*/
|
||||||
|
public static ModelLocation ofModel(ModelResourceLocation location) {
|
||||||
|
return new ModelLocation(location, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a {@link ModelLocation} from a resource.
|
||||||
|
*
|
||||||
|
* @param location The location of the model resource, such as {@code minecraft:item/dirt}.
|
||||||
|
* @return The new {@link ModelLocation} instance.
|
||||||
|
*/
|
||||||
|
public static ModelLocation ofResource(ResourceLocation location) {
|
||||||
|
return new ModelLocation(new ModelResourceLocation(location, "standalone"), location);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get this model from the provided model manager.
|
||||||
|
*
|
||||||
|
* @param manager The model manger.
|
||||||
|
* @return This model, or the missing model if it could not be found.
|
||||||
|
*/
|
||||||
|
public BakedModel getModel(ModelManager manager) {
|
||||||
|
return ClientPlatformHelper.get().getModel(manager, modelLocation, resourceLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the models this model location depends on.
|
||||||
|
*
|
||||||
|
* @return A list of models that this model location depends on.
|
||||||
|
* @see TurtleUpgradeModeller#getDependencies()
|
||||||
|
*/
|
||||||
|
public Stream<ResourceLocation> getDependencies() {
|
||||||
|
return resourceLocation == null ? Stream.empty() : Stream.of(resourceLocation);
|
||||||
|
}
|
||||||
|
}
|
@@ -13,30 +13,47 @@ import net.minecraft.client.resources.model.ModelResourceLocation;
|
|||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A model to render, combined with a transformation matrix to apply.
|
* A model to render, combined with a transformation matrix to apply.
|
||||||
|
*
|
||||||
|
* @param model The model.
|
||||||
|
* @param matrix The transformation matrix.
|
||||||
*/
|
*/
|
||||||
public final class TransformedModel {
|
public record TransformedModel(BakedModel model, Transformation matrix) {
|
||||||
private final BakedModel model;
|
|
||||||
private final Transformation matrix;
|
|
||||||
|
|
||||||
public TransformedModel(BakedModel model, Transformation matrix) {
|
|
||||||
this.model = Objects.requireNonNull(model);
|
|
||||||
this.matrix = Objects.requireNonNull(matrix);
|
|
||||||
}
|
|
||||||
|
|
||||||
public TransformedModel(BakedModel model) {
|
public TransformedModel(BakedModel model) {
|
||||||
this.model = Objects.requireNonNull(model);
|
this(model, Transformation.identity());
|
||||||
matrix = Transformation.identity();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Look up a model in the model bakery and construct a {@link TransformedModel} with no transformation.
|
||||||
|
*
|
||||||
|
* @param location The location of the model to load.
|
||||||
|
* @return The new {@link TransformedModel} instance.
|
||||||
|
*/
|
||||||
|
public static TransformedModel of(ModelLocation location) {
|
||||||
|
var modelManager = Minecraft.getInstance().getModelManager();
|
||||||
|
return new TransformedModel(location.getModel(modelManager));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Look up a model in the model bakery and construct a {@link TransformedModel} with no transformation.
|
||||||
|
*
|
||||||
|
* @param location The location of the model to load.
|
||||||
|
* @return The new {@link TransformedModel} instance.
|
||||||
|
* @see ModelLocation#ofModel(ModelResourceLocation)
|
||||||
|
*/
|
||||||
public static TransformedModel of(ModelResourceLocation location) {
|
public static TransformedModel of(ModelResourceLocation location) {
|
||||||
var modelManager = Minecraft.getInstance().getModelManager();
|
var modelManager = Minecraft.getInstance().getModelManager();
|
||||||
return new TransformedModel(modelManager.getModel(location));
|
return new TransformedModel(modelManager.getModel(location));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Look up a model in the model bakery and construct a {@link TransformedModel} with no transformation.
|
||||||
|
*
|
||||||
|
* @param location The location of the model to load.
|
||||||
|
* @return The new {@link TransformedModel} instance.
|
||||||
|
* @see ModelLocation#ofResource(ResourceLocation)
|
||||||
|
*/
|
||||||
public static TransformedModel of(ResourceLocation location) {
|
public static TransformedModel of(ResourceLocation location) {
|
||||||
var modelManager = Minecraft.getInstance().getModelManager();
|
var modelManager = Minecraft.getInstance().getModelManager();
|
||||||
return new TransformedModel(ClientPlatformHelper.get().getModel(modelManager, location));
|
return new TransformedModel(ClientPlatformHelper.get().getModel(modelManager, location));
|
||||||
@@ -46,12 +63,4 @@ public final class TransformedModel {
|
|||||||
var model = Minecraft.getInstance().getItemRenderer().getItemModelShaper().getItemModel(item);
|
var model = Minecraft.getInstance().getItemRenderer().getItemModelShaper().getItemModel(item);
|
||||||
return new TransformedModel(model, transform);
|
return new TransformedModel(model, transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BakedModel getModel() {
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Transformation getMatrix() {
|
|
||||||
return matrix;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,26 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2023 The CC: Tweaked Developers
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
package dan200.computercraft.api.client.turtle;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||||
|
import dan200.computercraft.api.upgrades.UpgradeType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A functional interface to register a {@link TurtleUpgradeModeller} for a class of turtle upgrades.
|
||||||
|
* <p>
|
||||||
|
* This interface is largely intended to be used from multi-loader code, to allow sharing registration code between
|
||||||
|
* multiple loaders.
|
||||||
|
*/
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface RegisterTurtleUpgradeModeller {
|
||||||
|
/**
|
||||||
|
* Register a {@link TurtleUpgradeModeller}.
|
||||||
|
*
|
||||||
|
* @param type The turtle upgrade type.
|
||||||
|
* @param modeller The upgrade modeller.
|
||||||
|
* @param <T> The type of the turtle upgrade.
|
||||||
|
*/
|
||||||
|
<T extends ITurtleUpgrade> void register(UpgradeType<T> type, TurtleUpgradeModeller<T> modeller);
|
||||||
|
}
|
@@ -4,72 +4,65 @@
|
|||||||
|
|
||||||
package dan200.computercraft.api.client.turtle;
|
package dan200.computercraft.api.client.turtle;
|
||||||
|
|
||||||
import dan200.computercraft.api.client.ComputerCraftAPIClient;
|
import dan200.computercraft.api.client.ModelLocation;
|
||||||
import dan200.computercraft.api.client.TransformedModel;
|
import dan200.computercraft.api.client.TransformedModel;
|
||||||
import dan200.computercraft.api.turtle.ITurtleAccess;
|
import dan200.computercraft.api.turtle.ITurtleAccess;
|
||||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||||
import dan200.computercraft.api.turtle.TurtleSide;
|
import dan200.computercraft.api.turtle.TurtleSide;
|
||||||
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
|
||||||
import net.minecraft.client.resources.model.ModelResourceLocation;
|
|
||||||
import net.minecraft.client.resources.model.UnbakedModel;
|
import net.minecraft.client.resources.model.UnbakedModel;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.core.component.DataComponentPatch;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import java.util.stream.Stream;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides models for a {@link ITurtleUpgrade}.
|
* Provides models for a {@link ITurtleUpgrade}.
|
||||||
|
* <p>
|
||||||
|
* Use {@code dan200.computercraft.api.client.FabricComputerCraftAPIClient#registerTurtleUpgradeModeller} to register a
|
||||||
|
* modeller on Fabric and {@code dan200.computercraft.api.client.turtle.RegisterTurtleModellersEvent} to register one
|
||||||
|
* on Forge.
|
||||||
|
*
|
||||||
|
* <h2>Example</h2>
|
||||||
|
* <h3>Fabric</h3>
|
||||||
|
* {@snippet class=com.example.examplemod.FabricExampleModClient region=turtle_modellers}
|
||||||
|
*
|
||||||
|
* <h3>Forge</h3>
|
||||||
|
* {@snippet class=com.example.examplemod.FabricExampleModClient region=turtle_modellers}
|
||||||
*
|
*
|
||||||
* @param <T> The type of turtle upgrade this modeller applies to.
|
* @param <T> The type of turtle upgrade this modeller applies to.
|
||||||
* @see ComputerCraftAPIClient#registerTurtleUpgradeModeller(TurtleUpgradeSerialiser, TurtleUpgradeModeller) To register a modeller.
|
* @see RegisterTurtleUpgradeModeller For multi-loader registration support.
|
||||||
*/
|
*/
|
||||||
public interface TurtleUpgradeModeller<T extends ITurtleUpgrade> {
|
public interface TurtleUpgradeModeller<T extends ITurtleUpgrade> {
|
||||||
/**
|
/**
|
||||||
* Obtain the model to be used when rendering a turtle peripheral.
|
* Obtain the model to be used when rendering a turtle peripheral.
|
||||||
* <p>
|
* <p>
|
||||||
* When the current turtle is {@literal null}, this function should be constant for a given upgrade and side.
|
* When the current turtle is {@literal null}, this function should be constant for a given upgrade, side and data.
|
||||||
*
|
*
|
||||||
* @param upgrade The upgrade that you're getting the model for.
|
* @param upgrade The upgrade that you're getting the model for.
|
||||||
* @param turtle Access to the turtle that the upgrade resides on. This will be null when getting item models, unless
|
* @param turtle Access to the turtle that the upgrade resides on. This will be null when getting item models.
|
||||||
* {@link #getModel(ITurtleUpgrade, CompoundTag, TurtleSide)} is overriden.
|
|
||||||
* @param side Which side of the turtle (left or right) the upgrade resides on.
|
* @param side Which side of the turtle (left or right) the upgrade resides on.
|
||||||
* @return The model that you wish to be used to render your upgrade.
|
|
||||||
*/
|
|
||||||
TransformedModel getModel(T upgrade, @Nullable ITurtleAccess turtle, TurtleSide side);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain the model to be used when rendering a turtle peripheral.
|
|
||||||
* <p>
|
|
||||||
* This is used when rendering the turtle's item model, and so no {@link ITurtleAccess} is available.
|
|
||||||
*
|
|
||||||
* @param upgrade The upgrade that you're getting the model for.
|
|
||||||
* @param data Upgrade data instance for current turtle side.
|
* @param data Upgrade data instance for current turtle side.
|
||||||
* @param side Which side of the turtle (left or right) the upgrade resides on.
|
|
||||||
* @return The model that you wish to be used to render your upgrade.
|
* @return The model that you wish to be used to render your upgrade.
|
||||||
*/
|
*/
|
||||||
default TransformedModel getModel(T upgrade, CompoundTag data, TurtleSide side) {
|
TransformedModel getModel(T upgrade, @Nullable ITurtleAccess turtle, TurtleSide side, DataComponentPatch data);
|
||||||
return getModel(upgrade, (ITurtleAccess) null, side);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a list of models that this turtle modeller depends on.
|
* Get the models that this turtle modeller depends on.
|
||||||
* <p>
|
* <p>
|
||||||
* Models included in this list will be loaded and baked alongside item and block models, and so may be referenced
|
* Models included in this stream will be loaded and baked alongside item and block models, and so may be referenced
|
||||||
* by {@link TransformedModel#of(ResourceLocation)}. You do not need to override this method if you will load models
|
* by {@link TransformedModel#of(ResourceLocation)}. You do not need to override this method if you will load models
|
||||||
* by other means.
|
* by other means.
|
||||||
*
|
*
|
||||||
* @return A list of models that this modeller depends on.
|
* @return A list of models that this modeller depends on.
|
||||||
* @see UnbakedModel#getDependencies()
|
* @see UnbakedModel#getDependencies()
|
||||||
*/
|
*/
|
||||||
default Collection<ResourceLocation> getDependencies() {
|
default Stream<ResourceLocation> getDependencies() {
|
||||||
return List.of();
|
return Stream.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A basic {@link TurtleUpgradeModeller} which renders using the upgrade's {@linkplain ITurtleUpgrade#getUpgradeItem(CompoundTag)}
|
* A basic {@link TurtleUpgradeModeller} which renders using the upgrade's {@linkplain ITurtleUpgrade#getUpgradeItem(DataComponentPatch)}
|
||||||
* upgrade item}.
|
* upgrade item}.
|
||||||
* <p>
|
* <p>
|
||||||
* This uses appropriate transformations for "flat" items, namely those extending the {@literal minecraft:item/generated}
|
* This uses appropriate transformations for "flat" items, namely those extending the {@literal minecraft:item/generated}
|
||||||
@@ -91,9 +84,8 @@ public interface TurtleUpgradeModeller<T extends ITurtleUpgrade> {
|
|||||||
* @param <T> The type of the turtle upgrade.
|
* @param <T> The type of the turtle upgrade.
|
||||||
* @return The constructed modeller.
|
* @return The constructed modeller.
|
||||||
*/
|
*/
|
||||||
static <T extends ITurtleUpgrade> TurtleUpgradeModeller<T> sided(ModelResourceLocation left, ModelResourceLocation right) {
|
static <T extends ITurtleUpgrade> TurtleUpgradeModeller<T> sided(ResourceLocation left, ResourceLocation right) {
|
||||||
// TODO(1.21.0): Remove this.
|
return sided(ModelLocation.ofResource(left), ModelLocation.ofResource(right));
|
||||||
return sided((ResourceLocation) left, right);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -104,16 +96,16 @@ public interface TurtleUpgradeModeller<T extends ITurtleUpgrade> {
|
|||||||
* @param <T> The type of the turtle upgrade.
|
* @param <T> The type of the turtle upgrade.
|
||||||
* @return The constructed modeller.
|
* @return The constructed modeller.
|
||||||
*/
|
*/
|
||||||
static <T extends ITurtleUpgrade> TurtleUpgradeModeller<T> sided(ResourceLocation left, ResourceLocation right) {
|
static <T extends ITurtleUpgrade> TurtleUpgradeModeller<T> sided(ModelLocation left, ModelLocation right) {
|
||||||
return new TurtleUpgradeModeller<>() {
|
return new TurtleUpgradeModeller<>() {
|
||||||
@Override
|
@Override
|
||||||
public TransformedModel getModel(T upgrade, @Nullable ITurtleAccess turtle, TurtleSide side) {
|
public TransformedModel getModel(T upgrade, @Nullable ITurtleAccess turtle, TurtleSide side, DataComponentPatch data) {
|
||||||
return TransformedModel.of(side == TurtleSide.LEFT ? left : right);
|
return TransformedModel.of(side == TurtleSide.LEFT ? left : right);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<ResourceLocation> getDependencies() {
|
public Stream<ResourceLocation> getDependencies() {
|
||||||
return List.of(left, right);
|
return Stream.of(left, right).flatMap(ModelLocation::getDependencies);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -11,11 +11,9 @@ import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
|||||||
import dan200.computercraft.api.turtle.TurtleSide;
|
import dan200.computercraft.api.turtle.TurtleSide;
|
||||||
import dan200.computercraft.impl.client.ClientPlatformHelper;
|
import dan200.computercraft.impl.client.ClientPlatformHelper;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.core.component.DataComponentPatch;
|
||||||
import net.minecraft.world.item.ItemStack;
|
|
||||||
import org.joml.Matrix4f;
|
import org.joml.Matrix4f;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
final class TurtleUpgradeModellers {
|
final class TurtleUpgradeModellers {
|
||||||
private static final Transformation leftTransform = getMatrixFor(-0.4065f);
|
private static final Transformation leftTransform = getMatrixFor(-0.4065f);
|
||||||
@@ -37,16 +35,8 @@ final class TurtleUpgradeModellers {
|
|||||||
|
|
||||||
private static final class UpgradeItemModeller implements TurtleUpgradeModeller<ITurtleUpgrade> {
|
private static final class UpgradeItemModeller implements TurtleUpgradeModeller<ITurtleUpgrade> {
|
||||||
@Override
|
@Override
|
||||||
public TransformedModel getModel(ITurtleUpgrade upgrade, @Nullable ITurtleAccess turtle, TurtleSide side) {
|
public TransformedModel getModel(ITurtleUpgrade upgrade, @Nullable ITurtleAccess turtle, TurtleSide side, DataComponentPatch data) {
|
||||||
return getModel(turtle == null ? upgrade.getCraftingItem() : upgrade.getUpgradeItem(turtle.getUpgradeNBTData(side)), side);
|
var stack = upgrade.getUpgradeItem(data);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TransformedModel getModel(ITurtleUpgrade upgrade, CompoundTag data, TurtleSide side) {
|
|
||||||
return getModel(upgrade.getUpgradeItem(data), side);
|
|
||||||
}
|
|
||||||
|
|
||||||
private TransformedModel getModel(ItemStack stack, TurtleSide side) {
|
|
||||||
var model = Minecraft.getInstance().getItemRenderer().getItemModelShaper().getItemModel(stack);
|
var model = Minecraft.getInstance().getItemRenderer().getItemModelShaper().getItemModel(stack);
|
||||||
if (stack.hasFoil()) model = ClientPlatformHelper.get().createdFoiledModel(model);
|
if (stack.hasFoil()) model = ClientPlatformHelper.get().createdFoiledModel(model);
|
||||||
return new TransformedModel(model, side == TurtleSide.LEFT ? leftTransform : rightTransform);
|
return new TransformedModel(model, side == TurtleSide.LEFT ? leftTransform : rightTransform);
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
package dan200.computercraft.impl.client;
|
package dan200.computercraft.impl.client;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.client.ModelLocation;
|
||||||
import dan200.computercraft.impl.Services;
|
import dan200.computercraft.impl.Services;
|
||||||
import net.minecraft.client.renderer.RenderType;
|
import net.minecraft.client.renderer.RenderType;
|
||||||
import net.minecraft.client.resources.model.BakedModel;
|
import net.minecraft.client.resources.model.BakedModel;
|
||||||
@@ -11,19 +12,33 @@ import net.minecraft.client.resources.model.ModelManager;
|
|||||||
import net.minecraft.client.resources.model.ModelResourceLocation;
|
import net.minecraft.client.resources.model.ModelResourceLocation;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
@ApiStatus.Internal
|
@ApiStatus.Internal
|
||||||
public interface ClientPlatformHelper {
|
public interface ClientPlatformHelper {
|
||||||
/**
|
/**
|
||||||
* Equivalent to {@link ModelManager#getModel(ModelResourceLocation)} but for arbitrary {@link ResourceLocation}s.
|
* Get a model from a resource.
|
||||||
*
|
*
|
||||||
* @param manager The model manager.
|
* @param manager The model manager.
|
||||||
* @param location The model location.
|
* @param resourceLocation The model resourceLocation.
|
||||||
* @return The baked model.
|
* @return The baked model.
|
||||||
|
* @see ModelLocation
|
||||||
*/
|
*/
|
||||||
BakedModel getModel(ModelManager manager, ResourceLocation location);
|
BakedModel getModel(ModelManager manager, ResourceLocation resourceLocation);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a model from a {@link ModelResourceLocation} or {@link ResourceLocation}.
|
||||||
|
* <p>
|
||||||
|
* This is largely equivalent to {@code resourceLocation == null ? manager.getModel(modelLocation) : getModel(manager, resourceLocation)},
|
||||||
|
* but allows pre-computing {@code modelLocation} (if needed).
|
||||||
|
*
|
||||||
|
* @param manager The model manager.
|
||||||
|
* @param modelLocation The location of the model to load.
|
||||||
|
* @param resourceLocation The location of the resource, if trying to load from a resource.
|
||||||
|
* @return The baked model.
|
||||||
|
* @see ModelLocation
|
||||||
|
*/
|
||||||
|
BakedModel getModel(ModelManager manager, ModelResourceLocation modelLocation, @Nullable ResourceLocation resourceLocation);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrap this model in a version which renders a foil/enchantment glint.
|
* Wrap this model in a version which renders a foil/enchantment glint.
|
||||||
|
@@ -4,9 +4,11 @@
|
|||||||
|
|
||||||
package dan200.computercraft.api;
|
package dan200.computercraft.api;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.component.ComputerComponent;
|
||||||
import dan200.computercraft.api.filesystem.Mount;
|
import dan200.computercraft.api.filesystem.Mount;
|
||||||
import dan200.computercraft.api.filesystem.WritableMount;
|
import dan200.computercraft.api.filesystem.WritableMount;
|
||||||
import dan200.computercraft.api.lua.GenericSource;
|
import dan200.computercraft.api.lua.GenericSource;
|
||||||
|
import dan200.computercraft.api.lua.IComputerSystem;
|
||||||
import dan200.computercraft.api.lua.ILuaAPI;
|
import dan200.computercraft.api.lua.ILuaAPI;
|
||||||
import dan200.computercraft.api.lua.ILuaAPIFactory;
|
import dan200.computercraft.api.lua.ILuaAPIFactory;
|
||||||
import dan200.computercraft.api.media.IMedia;
|
import dan200.computercraft.api.media.IMedia;
|
||||||
@@ -24,8 +26,7 @@ import net.minecraft.core.Direction;
|
|||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The static entry point to the ComputerCraft API.
|
* The static entry point to the ComputerCraft API.
|
||||||
@@ -146,7 +147,10 @@ public final class ComputerCraftAPI {
|
|||||||
*
|
*
|
||||||
* @param provider The media provider to register.
|
* @param provider The media provider to register.
|
||||||
* @see MediaProvider
|
* @see MediaProvider
|
||||||
|
* @deprecated Prefer {@code dan200.computercraft.api.media.MediaLookup} (Fabric) or
|
||||||
|
* {@code dan200.computercraft.api.media.MediaCapability} (NeoForge).
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static void registerMediaProvider(MediaProvider provider) {
|
public static void registerMediaProvider(MediaProvider provider) {
|
||||||
getInstance().registerMediaProvider(provider);
|
getInstance().registerMediaProvider(provider);
|
||||||
}
|
}
|
||||||
@@ -165,7 +169,13 @@ public final class ComputerCraftAPI {
|
|||||||
* Register a custom {@link ILuaAPI}, which may be added onto all computers without requiring a peripheral.
|
* Register a custom {@link ILuaAPI}, which may be added onto all computers without requiring a peripheral.
|
||||||
* <p>
|
* <p>
|
||||||
* Before implementing this interface, consider alternative methods of providing methods. It is generally preferred
|
* Before implementing this interface, consider alternative methods of providing methods. It is generally preferred
|
||||||
* to use peripherals to provide functionality to users.
|
* to use peripherals to provide functionality to users. If an API is <em>required</em>, you may want to consider
|
||||||
|
* using {@link ILuaAPI#getModuleName()} to expose this library as a module instead of as a global.
|
||||||
|
* <p>
|
||||||
|
* This may be used with {@link IComputerSystem#getComponent(ComputerComponent)} to only attach APIs to specific
|
||||||
|
* computers. For example, one can add a new API just to turtles with the following code:
|
||||||
|
*
|
||||||
|
* {@snippet class=com.example.examplemod.ExampleAPI region=register}
|
||||||
*
|
*
|
||||||
* @param factory The factory for your API subclass.
|
* @param factory The factory for your API subclass.
|
||||||
* @see ILuaAPIFactory
|
* @see ILuaAPIFactory
|
||||||
|
@@ -6,10 +6,12 @@ package dan200.computercraft.api;
|
|||||||
|
|
||||||
import net.minecraft.core.registries.Registries;
|
import net.minecraft.core.registries.Registries;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.tags.ItemTags;
|
||||||
import net.minecraft.tags.TagKey;
|
import net.minecraft.tags.TagKey;
|
||||||
import net.minecraft.world.InteractionHand;
|
import net.minecraft.world.InteractionHand;
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
import net.minecraft.world.item.Item;
|
import net.minecraft.world.item.Item;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.item.context.UseOnContext;
|
import net.minecraft.world.item.context.UseOnContext;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
@@ -26,6 +28,20 @@ public class ComputerCraftTags {
|
|||||||
public static final TagKey<Item> WIRED_MODEM = make("wired_modem");
|
public static final TagKey<Item> WIRED_MODEM = make("wired_modem");
|
||||||
public static final TagKey<Item> MONITOR = make("monitor");
|
public static final TagKey<Item> MONITOR = make("monitor");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Floppy disks. Both the read/write version, and treasure disks.
|
||||||
|
*
|
||||||
|
* @since 1.116.0
|
||||||
|
*/
|
||||||
|
public static final TagKey<Item> DISKS = make("disks");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All pocket computers.
|
||||||
|
*
|
||||||
|
* @since 1.116.0
|
||||||
|
*/
|
||||||
|
public static final TagKey<Item> POCKET_COMPUTERS = make("pocket_computers");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Items which can be {@linkplain Item#use(Level, Player, InteractionHand) used} when calling
|
* Items which can be {@linkplain Item#use(Level, Player, InteractionHand) used} when calling
|
||||||
* {@code turtle.place()}.
|
* {@code turtle.place()}.
|
||||||
@@ -35,8 +51,16 @@ public class ComputerCraftTags {
|
|||||||
*/
|
*/
|
||||||
public static final TagKey<Item> TURTLE_CAN_PLACE = make("turtle_can_place");
|
public static final TagKey<Item> TURTLE_CAN_PLACE = make("turtle_can_place");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Items which can be dyed.
|
||||||
|
* <p>
|
||||||
|
* This is similar to {@link ItemTags#DYEABLE}, but allows cleaning the item with a sponge, rather than in a
|
||||||
|
* cauldron.
|
||||||
|
*/
|
||||||
|
public static final TagKey<Item> DYEABLE = make("dyeable");
|
||||||
|
|
||||||
private static TagKey<Item> make(String name) {
|
private static TagKey<Item> make(String name) {
|
||||||
return TagKey.create(Registries.ITEM, new ResourceLocation(ComputerCraftAPI.MOD_ID, name));
|
return TagKey.create(Registries.ITEM, ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,6 +70,14 @@ public class ComputerCraftTags {
|
|||||||
public static final TagKey<Block> WIRED_MODEM = make("wired_modem");
|
public static final TagKey<Block> WIRED_MODEM = make("wired_modem");
|
||||||
public static final TagKey<Block> MONITOR = make("monitor");
|
public static final TagKey<Block> MONITOR = make("monitor");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blocks which should be ignored by a {@code peripheral_hub} peripheral.
|
||||||
|
* <p>
|
||||||
|
* This should include blocks which themselves expose a peripheral hub (such as {@linkplain #WIRED_MODEM wired
|
||||||
|
* modems}).
|
||||||
|
*/
|
||||||
|
public static final TagKey<Block> PERIPHERAL_HUB_IGNORE = make("peripheral_hub_ignore");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Blocks which can be broken by any turtle tool.
|
* Blocks which can be broken by any turtle tool.
|
||||||
*/
|
*/
|
||||||
@@ -67,13 +99,13 @@ public class ComputerCraftTags {
|
|||||||
public static final TagKey<Block> TURTLE_HOE_BREAKABLE = make("turtle_hoe_harvestable");
|
public static final TagKey<Block> TURTLE_HOE_BREAKABLE = make("turtle_hoe_harvestable");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Block which can be {@linkplain BlockState#use(Level, Player, InteractionHand, BlockHitResult) used} when
|
* Block which can be {@linkplain BlockState#useItemOn(ItemStack, Level, Player, InteractionHand, BlockHitResult) used}
|
||||||
* calling {@code turtle.place()}.
|
* when calling {@code turtle.place()}.
|
||||||
*/
|
*/
|
||||||
public static final TagKey<Block> TURTLE_CAN_USE = make("turtle_can_use");
|
public static final TagKey<Block> TURTLE_CAN_USE = make("turtle_can_use");
|
||||||
|
|
||||||
private static TagKey<Block> make(String name) {
|
private static TagKey<Block> make(String name) {
|
||||||
return TagKey.create(Registries.BLOCK, new ResourceLocation(ComputerCraftAPI.MOD_ID, name));
|
return TagKey.create(Registries.BLOCK, ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,24 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
package dan200.computercraft.api.component;
|
||||||
|
|
||||||
|
import net.minecraft.commands.CommandSourceStack;
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A computer which has permission to perform administrative/op commands, such as the command computer.
|
||||||
|
*/
|
||||||
|
@ApiStatus.NonExtendable
|
||||||
|
public interface AdminComputer {
|
||||||
|
/**
|
||||||
|
* The permission level that this computer can operate at.
|
||||||
|
*
|
||||||
|
* @return The permission level for this computer.
|
||||||
|
* @see CommandSourceStack#hasPermission(int)
|
||||||
|
*/
|
||||||
|
default int permissionLevel() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,48 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
package dan200.computercraft.api.component;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.lua.IComputerSystem;
|
||||||
|
import dan200.computercraft.api.lua.ILuaAPIFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A component attached to a computer.
|
||||||
|
* <p>
|
||||||
|
* Components provide a mechanism to attach additional data to a computer, that can then be queried with
|
||||||
|
* {@link IComputerSystem#getComponent(ComputerComponent)}.
|
||||||
|
* <p>
|
||||||
|
* This is largely designed for {@linkplain ILuaAPIFactory custom APIs}, allowing APIs to read additional properties
|
||||||
|
* of the computer, such as its position.
|
||||||
|
*
|
||||||
|
* @param <T> The type of this component.
|
||||||
|
* @see ComputerComponents The built-in components.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("UnusedTypeParameter")
|
||||||
|
public final class ComputerComponent<T> {
|
||||||
|
private final String id;
|
||||||
|
|
||||||
|
private ComputerComponent(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new computer component.
|
||||||
|
* <p>
|
||||||
|
* Mods typically will not need to create their own components.
|
||||||
|
*
|
||||||
|
* @param namespace The namespace of this component. This should be the mod id.
|
||||||
|
* @param id The unique id of this component.
|
||||||
|
* @param <T> The component
|
||||||
|
* @return The newly created component.
|
||||||
|
*/
|
||||||
|
public static <T> ComputerComponent<T> create(String namespace, String id) {
|
||||||
|
return new ComputerComponent<>(namespace + ":" + id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "ComputerComponent(" + id + ")";
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,29 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
package dan200.computercraft.api.component;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.ComputerCraftAPI;
|
||||||
|
import dan200.computercraft.api.pocket.IPocketAccess;
|
||||||
|
import dan200.computercraft.api.turtle.ITurtleAccess;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link ComputerComponent}s provided by ComputerCraft.
|
||||||
|
*/
|
||||||
|
public class ComputerComponents {
|
||||||
|
/**
|
||||||
|
* The {@link ITurtleAccess} associated with a turtle.
|
||||||
|
*/
|
||||||
|
public static final ComputerComponent<ITurtleAccess> TURTLE = ComputerComponent.create(ComputerCraftAPI.MOD_ID, "turtle");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link IPocketAccess} associated with a pocket computer.
|
||||||
|
*/
|
||||||
|
public static final ComputerComponent<IPocketAccess> POCKET = ComputerComponent.create(ComputerCraftAPI.MOD_ID, "pocket");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This component is only present on "command computers", and other computers with admin capabilities.
|
||||||
|
*/
|
||||||
|
public static final ComputerComponent<AdminComputer> ADMIN_COMPUTER = ComputerComponent.create(ComputerCraftAPI.MOD_ID, "admin_computer");
|
||||||
|
}
|
@@ -6,14 +6,14 @@ package dan200.computercraft.api.detail;
|
|||||||
|
|
||||||
import net.minecraft.world.item.Item;
|
import net.minecraft.world.item.Item;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An item detail provider for {@link ItemStack}'s whose {@link Item} has a specific type.
|
* An item detail provider for {@link ItemStack}s whose {@link Item} has a specific type.
|
||||||
*
|
*
|
||||||
* @param <T> The type the stack's item must have.
|
* @param <T> The type the stack's item must have.
|
||||||
*/
|
*/
|
||||||
@@ -22,7 +22,7 @@ public abstract class BasicItemDetailProvider<T> implements DetailProvider<ItemS
|
|||||||
private final @Nullable String namespace;
|
private final @Nullable String namespace;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new item detail provider. Meta will be inserted into a new sub-map named as per {@code namespace}.
|
* Create a new item detail provider. Details will be inserted into a new sub-map named as per {@code namespace}.
|
||||||
*
|
*
|
||||||
* @param itemType The type the stack's item must have.
|
* @param itemType The type the stack's item must have.
|
||||||
* @param namespace The namespace to use for this provider.
|
* @param namespace The namespace to use for this provider.
|
||||||
@@ -34,7 +34,7 @@ public abstract class BasicItemDetailProvider<T> implements DetailProvider<ItemS
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new item detail provider. Meta will be inserted directly into the results.
|
* Create a new item detail provider. Details will be inserted directly into the results.
|
||||||
*
|
*
|
||||||
* @param itemType The type the stack's item must have.
|
* @param itemType The type the stack's item must have.
|
||||||
*/
|
*/
|
||||||
@@ -53,21 +53,18 @@ public abstract class BasicItemDetailProvider<T> implements DetailProvider<ItemS
|
|||||||
* @param stack The item stack to provide details for.
|
* @param stack The item stack to provide details for.
|
||||||
* @param item The item to provide details for.
|
* @param item The item to provide details for.
|
||||||
*/
|
*/
|
||||||
public abstract void provideDetails(
|
public abstract void provideDetails(Map<? super String, Object> data, ItemStack stack, T item);
|
||||||
Map<? super String, Object> data, ItemStack stack, T item
|
|
||||||
);
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void provideDetails(Map<? super String, Object> data, ItemStack stack) {
|
public final void provideDetails(Map<? super String, Object> data, ItemStack stack) {
|
||||||
var item = stack.getItem();
|
var item = stack.getItem();
|
||||||
if (!itemType.isInstance(item)) return;
|
if (!itemType.isInstance(item)) return;
|
||||||
|
|
||||||
// If `namespace` is specified, insert into a new data map instead of the existing one.
|
if (namespace == null) {
|
||||||
Map<? super String, Object> child = namespace == null ? data : new HashMap<>();
|
provideDetails(data, stack, itemType.cast(item));
|
||||||
|
} else {
|
||||||
provideDetails(child, stack, itemType.cast(item));
|
Map<? super String, Object> child = new HashMap<>();
|
||||||
|
provideDetails(child, stack, itemType.cast(item));
|
||||||
if (namespace != null) {
|
|
||||||
data.put(namespace, child);
|
data.put(namespace, child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -8,8 +8,7 @@ import net.minecraft.core.BlockPos;
|
|||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A reference to a block in the world, used by block detail providers.
|
* A reference to a block in the world, used by block detail providers.
|
||||||
|
@@ -0,0 +1,72 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
package dan200.computercraft.api.detail;
|
||||||
|
|
||||||
|
import net.minecraft.core.component.DataComponentHolder;
|
||||||
|
import net.minecraft.core.component.DataComponentType;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An item detail provider for a specific {@linkplain DataComponentType data component} on {@link ItemStack}s or
|
||||||
|
* other {@link DataComponentHolder}.
|
||||||
|
*
|
||||||
|
* @param <T> The type of the component's contents.
|
||||||
|
*/
|
||||||
|
public abstract class ComponentDetailProvider<T> implements DetailProvider<DataComponentHolder> {
|
||||||
|
private final DataComponentType<T> component;
|
||||||
|
private final @Nullable String namespace;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new component detail provider. Details will be inserted into a new sub-map named as per {@code namespace}.
|
||||||
|
*
|
||||||
|
* @param component The data component to provide details for.
|
||||||
|
* @param namespace The namespace to use for this provider.
|
||||||
|
*/
|
||||||
|
public ComponentDetailProvider(@Nullable String namespace, DataComponentType<T> component) {
|
||||||
|
Objects.requireNonNull(component);
|
||||||
|
this.component = component;
|
||||||
|
this.namespace = namespace;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new component detail provider. Details will be inserted directly into the results.
|
||||||
|
*
|
||||||
|
* @param component The data component to provide details for.
|
||||||
|
*/
|
||||||
|
public ComponentDetailProvider(DataComponentType<T> component) {
|
||||||
|
this(null, component);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide additional details for the given data component. This method is called by {@code turtle.getItemDetail()}.
|
||||||
|
* New properties should be added to the given {@link Map}, {@code data}.
|
||||||
|
* <p>
|
||||||
|
* This method is always called on the server thread, so it is safe to interact with the world here, but you should
|
||||||
|
* take care to avoid long blocking operations as this will stall the server and other computers.
|
||||||
|
*
|
||||||
|
* @param data The full details to be returned for this item stack. New properties should be added to this map.
|
||||||
|
* @param component The component to provide details for.
|
||||||
|
*/
|
||||||
|
public abstract void provideComponentDetails(Map<? super String, Object> data, T component);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void provideDetails(Map<? super String, Object> data, DataComponentHolder holder) {
|
||||||
|
var value = holder.get(component);
|
||||||
|
if (value == null) return;
|
||||||
|
|
||||||
|
if (namespace == null) {
|
||||||
|
provideComponentDetails(data, value);
|
||||||
|
} else {
|
||||||
|
Map<? super String, Object> child = new HashMap<>();
|
||||||
|
provideComponentDetails(child, value);
|
||||||
|
data.put(namespace, child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -14,6 +14,7 @@ import java.util.Map;
|
|||||||
*
|
*
|
||||||
* @param <T> The type of object that this provider can provide details for.
|
* @param <T> The type of object that this provider can provide details for.
|
||||||
* @see DetailRegistry
|
* @see DetailRegistry
|
||||||
|
* @see dan200.computercraft.api.detail An overview of the detail system.
|
||||||
*/
|
*/
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface DetailProvider<T> {
|
public interface DetailProvider<T> {
|
||||||
|
@@ -17,6 +17,7 @@ import java.util.Map;
|
|||||||
* also in this package.
|
* also in this package.
|
||||||
*
|
*
|
||||||
* @param <T> The type of object that this registry provides details for.
|
* @param <T> The type of object that this registry provides details for.
|
||||||
|
* @see dan200.computercraft.api.detail An overview of the detail system.
|
||||||
*/
|
*/
|
||||||
@ApiStatus.NonExtendable
|
@ApiStatus.NonExtendable
|
||||||
public interface DetailRegistry<T> {
|
public interface DetailRegistry<T> {
|
||||||
@@ -26,7 +27,7 @@ public interface DetailRegistry<T> {
|
|||||||
* @param provider The detail provider to register.
|
* @param provider The detail provider to register.
|
||||||
* @see DetailProvider
|
* @see DetailProvider
|
||||||
*/
|
*/
|
||||||
void addProvider(DetailProvider<T> provider);
|
void addProvider(DetailProvider<? super T> provider);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute basic details about an object. This is cheaper than computing all details operation, and so is suitable
|
* Compute basic details about an object. This is cheaper than computing all details operation, and so is suitable
|
||||||
|
@@ -17,6 +17,9 @@ public class VanillaDetailRegistries {
|
|||||||
* <p>
|
* <p>
|
||||||
* This instance's {@link DetailRegistry#getBasicDetails(Object)} is thread safe (assuming the stack is immutable)
|
* This instance's {@link DetailRegistry#getBasicDetails(Object)} is thread safe (assuming the stack is immutable)
|
||||||
* and may be called from the computer thread.
|
* and may be called from the computer thread.
|
||||||
|
* <p>
|
||||||
|
* This does not have special handling for {@linkplain ItemStack#isEmpty() empty item stacks}, and so the returned
|
||||||
|
* details will be an empty stack of air. Callers should generally check for empty stacks before calling this.
|
||||||
*/
|
*/
|
||||||
public static final DetailRegistry<ItemStack> ITEM_STACK = ComputerCraftAPIService.get().getItemStackDetailRegistry();
|
public static final DetailRegistry<ItemStack> ITEM_STACK = ComputerCraftAPIService.get().getItemStackDetailRegistry();
|
||||||
|
|
||||||
|
@@ -0,0 +1,48 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2025 The CC: Tweaked Developers
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The detail system provides a standard way for mods to return descriptions of common game objects, such as blocks or
|
||||||
|
* items, as well as registering additional detail to be included in those descriptions.
|
||||||
|
* <p>
|
||||||
|
* For instance, the built-in {@code turtle.getItemDetail()} method uses
|
||||||
|
* {@linkplain dan200.computercraft.api.detail.VanillaDetailRegistries#ITEM_STACK in order to provide information about}
|
||||||
|
* the selected item:
|
||||||
|
*
|
||||||
|
* <pre class="language language-lua">{@code
|
||||||
|
* local item = turtle.getItemDetail(nil, true)
|
||||||
|
* --[[
|
||||||
|
* item = {
|
||||||
|
* name = "minecraft:wheat",
|
||||||
|
* displayName = "Wheat",
|
||||||
|
* count = 1,
|
||||||
|
* maxCount = 64,
|
||||||
|
* tags = {},
|
||||||
|
* }
|
||||||
|
* ]]
|
||||||
|
* }</pre>
|
||||||
|
*
|
||||||
|
* <h2>Built-in detail providers</h2>
|
||||||
|
* While you can define your own detail providers (perhaps for types from your own mod), CC comes with several built-in
|
||||||
|
* detail registries for vanilla and mod-loader objects:
|
||||||
|
*
|
||||||
|
* <ul>
|
||||||
|
* <li>{@link dan200.computercraft.api.detail.VanillaDetailRegistries}, for vanilla objects</li>
|
||||||
|
* <li>{@code dan200.computercraft.api.detail.ForgeDetailRegistries} for Forge-specific objects</li>
|
||||||
|
* <li>{@code dan200.computercraft.api.detail.FabricDetailRegistries} for Fabric-specific objects</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <h2>Example: Returning details from methods</h2>
|
||||||
|
* Here we define a {@code getHeldItem()} method for pocket computers which finds the currently held item of the player
|
||||||
|
* and returns it to the user using {@link dan200.computercraft.api.detail.VanillaDetailRegistries#ITEM_STACK} and
|
||||||
|
* {@link dan200.computercraft.api.detail.DetailRegistry#getDetails(java.lang.Object)}.
|
||||||
|
*
|
||||||
|
* {@snippet class=com.example.examplemod.ExamplePocketPeripheral region=details}
|
||||||
|
*
|
||||||
|
* <h2>Example: Registering custom detail registries</h2>
|
||||||
|
* Here we define a new detail provider for items that includes the nutrition and saturation values in the returned object.
|
||||||
|
*
|
||||||
|
* {@snippet class=com.example.examplemod.ExampleMod region=details}
|
||||||
|
*/
|
||||||
|
package dan200.computercraft.api.detail;
|
@@ -0,0 +1,58 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2017 The CC: Tweaked Developers
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
package dan200.computercraft.api.lua;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.component.ComputerComponent;
|
||||||
|
import dan200.computercraft.api.peripheral.IComputerAccess;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An interface passed to {@link ILuaAPIFactory} in order to provide additional information
|
||||||
|
* about a computer.
|
||||||
|
*/
|
||||||
|
@ApiStatus.NonExtendable
|
||||||
|
public interface IComputerSystem extends IComputerAccess {
|
||||||
|
/**
|
||||||
|
* Get the level this computer is currently in.
|
||||||
|
* <p>
|
||||||
|
* This method is not guaranteed to remain the same (even for stationary computers).
|
||||||
|
*
|
||||||
|
* @return The computer's current level.
|
||||||
|
*/
|
||||||
|
ServerLevel getLevel();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the position this computer is currently at.
|
||||||
|
* <p>
|
||||||
|
* This method is not guaranteed to remain the same (even for stationary computers).
|
||||||
|
*
|
||||||
|
* @return The computer's current position.
|
||||||
|
*/
|
||||||
|
BlockPos getPosition();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the label for this computer.
|
||||||
|
*
|
||||||
|
* @return This computer's label, or {@code null} if it is not set.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
String getLabel();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a component attached to this computer.
|
||||||
|
* <p>
|
||||||
|
* No component is guaranteed to be on a computer, and so this method should always be guarded with a null check.
|
||||||
|
* <p>
|
||||||
|
* This method will always return the same value for a given component, and so may be cached.
|
||||||
|
*
|
||||||
|
* @param component The component to query.
|
||||||
|
* @param <T> The type of the component.
|
||||||
|
* @return The component, if present.
|
||||||
|
*/
|
||||||
|
<T> @Nullable T getComponent(ComputerComponent<T> component);
|
||||||
|
}
|
@@ -4,13 +4,14 @@
|
|||||||
|
|
||||||
package dan200.computercraft.api.lua;
|
package dan200.computercraft.api.lua;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import dan200.computercraft.api.ComputerCraftAPI;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct an {@link ILuaAPI} for a specific computer.
|
* Construct an {@link ILuaAPI} for a computer.
|
||||||
*
|
*
|
||||||
* @see ILuaAPI
|
* @see ILuaAPI
|
||||||
* @see dan200.computercraft.api.ComputerCraftAPI#registerAPIFactory(ILuaAPIFactory)
|
* @see ComputerCraftAPI#registerAPIFactory(ILuaAPIFactory)
|
||||||
*/
|
*/
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface ILuaAPIFactory {
|
public interface ILuaAPIFactory {
|
@@ -7,29 +7,32 @@ package dan200.computercraft.api.media;
|
|||||||
import dan200.computercraft.api.ComputerCraftAPI;
|
import dan200.computercraft.api.ComputerCraftAPI;
|
||||||
import dan200.computercraft.api.filesystem.Mount;
|
import dan200.computercraft.api.filesystem.Mount;
|
||||||
import dan200.computercraft.api.filesystem.WritableMount;
|
import dan200.computercraft.api.filesystem.WritableMount;
|
||||||
|
import net.minecraft.core.Holder;
|
||||||
|
import net.minecraft.core.HolderLookup;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.sounds.SoundEvent;
|
|
||||||
import net.minecraft.world.item.Item;
|
import net.minecraft.world.item.Item;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.minecraft.world.item.JukeboxSong;
|
||||||
import javax.annotation.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an item that can be placed in a disk drive and used by a Computer.
|
* Represents an item that can be placed in a disk drive and used by a Computer.
|
||||||
* <p>
|
* <p>
|
||||||
* Implement this interface on your {@link Item} class to allow it to be used in the drive. Alternatively, register
|
* Implement this interface on your {@link Item} class to allow it to be used in the drive, or register via
|
||||||
* a {@link MediaProvider}.
|
* {@code dan200.computercraft.api.media.MediaLookup} (Fabric) or {@code dan200.computercraft.api.media.MediaCapability}
|
||||||
|
* (NeoForge).
|
||||||
*/
|
*/
|
||||||
public interface IMedia {
|
public interface IMedia {
|
||||||
/**
|
/**
|
||||||
* Get a string representing the label of this item. Will be called via {@code disk.getLabel()} in lua.
|
* Get a string representing the label of this item. Will be called via {@code disk.getLabel()} in lua.
|
||||||
*
|
*
|
||||||
* @param stack The {@link ItemStack} to inspect.
|
* @param registries The currently loaded registries.
|
||||||
|
* @param stack The {@link ItemStack} to inspect.
|
||||||
* @return The label. ie: "Dan's Programs".
|
* @return The label. ie: "Dan's Programs".
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
String getLabel(ItemStack stack);
|
String getLabel(HolderLookup.Provider registries, ItemStack stack);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a string representing the label of this item. Will be called vi {@code disk.setLabel()} in lua.
|
* Set a string representing the label of this item. Will be called vi {@code disk.setLabel()} in lua.
|
||||||
@@ -43,26 +46,15 @@ public interface IMedia {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If this disk represents an item with audio (like a record), get the readable name of the audio track. ie:
|
* If this disk represents an item with audio (like a record), get the corresponding {@link JukeboxSong}.
|
||||||
* "Jonathan Coulton - Still Alive"
|
|
||||||
*
|
*
|
||||||
* @param stack The {@link ItemStack} to modify.
|
* @param registries The currently loaded registries.
|
||||||
* @return The name, or null if this item does not represent an item with audio.
|
* @param stack The {@link ItemStack} to query.
|
||||||
|
* @return The song, or null if this item does not represent an item with audio.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
default String getAudioTitle(ItemStack stack) {
|
default Holder<JukeboxSong> getAudio(HolderLookup.Provider registries, ItemStack stack) {
|
||||||
return null;
|
return JukeboxSong.fromStack(registries, stack).orElse(null);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If this disk represents an item with audio (like a record), get the resource name of the audio track to play.
|
|
||||||
*
|
|
||||||
* @param stack The {@link ItemStack} to modify.
|
|
||||||
* @return The name, or null if this item does not represent an item with audio.
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
default SoundEvent getAudio(ItemStack stack) {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -5,8 +5,7 @@
|
|||||||
package dan200.computercraft.api.media;
|
package dan200.computercraft.api.media;
|
||||||
|
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This interface is used to provide {@link IMedia} implementations for {@link ItemStack}.
|
* This interface is used to provide {@link IMedia} implementations for {@link ItemStack}.
|
||||||
|
@@ -0,0 +1,46 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2025 The CC: Tweaked Developers
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
package dan200.computercraft.api.media;
|
||||||
|
|
||||||
|
import dan200.computercraft.impl.ComputerCraftAPIService;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The contents of a page (or book) created by a ComputerCraft printer.
|
||||||
|
*
|
||||||
|
* @since 1.115
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public interface PrintoutContents {
|
||||||
|
/**
|
||||||
|
* Get the (possibly empty) title for this printout.
|
||||||
|
*
|
||||||
|
* @return The title of this printout.
|
||||||
|
*/
|
||||||
|
String getTitle();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the text contents of this printout, as a sequence of lines.
|
||||||
|
* <p>
|
||||||
|
* The lines in the printout may include blank lines at the end of the document, as well as trailing spaces on each
|
||||||
|
* line.
|
||||||
|
*
|
||||||
|
* @return The text contents of this printout.
|
||||||
|
*/
|
||||||
|
Stream<String> getTextLines();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the printout contents for a particular stack.
|
||||||
|
*
|
||||||
|
* @param stack The stack to get the contents for.
|
||||||
|
* @return The printout contents, or {@code null} if this is not a printout item.
|
||||||
|
*/
|
||||||
|
static @Nullable PrintoutContents get(ItemStack stack) {
|
||||||
|
return ComputerCraftAPIService.get().getPrintoutContents(stack);
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user